mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
Moving to modules. Structural changes.
This commit is contained in:
parent
3903bc1766
commit
060d4c6d1e
258 changed files with 621 additions and 407 deletions
1
config/hosts/athame/home/default.nix
Normal file
1
config/hosts/athame/home/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ... }: { imports = [ ./weechat.nix ]; }
|
||||
5
config/hosts/athame/home/weechat.nix
Normal file
5
config/hosts/athame/home/weechat.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
programs.weechat = { enable = true; };
|
||||
}
|
||||
120
config/hosts/athame/meta.nix
Normal file
120
config/hosts/athame/meta.nix
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
{ lib, config, ... }: with lib; {
|
||||
config = {
|
||||
deploy.targets.infra = {
|
||||
tf = {
|
||||
resources.hcloud_ssh_key = {
|
||||
provider = "hcloud";
|
||||
type = "ssh_key";
|
||||
inputs = {
|
||||
name = "yubikey";
|
||||
public_key =
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCocjQqiDIvzq+Qu3jkf7FXw5piwtvZ1Mihw9cVjdVcsra3U2c9WYtYrA3rS50N3p00oUqQm9z1KUrvHzdE+03ZCrvaGdrtYVsaeoCuuvw7qxTQRbItTAEsfRcZLQ5c1v/57HNYNEsjVrt8VukMPRXWgl+lmzh37dd9w45cCY1QPi+JXQQ/4i9Vc3aWSe4X6PHOEMSBHxepnxm5VNHm4PObGcVbjBf0OkunMeztd1YYA9sEPyEK3b8IHxDl34e5t6NDLCIDz0N/UgzCxSxoz+YJ0feQuZtud/YLkuQcMxW2dSGvnJ0nYy7SA5DkW1oqcy6CGDndHl5StOlJ1IF9aGh0gGkx5SRrV7HOGvapR60RphKrR5zQbFFka99kvSQgOZqSB3CGDEQGHv8dXKXIFlzX78jjWDOBT67vA/M9BK9FS2iNnBF5x6shJ9SU5IK4ySxq8qvN7Us8emkN3pyO8yqgsSOzzJT1JmWUAx0tZWG/BwKcFBHfceAPQl6pwxx28TM3BTBRYdzPJLTkAy48y6iXW6UYdfAPlShy79IYjQtEThTuIiEzdzgYdros0x3PDniuAP0KOKMgbikr0gRa6zahPjf0qqBnHeLB6nHAfaVzI0aNbhOg2bdOueE1FX0x48sjKqjOpjlIfq4WeZp9REr2YHEsoLFOBfgId5P3BPtpBQ== cardno:000612078454";
|
||||
};
|
||||
};
|
||||
resources.athame = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "athame.kittywit.ch";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
network.nodes.athame = {
|
||||
imports = lib.hostImport "athame";
|
||||
networking = {
|
||||
hostName = "athame";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
# For the eventual migration
|
||||
|
||||
#resources.athame = {
|
||||
#provider = "hcloud";
|
||||
# type = "server";
|
||||
# inputs = {
|
||||
# name = "athame";
|
||||
# image = "ubuntu-20.04";
|
||||
# server_type = "cpx21";
|
||||
# location = "nbg1";
|
||||
# backups = false;
|
||||
# ssh_keys = [ (hcloud_ssh_key.refAttr "id") ];
|
||||
# };
|
||||
# connection = { host = config.lib.tf.terraformSelf "ipv4_address"; };
|
||||
# provisioners = [
|
||||
# {
|
||||
# file = {
|
||||
# destination = "/tmp/sshportfix.nix";
|
||||
# content = "{ config, ...}: { services.openssh.ports = [ 62954 ]; }";
|
||||
# };
|
||||
# }
|
||||
# {
|
||||
# remote-exec.command =
|
||||
# "curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | NIXOS_IMPORT=/tmp/sshportfix.nix NO_REBOOT=true PROVIDER=hetznercloud NIX_CHANNEL=nixos-20.09 bash 2>&1 | tee /tmp/infect.log";
|
||||
# }
|
||||
# {
|
||||
# remote-exec.command = "reboot";
|
||||
# onFailure = "continue";
|
||||
# }
|
||||
# ];
|
||||
#};
|
||||
|
||||
/* resources.athame_rdns = {
|
||||
provider = "hcloud";
|
||||
type = "rdns";
|
||||
inputs = {
|
||||
server_id = athame.refAttr "id";
|
||||
dns_ptr = "athame.kittywit.ch";
|
||||
ip_address = athame.refAttr "ipv4_address";
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
#dns.records.kittywitch_athame = {
|
||||
# tld = "kittywit.ch.";
|
||||
# domain = "athame";
|
||||
# a.address = athame.refAttr "ipv4_address";
|
||||
#};
|
||||
|
||||
#dns.records.kittywitch_root = {
|
||||
# tld = "kittywit.ch.";
|
||||
# domain = "@";
|
||||
# a.address = athame.refAttr "ipv4_address";
|
||||
#};
|
||||
|
||||
#dns.records.kittywitch_athame_v6 = {
|
||||
# tld = "kittywit.ch.";
|
||||
# domain = "athame";
|
||||
# aaaa.address = athame.refAttr "ipv6_address";
|
||||
#};
|
||||
|
||||
#dns.records.kittywitch_root_v6 = {
|
||||
# tld = "kittywit.ch.";
|
||||
# domain = "@";
|
||||
# aaaa.address = athame.refAttr "ipv6_address";
|
||||
#};
|
||||
|
||||
#dns.records.kittywitch_www = {
|
||||
# tld = "kittywit.ch.";
|
||||
# domain = "www";
|
||||
# cname.target = "athame.kittywit.ch.";
|
||||
#};
|
||||
|
||||
# connection = {
|
||||
# host = athame.refAttr "ipv4_address";
|
||||
# port = 62954;
|
||||
# };
|
||||
|
||||
#triggers.switch = lib.mapAttrs (name: record:
|
||||
# {
|
||||
# A = config.lib.tf.terraformExpr
|
||||
# ''join(",", ${record.out.resource.namedRef}.addresses)'';
|
||||
# AAAA = config.lib.tf.terraformExpr
|
||||
# ''join(",", ${record.out.resource.namedRef}.addresses)'';
|
||||
# CNAME = record.out.resource.refAttr "cname";
|
||||
# SRV = record.out.resource.refAttr "id";
|
||||
# }.${record.out.type}) config.dns.records;
|
||||
|
||||
79
config/hosts/athame/nixos/default.nix
Normal file
79
config/hosts/athame/nixos/default.nix
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
{ config, users, lib, pkgs, profiles, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hw.nix
|
||||
# profiles
|
||||
users.kat.server
|
||||
# host-specific services
|
||||
./virtualhosts.nix
|
||||
# services
|
||||
../../../services/fail2ban.nix
|
||||
../../../services/logrotate.nix
|
||||
../../../services/postgres.nix
|
||||
../../../services/nginx.nix
|
||||
../../../services/mail.nix
|
||||
../../../services/calendar.nix
|
||||
../../../services/xmpp.nix
|
||||
../../../services/gitea
|
||||
../../../services/syncplay.nix
|
||||
../../../services/weechat.nix
|
||||
../../../services/vaultwarden.nix
|
||||
../../../services/taskserver.nix
|
||||
../../../services/murmur.nix
|
||||
../../../services/matrix.nix
|
||||
../../../services/restic.nix
|
||||
../../../services/grafana.nix
|
||||
../../../services/prometheus.nix
|
||||
../../../services/loki.nix
|
||||
../../../services/node-exporter.nix
|
||||
../../../services/promtail.nix
|
||||
../../../services/netdata.nix
|
||||
../../../services/znc.nix
|
||||
../../../services/asterisk.nix
|
||||
];
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
|
||||
networking = {
|
||||
hostName = "athame";
|
||||
domain = "kittywit.ch";
|
||||
hostId = "7b0ac74e";
|
||||
useDHCP = false;
|
||||
interfaces.enp1s0.useDHCP = true;
|
||||
};
|
||||
|
||||
networking.interfaces.enp1s0.ipv6.addresses = [{
|
||||
address = "2a01:4f8:c2c:b7a8::1";
|
||||
prefixLength = 64;
|
||||
}];
|
||||
|
||||
networking.defaultGateway6 = {
|
||||
address = "fe80::1";
|
||||
interface = "enp1s0";
|
||||
};
|
||||
|
||||
kw.fw.public.interfaces = singleton "enp1s0";
|
||||
kw.fw.private.interfaces = singleton "hexnet";
|
||||
|
||||
kw.fw.public.tcp.ports = singleton 52969;
|
||||
|
||||
deploy.tf.dns.records.kittywitch_athame_v6 = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "athame";
|
||||
aaaa.address =
|
||||
(lib.head config.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
};
|
||||
|
||||
hexchen.network = {
|
||||
enable = true;
|
||||
pubkey = "55e3f29c252d16e73ac849a6039824f94df1dee670c030b9e29f90584f935575";
|
||||
listen.enable = true;
|
||||
listen.endpoints = [ "tcp://168.119.126.111:52969" ];
|
||||
};
|
||||
system.stateVersion = "20.09";
|
||||
}
|
||||
|
||||
10
config/hosts/athame/nixos/hw.nix
Normal file
10
config/hosts/athame/nixos/hw.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ sources, ... }: {
|
||||
imports = [ (sources.nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") ];
|
||||
boot.initrd.availableKernelModules =
|
||||
[ "ata_piix" "uhci_hcd" "virtio_pci" "sd_mod" "sr_mod" ];
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
fileSystems."/" = {
|
||||
device = "/dev/sda1";
|
||||
fsType = "ext4";
|
||||
};
|
||||
}
|
||||
23
config/hosts/athame/nixos/virtualhosts.nix
Normal file
23
config/hosts/athame/nixos/virtualhosts.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
common = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
services.nginx.virtualHosts = {
|
||||
"kittywit.ch" = { root = pkgs.kat-website; } // common;
|
||||
"athame.kittywit.ch" = { root = "/var/www/athame"; } // common;
|
||||
"files.kittywit.ch" = { root = "/var/www/files"; } // common;
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_files = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "files";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
48
config/hosts/dummy/nixos/default.nix
Normal file
48
config/hosts/dummy/nixos/default.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{ config, lib, pkgs, sources, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
hexchen = (import sources.hexchen) { };
|
||||
hexYgg = filterAttrs (_: c: c.enable)
|
||||
(mapAttrs (_: host: host.config.hexchen.network) hexchen.hosts);
|
||||
in
|
||||
{
|
||||
# stuff so dummy host is buildable (you probably don't want/need this???)
|
||||
# but idk your config sooooo
|
||||
boot.isContainer = true;
|
||||
networking.useDHCP = false;
|
||||
users.users.root.hashedPassword = "";
|
||||
|
||||
hexchen.network = {
|
||||
enable = true;
|
||||
pubkey = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
listen.enable = true;
|
||||
listen.endpoints = flatten (map (c: c.listen.endpoints) (filter
|
||||
(c:
|
||||
c.listen.enable && (c.pubkey
|
||||
!= "0000000000000000000000000000000000000000000000000000000000000000"))
|
||||
(attrValues hexYgg)));
|
||||
extra.pubkeys = {
|
||||
satorin =
|
||||
"53d99a74a648ff7bd5bc9ba68ef4f472fb4fb8b2e26dfecea33c781f0d5c9525";
|
||||
shanghai =
|
||||
"0cc3c26366cbfddfb1534b25c5655733d8f429edc941bcce674c46566fc87027";
|
||||
grimoire =
|
||||
"2a1567a2848540070328c9e938c58d40f2b1a3f08982c15c7edc5dcabfde3330";
|
||||
boline =
|
||||
"89684441745467da0d1bf7f47dc74ec3ca65e05c72f752298ef3c22a22024d43";
|
||||
} // (mapAttrs (_: c: c.pubkey) hexYgg);
|
||||
};
|
||||
|
||||
# snippet for single host
|
||||
# hexchen.network = {
|
||||
# enable = true;
|
||||
# pubkey = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
# # if server, enable this and set endpoint:
|
||||
# listen.enable = false;
|
||||
# listen.endpoints = [
|
||||
# "tcp://0.0.0.0:0"
|
||||
# ];
|
||||
# };
|
||||
}
|
||||
1
config/hosts/mabon/home/default.nix
Normal file
1
config/hosts/mabon/home/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ... }: { }
|
||||
0
config/hosts/mabon/meta.nix
Normal file
0
config/hosts/mabon/meta.nix
Normal file
29
config/hosts/mabon/nixos/default.nix
Normal file
29
config/hosts/mabon/nixos/default.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{ config, users, pkgs, profiles, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hw.nix
|
||||
profiles.gui
|
||||
profiles.fvwm
|
||||
profiles.laptop
|
||||
users.kairi.guiFull
|
||||
];
|
||||
|
||||
networking.wireless.interfaces = [ "wlp3s0" ];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages;
|
||||
boot.kernelModules = [ "wl" ];
|
||||
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
|
||||
|
||||
networking.hostId = "d199ad70";
|
||||
networking.hostName = "mabon";
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.enp1s0.useDHCP = false;
|
||||
networking.interfaces.wlp2s0.useDHCP = true;
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
||||
38
config/hosts/mabon/nixos/hw.nix
Normal file
38
config/hosts/mabon/nixos/hw.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"uhci_hcd"
|
||||
"ehci_pci"
|
||||
"ahci"
|
||||
"firewire_ohci"
|
||||
"usbhid"
|
||||
"usb_storage"
|
||||
"sd_mod"
|
||||
"sr_mod"
|
||||
"sdhci_pci"
|
||||
];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" "wl" ];
|
||||
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/236f9363-19ee-46e3-8db4-5dd1e28b742d";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
boot.initrd.luks.devices."cryptroot".device =
|
||||
"/dev/disk/by-uuid/b0435b6c-fd76-44d0-8b63-2c2c059df814";
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/84FB-4F88";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[{ device = "/dev/disk/by-uuid/926c41d6-c06a-4dcc-b55d-f4cfaafe4bac"; }];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
}
|
||||
12
config/hosts/mabon/tf.nix
Normal file
12
config/hosts/mabon/tf.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ config, hosts, ... }: {
|
||||
config = {
|
||||
resources.mabon = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "192.168.1.119";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
1
config/hosts/ostara/home/default.nix
Normal file
1
config/hosts/ostara/home/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ... }: { }
|
||||
22
config/hosts/ostara/meta.nix
Normal file
22
config/hosts/ostara/meta.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{ lib, config, ... }: with lib; {
|
||||
config = {
|
||||
deploy.targets.personal = {
|
||||
tf = {
|
||||
resources.ostara = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "192.168.1.245";
|
||||
};
|
||||
};
|
||||
};
|
||||
network.nodes.samhain = {
|
||||
imports = lib.hostImport "samhain";
|
||||
networking = {
|
||||
hostName = "samhain";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
58
config/hosts/ostara/nixos/default.nix
Normal file
58
config/hosts/ostara/nixos/default.nix
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{ lib, config, users, pkgs, profiles, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ ./hw.nix profiles.laptop ];
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
|
||||
networking.hostId = "9f89b327";
|
||||
networking.hostName = "ostara";
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.enp1s0.useDHCP = true;
|
||||
networking.interfaces.wlp2s0.useDHCP = true;
|
||||
|
||||
kw.fw.public.interfaces = singleton "wlp2s0";
|
||||
|
||||
kw.fw.public.tcp.ports = [ 9981 9982 ];
|
||||
|
||||
hardware.firmware = [ pkgs.libreelec-dvb-firmware ];
|
||||
|
||||
services.tvheadend.enable = true;
|
||||
|
||||
systemd.services.tvheadend.enable = lib.mkForce false;
|
||||
|
||||
systemd.services.tvheadend-kat = {
|
||||
description = "Tvheadend TV streaming server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
script = ''
|
||||
${pkgs.tvheadend}/bin/tvheadend \
|
||||
--http_root /tvheadend \
|
||||
--http_port 9981 \
|
||||
--htsp_port 9982 \
|
||||
-f \
|
||||
-C \
|
||||
-p ${config.users.users.tvheadend.home}/tvheadend.pid \
|
||||
-u tvheadend \
|
||||
-g video
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
PIDFile = "${config.users.users.tvheadend.home}/tvheadend.pid";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
User = "tvheadend";
|
||||
Group = "video";
|
||||
|
||||
ExecStop = "${pkgs.coreutils}/bin/rm ${config.users.users.tvheadend.home}/tvheadend.pid";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
||||
20
config/hosts/ostara/nixos/hw.nix
Normal file
20
config/hosts/ostara/nixos/hw.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules =
|
||||
[ "uhci_hcd" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/469a684b-eb8f-48a8-8f98-be58528312c4";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[{ device = "/dev/disk/by-uuid/2223e305-79c9-45b3-90d7-560dcc45775a"; }];
|
||||
|
||||
}
|
||||
12
config/hosts/ostara/tf.nix
Normal file
12
config/hosts/ostara/tf.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ config, hosts, ... }: {
|
||||
config = {
|
||||
resources.ostara = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "192.168.1.245";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
1
config/hosts/samhain/home/default.nix
Normal file
1
config/hosts/samhain/home/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ... }: { imports = [ ./sway ]; }
|
||||
79
config/hosts/samhain/home/sway/default.nix
Normal file
79
config/hosts/samhain/home/sway/default.nix
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./swayidle.nix ];
|
||||
|
||||
wayland.windowManager.sway = {
|
||||
config =
|
||||
let
|
||||
lockCommand = "swaylock -i HDMI-A-1:${../../../../users/kat/sway/wallpapers/main.png} -i DP-1:${
|
||||
../../../../users/kat/sway/wallpapers/left.jpg
|
||||
} -i DVI-D-1:${../../../../users/kat/sway/wallpapers/right.jpg} -s fill";
|
||||
cfg = config.wayland.windowManager.sway.config;
|
||||
in
|
||||
{
|
||||
#startup = [{ command = "${pkgs.ckb-next}/bin/ckb-next -b"; }];
|
||||
|
||||
output =
|
||||
let
|
||||
left = {
|
||||
res = "1920x1080";
|
||||
pos = "0 0";
|
||||
};
|
||||
middle = {
|
||||
res = "1920x1200";
|
||||
pos = "1920 0";
|
||||
};
|
||||
right = {
|
||||
res = "1920x1080";
|
||||
pos = "3840 0";
|
||||
};
|
||||
in
|
||||
{
|
||||
"DP-1" = left;
|
||||
"DVI-D-1" = middle;
|
||||
"HDMI-A-1" = right;
|
||||
};
|
||||
|
||||
keybindings = {
|
||||
"${cfg.modifier}+x" = "exec ${lockCommand}";
|
||||
};
|
||||
|
||||
modes = {
|
||||
"System (l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown" =
|
||||
{
|
||||
"l" = "exec ${lockCommand}, mode default";
|
||||
"e" = "exec swaymsg exit, mode default";
|
||||
"s" = "exec systemctl suspend, mode default";
|
||||
"h" = "exec systemctl hibernate, mode default";
|
||||
"r" = "exec systemctl reboot, mode default";
|
||||
"Shift+s" = "exec systemctl shutdown, mode default";
|
||||
"Return" = "mode default";
|
||||
"Escape" = "mode default";
|
||||
};
|
||||
};
|
||||
|
||||
input = {
|
||||
"5824:1503:screenstub-tablet" = { events = "disabled"; };
|
||||
"5824:1503:screenstub-mouse" = { events = "disabled"; };
|
||||
"5824:1503:screenstub-kbd" = { events = "disabled"; };
|
||||
"1386:215:Wacom_BambooPT_2FG_Small_Pen" = {
|
||||
map_to_output = "HDMI-A-1";
|
||||
};
|
||||
"1386:215:Wacom_BambooPT_2FG_Small_Finger" = {
|
||||
natural_scroll = "enabled";
|
||||
middle_emulation = "enabled";
|
||||
tap = "enabled";
|
||||
dwt = "enabled";
|
||||
accel_profile = "flat";
|
||||
pointer_accel = "0.05";
|
||||
};
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
workspace "1" output "DP-1"
|
||||
workspace "11:F1" output "DVI-1"
|
||||
workspace "12:F2" output "HDMI-A-1"
|
||||
'';
|
||||
};
|
||||
}
|
||||
32
config/hosts/samhain/home/sway/swayidle.nix
Normal file
32
config/hosts/samhain/home/sway/swayidle.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
systemd.user.services.swayidle = {
|
||||
Unit = {
|
||||
Description = "swayidle";
|
||||
Documentation = [ "man:swayidle(1)" ];
|
||||
PartOf = [ "graphical-session.target" ];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = ''
|
||||
${pkgs.swayidle}/bin/swayidle -w \
|
||||
timeout 300 '${pkgs.swaylock}/bin/swaylock -f -i HDMI-A-1:${
|
||||
../../../../users/kat/sway/wallpapers/main.png
|
||||
} -i DP-1:${../../../../users/kat/sway/wallpapers/left.jpg} -i DVI-D-1:${
|
||||
../../../../users/kat/sway/wallpapers/right.jpg
|
||||
}' \
|
||||
timeout 600 'swaymsg "output * dpms off"' \
|
||||
resume 'swaymsg "output * dpms on"' \
|
||||
before-sleep '${pkgs.swaylock}/bin/swaylock -f -i HDMI-A-1:${
|
||||
../../../../users/kat/sway/wallpapers/main.png
|
||||
} -i DP-1:${../../../../users/kat/sway/wallpapers/left.jpg} -i DVI-D-1:${
|
||||
../../../../users/kat/sway/wallpapers/right.jpg
|
||||
}'
|
||||
'';
|
||||
RestartSec = 3;
|
||||
Restart = "always";
|
||||
};
|
||||
Install = { WantedBy = [ "sway-session.target" ]; };
|
||||
};
|
||||
}
|
||||
22
config/hosts/samhain/meta.nix
Normal file
22
config/hosts/samhain/meta.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{ lib, config, ... }: with lib; {
|
||||
config = {
|
||||
deploy.targets.personal = {
|
||||
tf = {
|
||||
resources.samhain = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "192.168.1.135";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
network.nodes.samhain = {
|
||||
imports = lib.hostImport "samhain";
|
||||
networking = {
|
||||
hostName = "samhain";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
142
config/hosts/samhain/nixos/default.nix
Normal file
142
config/hosts/samhain/nixos/default.nix
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
{ tf, config, users, pkgs, lib, profiles, sources, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
hexchen = (import sources.hexchen) { };
|
||||
hexYgg = filterAttrs (_: c: c.enable)
|
||||
(mapAttrs (_: host: host.config.hexchen.network) hexchen.hosts);
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./hw.nix
|
||||
profiles.gui
|
||||
profiles.sway
|
||||
users.kat.guiFull
|
||||
../../../services/zfs.nix
|
||||
../../../services/restic.nix
|
||||
../../../services/nginx.nix
|
||||
../../../services/node-exporter.nix
|
||||
../../../services/promtail.nix
|
||||
../../../services/netdata.nix
|
||||
./transmission.nix
|
||||
./jellyfin.nix
|
||||
./virtualhosts.nix
|
||||
];
|
||||
|
||||
home-manager.users.kat = {
|
||||
imports = [
|
||||
../home
|
||||
];
|
||||
};
|
||||
|
||||
deploy.tf.variables.dyn_username = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/hexdns-dynamic -f username";
|
||||
};
|
||||
|
||||
deploy.tf.variables.dyn_password = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/hexdns-dynamic -f password";
|
||||
};
|
||||
|
||||
deploy.tf.variables.dyn_hostname = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/hexdns-dynamic -f hostname";
|
||||
};
|
||||
|
||||
security.acme.certs."samhain.net.kittywit.ch" = {
|
||||
domain = "samhain.net.kittywit.ch";
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
group = "nginx";
|
||||
};
|
||||
|
||||
secrets.files.kat-glauca-dns = {
|
||||
text = ''
|
||||
user="${tf.variables.dyn_username.ref}"
|
||||
pass="${tf.variables.dyn_password.ref}"
|
||||
hostname="${tf.variables.dyn_hostname.ref}"
|
||||
'';
|
||||
owner = "kat";
|
||||
group = "users";
|
||||
};
|
||||
|
||||
systemd.services.kat-glauca-dns = {
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.kat-glauca-dns}/bin/kat-glauca-dns";
|
||||
};
|
||||
environment = { passFile = config.secrets.files.kat-glauca-dns.path; };
|
||||
wantedBy = [ "default.target" ];
|
||||
};
|
||||
|
||||
#hardware.ckb-next = {
|
||||
# enable = true;
|
||||
# package = pkgs.ckb-next;
|
||||
#};
|
||||
|
||||
kw.fw.private.interfaces = singleton "hexnet";
|
||||
kw.fw.public.interfaces = singleton "br";
|
||||
|
||||
hardware.openrazer = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
kw.fw.private.tcp.ports = [ 10445 ];
|
||||
|
||||
systemd.timers.kat-glauca-dns = {
|
||||
timerConfig = {
|
||||
Unit = "kat-glauca-dns.service";
|
||||
OnBootSec = "5m";
|
||||
OnUnitActiveSec = "30m";
|
||||
};
|
||||
wantedBy = [ "default.target" ];
|
||||
};
|
||||
|
||||
# graphics tablet
|
||||
services.xserver.wacom.enable = true;
|
||||
|
||||
environment.systemPackages = [ pkgs.stepmania pkgs.screenstub ];
|
||||
|
||||
# other stuffs
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.supportedFilesystems = [ "zfs" "xfs" ];
|
||||
networking.hostName = "samhain";
|
||||
networking.hostId = "617050fc";
|
||||
networking.useDHCP = false;
|
||||
networking.useNetworkd = true;
|
||||
networking.firewall.allowPing = true;
|
||||
|
||||
systemd.network = {
|
||||
networks.enp34s0 = {
|
||||
matchConfig.Name = "enp34s0";
|
||||
bridge = singleton "br";
|
||||
};
|
||||
networks.br = {
|
||||
matchConfig.Name = "br";
|
||||
address = [ "192.168.1.135/24" ];
|
||||
gateway = [ "192.168.1.254" ];
|
||||
};
|
||||
netdevs.br = {
|
||||
netdevConfig = {
|
||||
Name = "br";
|
||||
Kind = "bridge";
|
||||
MACAddress = "00:d8:61:c7:f4:9d";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.avahi.enable = true;
|
||||
|
||||
hexchen.network = {
|
||||
enable = true;
|
||||
pubkey = "a7110d0a1dc9ec963d6eb37bb6922838b8088b53932eae727a9136482ce45d47";
|
||||
# if server, enable this and set endpoint:
|
||||
listen.enable = false;
|
||||
listen.endpoints = [ "tcp://0.0.0.0:0" ];
|
||||
};
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
||||
|
||||
51
config/hosts/samhain/nixos/hw.nix
Normal file
51
config/hosts/samhain/nixos/hw.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" "nct6775" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "rpool/safe/root";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nix" = {
|
||||
device = "rpool/local/nix";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home" = {
|
||||
device = "rpool/safe/home";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-uuid/AED6-D0D1";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
fileSystems."/mnt/zraw" = {
|
||||
device = "zstore/raw";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/mnt/zcomp" = {
|
||||
device = "zstore/compress";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/mnt/zenc" = {
|
||||
device = "zstore/protect";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/disk/by-uuid/89831a0f-93e6-4d30-85e4-09061259f140"; }
|
||||
{ device = "/dev/disk/by-uuid/8f944315-fe1c-4095-90ce-50af03dd5e3f"; }
|
||||
];
|
||||
|
||||
}
|
||||
15
config/hosts/samhain/nixos/jellyfin.nix
Normal file
15
config/hosts/samhain/nixos/jellyfin.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ranges = [{
|
||||
from = 32768;
|
||||
to = 60999;
|
||||
}];
|
||||
|
||||
kw.fw.private.tcp.ranges = [{
|
||||
from = 32768;
|
||||
to = 60999;
|
||||
}];
|
||||
|
||||
services.jellyfin.enable = true;
|
||||
}
|
||||
39
config/hosts/samhain/nixos/thermal/default.nix
Normal file
39
config/hosts/samhain/nixos/thermal/default.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
boot.kernelParams = [ "amdgpu.ppfeaturemask=0xffffffff" ];
|
||||
powerManagement = {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "conservative";
|
||||
};
|
||||
systemd = {
|
||||
services = {
|
||||
kaede-thermals = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.bash pkgs.coreutils-full pkgs.gawk ];
|
||||
serviceConfig = {
|
||||
RemainAfterExit = "no";
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.runtimeShell} ${./kaede-thermals.sh} start";
|
||||
ExecStop = "${pkgs.runtimeShell} ${./kaede-thermals.sh} stop";
|
||||
User = "root";
|
||||
};
|
||||
};
|
||||
kaede-power = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.bash pkgs.linuxPackages.cpupower ];
|
||||
serviceConfig = {
|
||||
RemainAfterExit = "yes";
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.runtimeShell} ${./kaede-power.sh} start";
|
||||
ExecStop = "${pkgs.runtimeShell} ${./kaede-power.sh} stop";
|
||||
User = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
services.thermald = {
|
||||
enable = true;
|
||||
configFile = "${./kaede-thermald.xml}";
|
||||
};
|
||||
}
|
||||
65
config/hosts/samhain/nixos/thermal/kaede-power.sh
Normal file
65
config/hosts/samhain/nixos/thermal/kaede-power.sh
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env bash
|
||||
################################################################################
|
||||
# Written by Kaede Fox <kaede@boxedfox.org>
|
||||
|
||||
##########
|
||||
# Default governor, currently required to be "conservative".
|
||||
METHOD=conservative
|
||||
|
||||
# Configuration parameters.
|
||||
SCALE_UP=40
|
||||
SCALE_DOWN=30
|
||||
SCALE_STEP=1
|
||||
SAMPLING_RATE=10000
|
||||
SAMPLING_FACTOR=10
|
||||
NO_NICE=1
|
||||
|
||||
##########
|
||||
script_name=`basename $0`
|
||||
|
||||
case "$1" in
|
||||
"start")
|
||||
modprobe cpufreq_conservative
|
||||
modprobe cpufreq_ondemand
|
||||
|
||||
# This also needs to be loaded, in case the service is stopped later
|
||||
# we can fall back to it.
|
||||
modprobe cpufreq_performance
|
||||
|
||||
# The governor must be selected for its relevant configuration entries
|
||||
# to appear in sysfs.
|
||||
cpupower frequency-set -g $METHOD
|
||||
sleep .5s
|
||||
|
||||
CONFIG=/sys/devices/system/cpu/cpufreq/$METHOD
|
||||
chmod $CONFIG 644
|
||||
echo $SCALE_UP > $CONFIG/up_threshold
|
||||
echo $SCALE_DOWN > $CONFIG/down_threshold
|
||||
echo $SCALE_STEP > $CONFIG/freq_step
|
||||
echo $SAMPLING_RATE > $CONFIG/sampling_rate
|
||||
echo $SAMPLING_FACTOR > $CONFIG/sampling_down_factor
|
||||
echo $NO_NICE > $CONFIG/ignore_nice_load
|
||||
sleep .5s
|
||||
|
||||
# Force reload all configuration.
|
||||
cpupower frequency-set -g $METHOD
|
||||
echo "enabled cpupower"
|
||||
|
||||
echo "loaded ${script_name}"
|
||||
;;
|
||||
"stop")
|
||||
cpupower frequency-set -g performance &&
|
||||
echo "disabled cpupower" &
|
||||
wait
|
||||
|
||||
sleep .5s
|
||||
modprobe -r cpufreq_conservative
|
||||
modprobe -r cpufreq_ondemand
|
||||
|
||||
echo "unloaded ${script_name}"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ${script_name} (start | stop)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
308
config/hosts/samhain/nixos/thermal/kaede-thermald.xml
Normal file
308
config/hosts/samhain/nixos/thermal/kaede-thermald.xml
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
use "man thermal-conf.xml" for details
|
||||
-->
|
||||
|
||||
<!-- BEGIN -->
|
||||
<ThermalConfiguration>
|
||||
<Platform>
|
||||
<Name>AMD Ryzen 5 3600 6-Core Processor</Name>
|
||||
<ProductName>*</ProductName>
|
||||
<UUID>*</UUID>
|
||||
<Preference>quiet</Preference>
|
||||
<ThermalSensors>
|
||||
<ThermalSensor>
|
||||
<!--CPU sensor on die -->
|
||||
<Type>CPU_TEMP_CORE</Type>
|
||||
<Path>/var/cache/kaede-thermals/cpu_core_temp</Path>
|
||||
<AsyncCapable>1</AsyncCapable>
|
||||
</ThermalSensor>
|
||||
<ThermalSensor>
|
||||
<!-- GPU sensor -->
|
||||
<Type>GPU_TEMP</Type>
|
||||
<Path>/var/cache/kaede-thermals/gpu_temp</Path>
|
||||
<AsyncCapable>1</AsyncCapable>
|
||||
</ThermalSensor>
|
||||
</ThermalSensors>
|
||||
<ThermalZones>
|
||||
<ThermalZone>
|
||||
<Type>CPU_CTRL</Type>
|
||||
<TripPoints>
|
||||
<!-- CPU PASSIVE CONTROL -->
|
||||
<!-- Ideal temp: 70-75*C, Max temp: 95*C -->
|
||||
<TripPoint>
|
||||
<SensorType>CPU_TEMP_CORE</SensorType>
|
||||
<Temperature>65000</Temperature>
|
||||
<Type>passive</Type>
|
||||
<ControlType>parallel</ControlType>
|
||||
<CoolingDevice>
|
||||
<index>1</index>
|
||||
<type>CPU_FREQ0</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>2</index>
|
||||
<type>CPU_FREQ1</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>3</index>
|
||||
<type>CPU_FREQ2</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>4</index>
|
||||
<type>CPU_FREQ3</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>5</index>
|
||||
<type>CPU_FREQ4</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>6</index>
|
||||
<type>CPU_FREQ5</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>7</index>
|
||||
<type>CPU_FREQ6</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>8</index>
|
||||
<type>CPU_FREQ7</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>9</index>
|
||||
<type>CPU_FREQ8</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>10</index>
|
||||
<type>CPU_FREQ9</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>11</index>
|
||||
<type>CPU_FREQ10</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>12</index>
|
||||
<type>CPU_FREQ11</type>
|
||||
<influence>100</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
</TripPoint>
|
||||
<!-- EMERGENCY THROTTLING. -->
|
||||
<!-- HOT means suspend the system. -->
|
||||
<!-- CRITICAL means turn off the system. -->
|
||||
<TripPoint>
|
||||
<SensorType>CPU_TEMP_CORE</SensorType>
|
||||
<Temperature>85000</Temperature>
|
||||
<Type>hot</Type>
|
||||
</TripPoint>
|
||||
<TripPoint>
|
||||
<SensorType>CPU_TEMP_CORE</SensorType>
|
||||
<Temperature>90000</Temperature>
|
||||
<Type>critical</Type>
|
||||
</TripPoint>
|
||||
</TripPoints>
|
||||
</ThermalZone>
|
||||
<ThermalZone>
|
||||
<Type>GPU_CTRL</Type>
|
||||
<TripPoints>
|
||||
<!-- GPU PASSIVE CONTROL -->
|
||||
<!-- Ideal temp: 70-75*C, Max temp: 90*C -->
|
||||
<TripPoint>
|
||||
<SensorType>GPU_TEMP</SensorType>
|
||||
<Temperature>70000</Temperature>
|
||||
<Type>passive</Type>
|
||||
<ControlType>parallel</ControlType>
|
||||
<CoolingDevice>
|
||||
<index>1</index>
|
||||
<type>GPU_FREQ_CORE</type>
|
||||
<influence>50</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<index>2</index>
|
||||
<type>GPU_FREQ_MEM</type>
|
||||
<influence>50</influence>
|
||||
<SamplingPeriod>1</SamplingPeriod>
|
||||
</CoolingDevice>
|
||||
</TripPoint>
|
||||
</TripPoints>
|
||||
</ThermalZone>
|
||||
</ThermalZones>
|
||||
<CoolingDevices>
|
||||
<!-- CPU frequency scaling. -->
|
||||
<!-- This allows finer control of the CPU scaling in comparison to -->
|
||||
<!-- thermald's built in 'cpufreq' driver. -->
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ0</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ1</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ2</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ3</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ4</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ5</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu5/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ6</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu6/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ7</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu7/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ8</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu8/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ9</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu9/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ10</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu10/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>CPU_FREQ11</Type>
|
||||
<Path>/sys/devices/system/cpu/cpu7/cpufreq/scaling_max_freq</Path>
|
||||
<MinState>3600000</MinState>
|
||||
<MaxState>2200000</MaxState>
|
||||
<IncDecStep>-100000</IncDecStep>
|
||||
<ReadBack>1</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
</CoolingDevice>
|
||||
<!-- GPU frequency scaling. -->
|
||||
<!-- This is read by a custom service and translated into the format
|
||||
expected by the video driver. -->
|
||||
<CoolingDevice>
|
||||
<Type>GPU_FREQ_CORE</Type>
|
||||
<Path>/var/cache/kaede-thermals/gpu_power_core</Path>
|
||||
<MinState>255</MinState>
|
||||
<MaxState>0</MaxState>
|
||||
<IncDecStep>-5</IncDecStep>
|
||||
<!-- Make sure ReadBack is disabled as our servive needs to
|
||||
reset the value periodically. -->
|
||||
<ReadBack>0</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
<!-- As negative values are possible and have special meaning,
|
||||
leave room for the sign. -->
|
||||
<WritePrefix> </WritePrefix>
|
||||
</CoolingDevice>
|
||||
<CoolingDevice>
|
||||
<Type>GPU_FREQ_MEM</Type>
|
||||
<Path>/var/cache/kaede-thermals/gpu_power_mem</Path>
|
||||
<MinState>255</MinState>
|
||||
<MaxState>0</MaxState>
|
||||
<IncDecStep>-5</IncDecStep>
|
||||
<ReadBack>0</ReadBack>
|
||||
<AutoOffMode>1</AutoOffMode>
|
||||
<DebouncePeriod>10</DebouncePeriod>
|
||||
<WritePrefix> </WritePrefix>
|
||||
</CoolingDevice>
|
||||
</CoolingDevices>
|
||||
</Platform>
|
||||
</ThermalConfiguration>
|
||||
157
config/hosts/samhain/nixos/thermal/kaede-thermals.sh
Normal file
157
config/hosts/samhain/nixos/thermal/kaede-thermals.sh
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env bash
|
||||
################################################################################
|
||||
# Written by Kaede Fox <kaede@boxedfox.org>
|
||||
|
||||
##########
|
||||
# thermald can't handle hwmon* moving around, so we use symlinks to resolve
|
||||
# dynamic paths to static paths.
|
||||
THERMAL_PATH="/var/cache/kaede-thermals"
|
||||
|
||||
# CPU sensor paths.
|
||||
CPU_SENSOR_CORE="/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon*/temp1_input"
|
||||
#CPU_SENSOR_SOCKET="/sys/devices/platform/nct6775.656/hwmon/hwmon*/temp2_input"
|
||||
|
||||
# GPU control and sensor paths (using amdgpu).
|
||||
GPU_CONTROL="/sys/class/drm/card0/device/"
|
||||
GPU_SENSOR="/sys/class/drm/card0/device/hwmon/hwmon*/temp1_input"
|
||||
|
||||
# WARNING: MAKE ABSOLUTELY SURE THESE ARE THE PERFORMANCE STATES AND NOT THE
|
||||
# ACTUAL CORE/MEM CLOCKS OR WE COULD DAMAGE THE HARDWARE.
|
||||
GPUCTRL_CORECLK="${GPU_CONTROL}/pp_dpm_sclk"
|
||||
GPUCTRL_MEMCLK="${GPU_CONTROL}/pp_dpm_mclk"
|
||||
|
||||
# How often to resolve paths (in seconds). Changes are extremely rare, but they
|
||||
# can occur even while the system is booted.
|
||||
INTERVAL='300'
|
||||
# How often to update GPU power settings from thermald.
|
||||
TIMESLICE='1'
|
||||
|
||||
# Formatter used to round floats to integers via printf.
|
||||
float_to_int='%'\''.0f'
|
||||
|
||||
##########
|
||||
script_name=`basename $0`
|
||||
|
||||
# Our simple path resolver subroutine, which uses ls to replace hwmon* with
|
||||
# whichever hwmon is currently active.
|
||||
sub_resolve_paths() {
|
||||
ln -s -f "`ls $CPU_SENSOR_CORE`" "./cpu_core_temp"
|
||||
# ln -s -f "`ls $CPU_SENSOR_SOCKET`" "./cpu_socket_temp"
|
||||
ln -s -f "`ls $GPU_SENSOR`" "./gpu_temp"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"start")
|
||||
echo "loaded ${script_name}"
|
||||
|
||||
mkdir -p "$THERMAL_PATH" 2>/dev/null
|
||||
cd "$THERMAL_PATH"
|
||||
|
||||
# Switch the video driver into manual control mode for
|
||||
# performance levels.
|
||||
echo "manual" >${GPU_CONTROL}/power_dpm_force_performance_level
|
||||
echo "enabled gpupower"
|
||||
|
||||
# Immediately resolve paths at startup.
|
||||
sub_resolve_paths
|
||||
|
||||
# Followed by starting thermald in case the paths didn't
|
||||
# exist, which would've made it fail to start.
|
||||
sleep .5s
|
||||
systemctl start thermald
|
||||
|
||||
# thermald will create these files with the wrong permissions.
|
||||
rm "./gpu_power_core"; printf "%d\n" '-1'>./gpu_power_core
|
||||
rm "./gpu_power_mem"; printf "%d\n" '-1'>./gpu_power_mem
|
||||
|
||||
# Enter service mode.
|
||||
slice_counter='0'
|
||||
while true; do
|
||||
# Execute a timeslice. Paths are updated every time the
|
||||
# counter wraps around.
|
||||
slice_counter=$((slice_counter + TIMESLICE))
|
||||
if [ "$slice_counter" -ge "$INTERVAL" ]; then
|
||||
#printf "DEBUG: *** Updating paths after %d seconds ***\n" "$slice_counter"
|
||||
slice_counter=$((slice_counter - INTERVAL))
|
||||
|
||||
# Resolve paths.
|
||||
sub_resolve_paths
|
||||
fi
|
||||
|
||||
# Read GPU thermal settings from thermald and apply
|
||||
# them to the driver via sysfs.
|
||||
#
|
||||
# The core and memory clock lists are highly specific
|
||||
# to the hardware, and need updating if the video card
|
||||
# is ever changed.
|
||||
#
|
||||
gpu_power_core="`cat ./gpu_power_core`"
|
||||
gpu_power_mem="`cat ./gpu_power_mem`"
|
||||
if [ -z "$gpu_power_core" ]; then gpu_power_core='-1'; fi
|
||||
if [ -z "$gpu_power_mem" ]; then gpu_power_mem='-1'; fi
|
||||
|
||||
# Check if we need to update the core clock.
|
||||
if [ "$gpu_power_core" -ge '0' ]; then
|
||||
#printf "DEBUG: *** Updating GPU core clock ***\n"
|
||||
printf "%d\n" '-1'>./gpu_power_core
|
||||
printf "$gpu_power_core\n">./gpu_power_core_cached
|
||||
|
||||
core_count_f="$(echo "$gpu_power_core" | awk '{ x=(($1/255.0)*(7-1))+1; printf("%f",x) }')"
|
||||
core_count="$(printf "$float_to_int" "$core_count_f")"
|
||||
if [ "$core_count" -lt '1' ]; then core_count='1'; fi
|
||||
if [ "$core_count" -gt '7' ]; then core_count='7'; fi
|
||||
|
||||
gpu_list_core="1"
|
||||
for ((i=2; i<=core_count; i++)); do
|
||||
gpu_list_core="$gpu_list_core $i"; done
|
||||
|
||||
echo "$gpu_list_core" >${GPUCTRL_CORECLK}
|
||||
|
||||
#echo "dbg: gpu_power_core: $gpu_power_core"
|
||||
#echo "dbg: core_count_f: $core_count_f, core_count: $core_count"
|
||||
#echo "dbg: gpu_list_core: $gpu_list_core"
|
||||
fi
|
||||
|
||||
# Check if we need to update the memory clock.
|
||||
if [ "$gpu_power_mem" -ge '0' ]; then
|
||||
#printf "DEBUG: *** Updating GPU memory clock ***\n"
|
||||
printf "%d\n" '-1'>./gpu_power_mem
|
||||
printf "$gpu_power_mem\n">./gpu_power_mem_cached
|
||||
|
||||
mem_count_f="$(echo "$gpu_power_mem" | awk '{ x=(($1/255.0)*(3-1))+1; printf("%f",x) }')"
|
||||
mem_count="$(printf "$float_to_int" "$mem_count_f")"
|
||||
if [ "$mem_count" -lt '1' ]; then mem_count='1'; fi
|
||||
if [ "$mem_count" -gt '3' ]; then mem_count='3'; fi
|
||||
|
||||
gpu_list_mem="1"
|
||||
for ((i=2; i<=mem_count; i++)); do
|
||||
gpu_list_mem="$gpu_list_mem $i"; done
|
||||
|
||||
echo "$gpu_list_mem" >${GPUCTRL_MEMCLK}
|
||||
|
||||
#echo "dbg: gpu_power_mem: $gpu_power_mem"
|
||||
#echo "dbg: mem_count_f: $mem_count_f, mem_count: $mem_count"
|
||||
#echo "dbg: gpu_list_mem: $gpu_list_mem"
|
||||
fi
|
||||
|
||||
# Sleep until the next cycle.
|
||||
sleep "${TIMESLICE}s"
|
||||
done
|
||||
;;
|
||||
"stop")
|
||||
# Reset all performance level tunings.
|
||||
echo "1 2 3 4 5 6 7" >${GPUCTRL_CORECLK}
|
||||
echo "1 2 3" >${GPUCTRL_MEMCLK}
|
||||
# Switch the video driver into automatic control mode for
|
||||
# performance levels.
|
||||
echo "auto" >${GPU_CONTROL}/power_dpm_force_performance_level
|
||||
echo "disabled gpupower"
|
||||
|
||||
sleep .5s
|
||||
echo "unloaded ${script_name}"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ${script_name} (start | stop)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
35
config/hosts/samhain/nixos/transmission.nix
Normal file
35
config/hosts/samhain/nixos/transmission.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.transmission =
|
||||
let
|
||||
transmission-done-script = pkgs.writeScriptBin "script" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -e
|
||||
if [ "$TR_TORRENT_DIR"/"$TR_TORRENT_NAME" != "/" ]; then
|
||||
cd "$TR_TORRENT_DIR"/"$TR_TORRENT_NAME"
|
||||
if [ ! -z "*.rar" ]; then
|
||||
${pkgs.unrar}/bin/unrar x "*.rar"
|
||||
fi
|
||||
chmod ugo=rwX .
|
||||
fi'';
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
home = "/mnt/zraw/transmission";
|
||||
downloadDirPermissions = "777";
|
||||
settings = {
|
||||
download-dir = "/mnt/zraw/media/unsorted";
|
||||
incomplete-dir = "/mnt/zraw/media/.incomplete";
|
||||
incomplete-dir-enabled = true;
|
||||
rpc-bind-address = "::";
|
||||
rpc-whitelist-enabled = false;
|
||||
rpc-host-whitelist-enabled = false;
|
||||
script-torrent-done-enabled = true;
|
||||
dht-enabled = true;
|
||||
pex-enabled = true;
|
||||
script-torrent-done-filename = "${transmission-done-script}/bin/script";
|
||||
umask = 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
71
config/hosts/samhain/nixos/virtualhosts.nix
Normal file
71
config/hosts/samhain/nixos/virtualhosts.nix
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = singleton 1935;
|
||||
kw.fw.public.tcp.ports = singleton 1935;
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"samhain.net.kittywit.ch" = {
|
||||
useACMEHost = "samhain.net.kittywit.ch";
|
||||
forceSSL = true;
|
||||
locations = {
|
||||
"/jellyfin/".proxyPass = "http://127.0.0.1:8096/jellyfin/";
|
||||
"/jellyfin/socket" = {
|
||||
proxyPass = "http://127.0.0.1:8096/jellyfin/";
|
||||
extraConfig = ''
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
'';
|
||||
};
|
||||
"/tvheadend/".proxyPass = "http://192.168.1.245:9981";
|
||||
"/" = {
|
||||
root = "/mnt/zraw/media/";
|
||||
extraConfig = "autoindex on;";
|
||||
};
|
||||
"/transmission" = {
|
||||
proxyPass = "http://[::1]:9091";
|
||||
extraConfig = "proxy_pass_header X-Transmission-Session-Id;";
|
||||
};
|
||||
};
|
||||
};
|
||||
"192.168.1.135" = {
|
||||
locations = {
|
||||
"/jellyfin/".proxyPass = "http://127.0.0.1:8096/jellyfin/";
|
||||
"/jellyfin/socket" = {
|
||||
proxyPass = "http://127.0.0.1:8096/jellyfin/";
|
||||
extraConfig = ''
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
'';
|
||||
};
|
||||
|
||||
"/share/" = {
|
||||
alias = "/mnt/zraw/media/";
|
||||
extraConfig = "autoindex on;";
|
||||
};
|
||||
};
|
||||
};
|
||||
"100.103.111.44" = {
|
||||
locations."/share/" = {
|
||||
alias = "/mnt/zraw/media/";
|
||||
extraConfig = "autoindex on;";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.appendConfig = ''
|
||||
rtmp {
|
||||
server {
|
||||
listen [::]:1935 ipv6only=off;
|
||||
application kattv {
|
||||
live on;
|
||||
|
||||
allow publish all;
|
||||
allow play all;
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
}
|
||||
1
config/hosts/yule/home/default.nix
Normal file
1
config/hosts/yule/home/default.nix
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ... }: { imports = [ ./sway ]; }
|
||||
51
config/hosts/yule/home/sway/default.nix
Normal file
51
config/hosts/yule/home/sway/default.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./swayidle.nix ];
|
||||
|
||||
wayland.windowManager.sway.config =
|
||||
let
|
||||
lockCommand = "swaylock -i eDP-1:${
|
||||
../../../../users/kat/sway/wallpapers/main.png
|
||||
} -s fill";
|
||||
cfg = config.wayland.windowManager.sway.config;
|
||||
in
|
||||
{
|
||||
output =
|
||||
let
|
||||
laptop = {
|
||||
res = "1920x1080";
|
||||
pos = "0 0";
|
||||
};
|
||||
in
|
||||
{ "eDP-1" = laptop; };
|
||||
|
||||
keybindings = {
|
||||
"${cfg.modifier}+x" = "exec ${lockCommand}";
|
||||
};
|
||||
|
||||
modes = {
|
||||
"System (l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown" =
|
||||
{
|
||||
"l" = "exec ${lockCommand}, mode default";
|
||||
"e" = "exec swaymsg exit, mode default";
|
||||
"s" = "exec systemctl suspend, mode default";
|
||||
"h" = "exec systemctl hibernate, mode default";
|
||||
"r" = "exec systemctl reboot, mode default";
|
||||
"Shift+s" = "exec systemctl shutdown, mode default";
|
||||
"Return" = "mode default";
|
||||
"Escape" = "mode default";
|
||||
};
|
||||
};
|
||||
|
||||
input = {
|
||||
"1739:33362:Synaptics_TM3336-002" = {
|
||||
dwt = "enabled";
|
||||
tap = "enabled";
|
||||
natural_scroll = "enabled";
|
||||
middle_emulation = "enabled";
|
||||
click_method = "clickfinger";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
24
config/hosts/yule/home/sway/swayidle.nix
Normal file
24
config/hosts/yule/home/sway/swayidle.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
systemd.user.services.swayidle = {
|
||||
Unit = {
|
||||
Description = "swayidle";
|
||||
Documentation = [ "man:swayidle(1)" ];
|
||||
PartOf = [ "graphical-session.target" ];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = ''
|
||||
${pkgs.swayidle}/bin/swayidle -w \
|
||||
timeout 300 '${pkgs.swaylock}/bin/swaylock -f -i eDP-1:${../../../../users/kat/sway/wallpapers/main.png} \
|
||||
timeout 600 'swaymsg "output * dpms off"' \
|
||||
resume 'swaymsg "output * dpms on"' \
|
||||
before-sleep '${pkgs.swaylock}/bin/swaylock -f -i eDP-1:${../../../../users/kat/sway/wallpapers/main.png}'
|
||||
'';
|
||||
RestartSec = 3;
|
||||
Restart = "always";
|
||||
};
|
||||
Install = { WantedBy = [ "sway-session.target" ]; };
|
||||
};
|
||||
}
|
||||
22
config/hosts/yule/meta.nix
Normal file
22
config/hosts/yule/meta.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{ lib, config, ... }: with lib; {
|
||||
config = {
|
||||
deploy.targets.personal = {
|
||||
tf = {
|
||||
resources.yule = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
connection = {
|
||||
port = 62954;
|
||||
host = "192.168.1.92";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
network.nodes.yule = {
|
||||
imports = lib.hostImport "yule";
|
||||
networking = {
|
||||
hostName = "yule";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
52
config/hosts/yule/nixos/default.nix
Normal file
52
config/hosts/yule/nixos/default.nix
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{ config, users, pkgs, lib, profiles, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hw.nix
|
||||
../../../services/zfs.nix
|
||||
../../../services/restic.nix
|
||||
../../../services/node-exporter.nix
|
||||
../../../services/promtail.nix
|
||||
../../../services/netdata.nix
|
||||
../../../services/nginx.nix
|
||||
profiles.gui
|
||||
profiles.sway
|
||||
profiles.laptop
|
||||
users.kat.guiFull
|
||||
];
|
||||
|
||||
home-manager.users.kat = {
|
||||
imports = [
|
||||
../home
|
||||
];
|
||||
};
|
||||
|
||||
networking.wireless.interfaces = [ "wlp2s0" ];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
|
||||
kw.fw.private.interfaces = singleton "hexnet";
|
||||
kw.fw.public.interfaces = [ "enp1s0" "wlp2s0" ];
|
||||
|
||||
networking.hostId = "dddbb888";
|
||||
networking.hostName = "yule";
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.enp1s0.useDHCP = true;
|
||||
networking.interfaces.wlp2s0.useDHCP = true;
|
||||
|
||||
hexchen.network = {
|
||||
enable = true;
|
||||
pubkey = "9779fd6b5bdba6b9e0f53c96e141f4b11ce5ef749d1b9e77a759a3fdbd33a653";
|
||||
# if server, enable this and set endpoint:
|
||||
listen.enable = false;
|
||||
listen.endpoints = [ "tcp://0.0.0.0:0" ];
|
||||
};
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
||||
|
||||
35
config/hosts/yule/nixos/hw.nix
Normal file
35
config/hosts/yule/nixos/hw.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules =
|
||||
[ "xhci_pci" "ahci" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "rpool/safe/root";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/home" = {
|
||||
device = "rpool/safe/home";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/nix" = {
|
||||
device = "rpool/local/nix";
|
||||
fsType = "zfs";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/2552-18F2";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[{ device = "/dev/disk/by-uuid/87ff4f68-cc00-494e-8eba-050469c3bf03"; }];
|
||||
|
||||
}
|
||||
10
config/modules/home/default.nix
Normal file
10
config/modules/home/default.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ sources, ... }:
|
||||
|
||||
{
|
||||
disabledModules = [ "programs/vim.nix" ];
|
||||
imports = with (import (sources.nixexprs + "/modules")).home-manager; [ base16 syncplay konawall i3gopher weechat shell ] ++ [
|
||||
./vim.nix
|
||||
./deploy-tf
|
||||
(sources.tf-nix + "/modules/home/secrets.nix")
|
||||
];
|
||||
}
|
||||
34
config/modules/home/deploy-tf/default.nix
Normal file
34
config/modules/home/deploy-tf/default.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.deploy.tf;
|
||||
unmergedValues = types.mkOptionType {
|
||||
name = "unmergedValues";
|
||||
merge = loc: defs: map (def: def.value) defs;
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
options.deploy.tf = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf unmergedValues;
|
||||
|
||||
options = {
|
||||
attrs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
out.set = mkOption { type = types.unspecified; };
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
config = {
|
||||
deploy.tf = {
|
||||
attrs = [ "out" "attrs" ];
|
||||
out.set = removeAttrs cfg cfg.attrs;
|
||||
};
|
||||
};
|
||||
}
|
||||
194
config/modules/home/vim.nix
Normal file
194
config/modules/home/vim.nix
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.vim;
|
||||
defaultPlugins = [ pkgs.vimPlugins.vim-sensible ];
|
||||
|
||||
knownSettings = {
|
||||
background = types.enum [ "dark" "light" ];
|
||||
backupdir = types.listOf types.str;
|
||||
copyindent = types.bool;
|
||||
directory = types.listOf types.str;
|
||||
expandtab = types.bool;
|
||||
hidden = types.bool;
|
||||
history = types.int;
|
||||
ignorecase = types.bool;
|
||||
modeline = types.bool;
|
||||
mouse = types.enum [ "n" "v" "i" "c" "h" "a" "r" ];
|
||||
mousefocus = types.bool;
|
||||
mousehide = types.bool;
|
||||
mousemodel = types.enum [ "extend" "popup" "popup_setpos" ];
|
||||
number = types.bool;
|
||||
relativenumber = types.bool;
|
||||
shiftwidth = types.int;
|
||||
smartcase = types.bool;
|
||||
tabstop = types.int;
|
||||
undodir = types.listOf types.str;
|
||||
undofile = types.bool;
|
||||
};
|
||||
|
||||
vimSettingsType = types.submodule {
|
||||
options =
|
||||
let
|
||||
opt = name: type:
|
||||
mkOption {
|
||||
type = types.nullOr type;
|
||||
default = null;
|
||||
visible = false;
|
||||
};
|
||||
in
|
||||
mapAttrs opt knownSettings;
|
||||
};
|
||||
|
||||
setExpr = name: value:
|
||||
let
|
||||
v =
|
||||
if isBool value then
|
||||
(if value then "" else "no") + name
|
||||
else
|
||||
"${name}=${
|
||||
if isList value then concatStringsSep "," value else toString value
|
||||
}";
|
||||
in
|
||||
optionalString (value != null) ("set " + v);
|
||||
|
||||
plugins =
|
||||
let
|
||||
vpkgs = pkgs.vimPlugins;
|
||||
getPkg = p:
|
||||
if isDerivation p then
|
||||
[ p ]
|
||||
else
|
||||
optional (isString p && hasAttr p vpkgs) vpkgs.${p};
|
||||
in
|
||||
concatMap getPkg cfg.plugins;
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.vim = {
|
||||
enable = mkEnableOption "Vim";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.vim_configurable;
|
||||
defaultText = literalExample "pkgs.vim_configurable";
|
||||
description = "The package to use for the vim binary.";
|
||||
};
|
||||
|
||||
finalPackage = mkOption {
|
||||
type = types.package;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
description = "Resulting customized vim package.";
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
type = with types; listOf (either str package);
|
||||
default = defaultPlugins;
|
||||
example = literalExample "[ pkgs.vimPlugins.YankRing ]";
|
||||
description = ''
|
||||
List of vim plugins to install. To get a list of supported plugins run:
|
||||
<command>nix-env -f '<nixpkgs>' -qaP -A vimPlugins</command>.
|
||||
|
||||
</para><para>
|
||||
|
||||
Note: String values are deprecated, please use actual packages.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = vimSettingsType;
|
||||
default = { };
|
||||
example = literalExample ''
|
||||
{
|
||||
expandtab = true;
|
||||
history = 1000;
|
||||
background = "dark";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
At attribute set of Vim settings. The attribute names and
|
||||
corresponding values must be among the following supported
|
||||
options.
|
||||
|
||||
<informaltable frame="none"><tgroup cols="1"><tbody>
|
||||
${concatStringsSep "\n" (mapAttrsToList (n: v: ''
|
||||
<row>
|
||||
<entry><varname>${n}</varname></entry>
|
||||
<entry>${v.description}</entry>
|
||||
</row>
|
||||
'') knownSettings)}
|
||||
</tbody></tgroup></informaltable>
|
||||
|
||||
See the Vim documentation for detailed descriptions of these
|
||||
options. Note, use <varname>extraConfig</varname> to
|
||||
manually set any options not listed above.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
set nocompatible
|
||||
set nobackup
|
||||
'';
|
||||
description = "Custom .vimrc lines";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = (
|
||||
let
|
||||
customRC = ''
|
||||
${concatStringsSep "\n" (filter (v: v != "") (mapAttrsToList setExpr
|
||||
(builtins.intersectAttrs knownSettings cfg.settings)))}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
vim = cfg.package.customize {
|
||||
name = "vim";
|
||||
vimrcConfig = {
|
||||
inherit customRC;
|
||||
|
||||
packages.home-manager.start = plugins;
|
||||
};
|
||||
};
|
||||
in
|
||||
mkIf cfg.enable {
|
||||
assertions =
|
||||
let
|
||||
packagesNotFound =
|
||||
filter (p: isString p && (!hasAttr p pkgs.vimPlugins)) cfg.plugins;
|
||||
in
|
||||
[{
|
||||
assertion = packagesNotFound == [ ];
|
||||
message = "Following VIM plugin not found in pkgs.vimPlugins: ${
|
||||
concatMapStringsSep ", " (p: ''"${p}"'') packagesNotFound
|
||||
}";
|
||||
}];
|
||||
|
||||
warnings =
|
||||
let stringPlugins = filter isString cfg.plugins;
|
||||
in
|
||||
optional (stringPlugins != [ ]) ''
|
||||
Specifying VIM plugins using strings is deprecated, found ${
|
||||
concatMapStringsSep ", " (p: ''"${p}"'') stringPlugins
|
||||
} as strings.
|
||||
'';
|
||||
|
||||
home.packages = [ cfg.finalPackage ];
|
||||
|
||||
programs.vim = {
|
||||
finalPackage = vim;
|
||||
plugins = defaultPlugins;
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
8
config/modules/meta/default.nix
Normal file
8
config/modules/meta/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./deploy.nix
|
||||
./network.nix
|
||||
];
|
||||
}
|
||||
69
config/modules/meta/deploy-old.nix
Normal file
69
config/modules/meta/deploy-old.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
{ tf, target, config, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.deploy.tf;
|
||||
unmergedValues = types.mkOptionType {
|
||||
name = "unmergedValues";
|
||||
merge = loc: defs: map (def: def.value) defs;
|
||||
};
|
||||
in
|
||||
{
|
||||
options.deploy.target = mkOption {
|
||||
type = with types; str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
options.deploy.tf = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf unmergedValues;
|
||||
|
||||
options = {
|
||||
attrs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
out.set = mkOption { type = types.unspecified; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
deploy.tf = mkMerge (singleton
|
||||
{
|
||||
attrs = [ "out" "attrs" ];
|
||||
out.set = removeAttrs cfg cfg.attrs;
|
||||
deploy.systems.${config.networking.hostName} =
|
||||
with tf.resources; {
|
||||
isRemote =
|
||||
(config.networking.hostName != builtins.getEnv "HOME_HOSTNAME");
|
||||
nixosConfig = config;
|
||||
connection = tf.resources.${config.networking.hostName}.connection.set;
|
||||
triggers.copy.${config.networking.hostName} =
|
||||
tf.resources.${config.networking.hostName}.refAttr "id";
|
||||
triggers.secrets.${config.networking.hostName} =
|
||||
tf.resources.${config.networking.hostName}.refAttr "id";
|
||||
};
|
||||
|
||||
dns.records."kittywitch_net_${config.networking.hostName}" =
|
||||
mkIf (config.hexchen.network.enable) {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "${config.networking.hostName}.net";
|
||||
aaaa.address = config.hexchen.network.address;
|
||||
};
|
||||
|
||||
} ++ mapAttrsToList
|
||||
(_: user:
|
||||
mapAttrs (_: mkMerge) user.deploy.tf.out.set)
|
||||
config.home-manager.users);
|
||||
|
||||
security.acme.certs."${config.networking.hostName}.net.kittywit.ch" =
|
||||
mkIf (config.services.nginx.enable && config.hexchen.network.enable) {
|
||||
domain = "${config.networking.hostName}.net.kittywit.ch";
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
group = "nginx";
|
||||
};
|
||||
|
||||
_module.args.tf = target.${config.deploy.target};
|
||||
};
|
||||
}
|
||||
99
config/modules/meta/deploy.nix
Normal file
99
config/modules/meta/deploy.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{ sources, config, pkgs, lib, ... }: with lib; let
|
||||
cfg = config.deploy;
|
||||
meta = config;
|
||||
tfModule = { lib, ... }: with lib; {
|
||||
config._module.args = {
|
||||
pkgs = mkDefault pkgs;
|
||||
};
|
||||
};
|
||||
tfType = types.submoduleWith {
|
||||
modules = [
|
||||
tfModule
|
||||
"${toString sources.tf-nix}/modules"
|
||||
];
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
(toString (sources.tf-nix + "/modules/run.nix"))
|
||||
] ++ (optional (builtins.pathExists ../../trusted/tf/tf.nix) (../../trusted/tf/tf.nix));
|
||||
options = {
|
||||
deploy = {
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
};
|
||||
local = {
|
||||
isRoot = mkOption {
|
||||
type = types.bool;
|
||||
default = builtins.getEnv "HOME_UID" == "0";
|
||||
};
|
||||
hostName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = let
|
||||
hostName = builtins.getEnv "HOME_HOSTNAME";
|
||||
in if hostName == "" then null else hostName;
|
||||
};
|
||||
};
|
||||
targets = let
|
||||
type = types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
};
|
||||
nodeNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
tf = mkOption {
|
||||
type = tfType;
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
config.tf = mkMerge (singleton {
|
||||
imports = [
|
||||
../../targets/common
|
||||
];
|
||||
deps = {
|
||||
select.allProviders = true;
|
||||
enable = true;
|
||||
};
|
||||
terraform = {
|
||||
version = "1.0";
|
||||
logPath = cfg.dataDir + "/terraform-${config.name}.log";
|
||||
dataDir = cfg.dataDir + "/tfdata/${config.name}";
|
||||
environment.TF_CLI_ARGS_apply = "-backup=-";
|
||||
environment.TF_CLI_ARGS_taint = "-backup=-";
|
||||
};
|
||||
state = {
|
||||
file = cfg.dataDir + "/terraform-${config.name}.tfstate";
|
||||
};
|
||||
runners = {
|
||||
lazy = {
|
||||
inherit (meta.runners.lazy) file args;
|
||||
attrPrefix = "deploy.targets.${name}.tf.runners.run.";
|
||||
};
|
||||
run = {
|
||||
apply.name = "${name}-apply";
|
||||
terraform.name = "${name}-tf";
|
||||
};
|
||||
};
|
||||
continue.envVar = "TF_NIX_CONTINUE_${replaceStrings [ "-" ] [ "_" ] config.name}";
|
||||
} ++ map (nodeName: mapAttrs (_: mkMerge) meta.network.nodes.${nodeName}.deploy.tf.out.set) config.nodeNames);
|
||||
});
|
||||
in mkOption {
|
||||
type = types.attrsOf type;
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
runners = {
|
||||
run = mkMerge (mapAttrsToList (targetName: target: mapAttrs' (k: run:
|
||||
nameValuePair run.name run.set
|
||||
) target.tf.runners.run) cfg.targets);
|
||||
lazy.run = mkMerge (mapAttrsToList (targetName: target: mapAttrs' (k: run:
|
||||
nameValuePair run.name run.set
|
||||
) target.tf.runners.lazy.run) cfg.targets);
|
||||
};
|
||||
};
|
||||
}
|
||||
59
config/modules/meta/network.nix
Normal file
59
config/modules/meta/network.nix
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{ pkgs, sources, users, profiles, lib, config, ... }: with lib;
|
||||
|
||||
{
|
||||
options.network = {
|
||||
nixos = {
|
||||
extraModules = mkOption {
|
||||
type = types.listOf types.unspecified;
|
||||
default = [ ];
|
||||
};
|
||||
specialArgs = mkOption {
|
||||
type = types.attrsOf types.unspecified;
|
||||
default = { };
|
||||
};
|
||||
modulesPath = mkOption {
|
||||
type = types.path;
|
||||
default = toString (pkgs.path + "/nixos/modules");
|
||||
};
|
||||
};
|
||||
nodes = let
|
||||
nixosModule = { name, config, meta, modulesPath, lib, ... }: with lib; {
|
||||
config = {
|
||||
nixpkgs = {
|
||||
system = mkDefault pkgs.system;
|
||||
pkgs = mkDefault pkgs;
|
||||
#inherit (pkgs) config;
|
||||
};
|
||||
};
|
||||
};
|
||||
nixosType = let
|
||||
baseModules = import (config.network.nixos.modulesPath + "/module-list.nix");
|
||||
in types.submoduleWith {
|
||||
modules = baseModules
|
||||
++ singleton nixosModule
|
||||
++ config.network.nixos.extraModules;
|
||||
|
||||
specialArgs = {
|
||||
inherit baseModules;
|
||||
inherit (config.network.nixos) modulesPath;
|
||||
} // config.network.nixos.specialArgs;
|
||||
};
|
||||
in mkOption {
|
||||
type = types.attrsOf nixosType;
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
config.network = {
|
||||
nixos = {
|
||||
extraModules = [
|
||||
"${toString sources.home-manager}/nixos"
|
||||
../../modules/nixos
|
||||
];
|
||||
specialArgs = {
|
||||
inherit (config.network) nodes;
|
||||
inherit sources profiles users;
|
||||
meta = config;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
21
config/modules/nixos/default.nix
Normal file
21
config/modules/nixos/default.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{ meta, sources, lib, ... }:
|
||||
|
||||
{
|
||||
imports = with (import (sources.nixexprs + "/modules")).nixos; [ base16 base16-shared ] ++ [
|
||||
./nftables.nix
|
||||
./fw-abstraction.nix
|
||||
./deploy-tf.nix
|
||||
(sources.tf-nix + "/modules/nixos/secrets.nix")
|
||||
(sources.tf-nix + "/modules/nixos/secrets-users.nix")
|
||||
(sources.hexchen + "/modules/hexnet")
|
||||
];
|
||||
|
||||
# stubs for hexchens modules, until more generalized
|
||||
options.hexchen.dns = lib.mkOption { };
|
||||
options.hexchen.deploy = lib.mkOption { };
|
||||
|
||||
# shim
|
||||
config = {
|
||||
_module.args.hosts = lib.mapAttrs (_: config: { inherit config; } ) meta.network.nodes;
|
||||
};
|
||||
}
|
||||
91
config/modules/nixos/deploy-tf.nix
Normal file
91
config/modules/nixos/deploy-tf.nix
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{ tf, target, name, meta, config, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.deploy;
|
||||
unmergedValues = types.mkOptionType {
|
||||
name = "unmergedValues";
|
||||
merge = loc: defs: map (def: def.value) defs;
|
||||
};
|
||||
in
|
||||
{
|
||||
options.deploy = {
|
||||
targetName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
system = mkOption {
|
||||
type = types.unspecified;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
options.deploy.tf = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf unmergedValues;
|
||||
|
||||
options = {
|
||||
import = mkOption {
|
||||
type = types.attrsOf types.unspecified;
|
||||
default = [ ];
|
||||
};
|
||||
imports = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Other targets to depend on";
|
||||
default = [ ];
|
||||
};
|
||||
attrs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
out.set = mkOption { type = types.unspecified; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
deploy = {
|
||||
system = config.system.build.toplevel;
|
||||
targetName = if (meta.deploy.targets ? ${name}) then
|
||||
(mkDefault name)
|
||||
else
|
||||
head (attrNames ((filterAttrs(targetName: target: elem config.networking.hostName target.nodeNames) meta.deploy.targets)));
|
||||
};
|
||||
deploy.tf = mkMerge (singleton
|
||||
{
|
||||
attrs = [ "import" "imports" "out" "attrs" ];
|
||||
import = genAttrs cfg.tf.imports (target: meta.deploy.targets.${target}.tf);
|
||||
out.set = removeAttrs cfg.tf cfg.tf.attrs;
|
||||
deploy.systems.${config.networking.hostName} =
|
||||
with tf.resources; {
|
||||
isRemote =
|
||||
(config.networking.hostName != builtins.getEnv "HOME_HOSTNAME");
|
||||
nixosConfig = config;
|
||||
connection = tf.resources.${config.networking.hostName}.connection.set;
|
||||
triggers.copy.${config.networking.hostName} =
|
||||
tf.resources.${config.networking.hostName}.refAttr "id";
|
||||
triggers.secrets.${config.networking.hostName} =
|
||||
tf.resources.${config.networking.hostName}.refAttr "id";
|
||||
};
|
||||
|
||||
dns.records."kittywitch_net_${config.networking.hostName}" =
|
||||
mkIf (config.hexchen.network.enable) {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "${config.networking.hostName}.net";
|
||||
aaaa.address = config.hexchen.network.address;
|
||||
};
|
||||
|
||||
} ++ mapAttrsToList
|
||||
(_: user:
|
||||
mapAttrs (_: mkMerge) user.deploy.tf.out.set)
|
||||
config.home-manager.users);
|
||||
|
||||
security.acme.certs."${config.networking.hostName}.net.kittywit.ch" =
|
||||
mkIf (config.services.nginx.enable && config.hexchen.network.enable) {
|
||||
domain = "${config.networking.hostName}.net.kittywit.ch";
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
group = "nginx";
|
||||
};
|
||||
_module.args.target = mapNullable (targetName: meta.deploy.targets.${targetName}) cfg.targetName;
|
||||
_module.args.tf = mapNullable (target: target.tf) target;
|
||||
};
|
||||
}
|
||||
80
config/modules/nixos/fw-abstraction.nix
Normal file
80
config/modules/nixos/fw-abstraction.nix
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let cfg = config.kw.fw;
|
||||
in
|
||||
{
|
||||
options.kw.fw = {
|
||||
public.tcp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
public.udp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
private.tcp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
private.udp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
public.tcp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
public.udp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
private.tcp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
private.udp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
public.interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Public firewall interfaces";
|
||||
default = [ ];
|
||||
};
|
||||
private.interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Private firewall interfaces";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
networking.firewall.interfaces =
|
||||
let
|
||||
fwTypes = {
|
||||
ports = "Ports";
|
||||
ranges = "PortRanges";
|
||||
};
|
||||
|
||||
interfaceDef = visibility:
|
||||
listToAttrs (flatten (mapAttrsToList
|
||||
(type: typeString:
|
||||
map
|
||||
(proto: {
|
||||
name = "allowed${toUpper proto}${typeString}";
|
||||
value = cfg.${visibility}.${proto}.${type};
|
||||
}) [ "tcp" "udp" ])
|
||||
fwTypes));
|
||||
|
||||
interfaces = visibility:
|
||||
listToAttrs
|
||||
(map (interface: nameValuePair interface (interfaceDef visibility))
|
||||
cfg.${visibility}.interfaces);
|
||||
in
|
||||
mkMerge (map (visibility: interfaces visibility) [ "public" "private" ]);
|
||||
};
|
||||
}
|
||||
134
config/modules/nixos/nftables.nix
Normal file
134
config/modules/nixos/nftables.nix
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
{ pkgs, lib, config, modulesPath, ... }:
|
||||
|
||||
let
|
||||
fwcfg = config.networking.firewall;
|
||||
cfg = config.kw.nftables;
|
||||
|
||||
doDocker = config.virtualisation.docker.enable && cfg.generateDockerRules;
|
||||
|
||||
mkPorts = cond: ports: ranges: action: let
|
||||
portStrings = (map (range: "${toString range.from}-${toString range.to}") ranges)
|
||||
++ (map toString ports);
|
||||
in lib.optionalString (portStrings != []) ''
|
||||
${cond} dport { ${lib.concatStringsSep ", " portStrings} } ${action}
|
||||
'';
|
||||
|
||||
ruleset = ''
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority filter
|
||||
policy ${cfg.inputPolicy}
|
||||
|
||||
icmpv6 type { echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-done, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, packet-too-big } accept
|
||||
icmp type echo-request accept
|
||||
|
||||
ct state invalid drop
|
||||
ct state established,related accept
|
||||
|
||||
iifname { ${
|
||||
lib.concatStringsSep "," (["lo"] ++ fwcfg.trustedInterfaces)
|
||||
} } accept
|
||||
|
||||
${mkPorts "tcp" fwcfg.allowedTCPPorts fwcfg.allowedTCPPortRanges "accept"}
|
||||
${mkPorts "udp" fwcfg.allowedUDPPorts fwcfg.allowedUDPPortRanges "accept"}
|
||||
|
||||
${
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList (name: ifcfg:
|
||||
mkPorts "iifname ${name} tcp" ifcfg.allowedTCPPorts ifcfg.allowedTCPPortRanges "accept"
|
||||
+ mkPorts "iifname ${name} udp" ifcfg.allowedUDPPorts ifcfg.allowedUDPPortRanges "accept"
|
||||
) fwcfg.interfaces)
|
||||
}
|
||||
|
||||
# DHCPv6
|
||||
ip6 daddr fe80::/64 udp dport 546 accept
|
||||
|
||||
${cfg.extraInput}
|
||||
|
||||
counter
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority filter
|
||||
policy ${cfg.outputPolicy}
|
||||
|
||||
${cfg.extraOutput}
|
||||
|
||||
counter
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority filter
|
||||
policy ${cfg.forwardPolicy}
|
||||
|
||||
${lib.optionalString doDocker ''
|
||||
oifname docker0 ct state invalid drop
|
||||
oifname docker0 ct state established,related accept
|
||||
iifname docker0 accept
|
||||
''}
|
||||
|
||||
${cfg.extraForward}
|
||||
|
||||
counter
|
||||
}
|
||||
}
|
||||
${lib.optionalString doDocker ''
|
||||
table ip nat {
|
||||
chain docker-postrouting {
|
||||
type nat hook postrouting priority 10
|
||||
iifname docker0 masquerade
|
||||
}
|
||||
}
|
||||
''}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
in {
|
||||
options = with lib; {
|
||||
kw.nftables = {
|
||||
enable = mkEnableOption "nftables firewall";
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
extraInput = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
extraOutput = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
extraForward = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
inputPolicy = mkOption {
|
||||
type = types.str;
|
||||
default = "drop";
|
||||
};
|
||||
outputPolicy = mkOption {
|
||||
type = types.str;
|
||||
default = "accept";
|
||||
};
|
||||
forwardPolicy = mkOption {
|
||||
type = types.str;
|
||||
default = "accept";
|
||||
};
|
||||
generateDockerRules = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
networking.firewall.enable = false;
|
||||
networking.nftables = {
|
||||
enable = true;
|
||||
inherit ruleset;
|
||||
};
|
||||
|
||||
virtualisation.docker = lib.mkIf doDocker {
|
||||
extraOptions = "--iptables=false";
|
||||
};
|
||||
};
|
||||
}
|
||||
52
config/nixos.nix
Normal file
52
config/nixos.nix
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{ pkgs, config, lib, tf, sources, options, profiles, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
profiles/common
|
||||
];
|
||||
|
||||
options = {
|
||||
deploy.profile.gui = lib.mkEnableOption "graphical system";
|
||||
deploy.profile.fvwm = lib.mkEnableOption "fvwm";
|
||||
deploy.profile.sway = lib.mkEnableOption "sway wm";
|
||||
deploy.profile.laptop = lib.mkEnableOption "lappytop";
|
||||
home-manager.users = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submoduleWith {
|
||||
modules = [ ./modules/home ];
|
||||
specialArgs = {
|
||||
inherit sources tf;
|
||||
superConfig = config;
|
||||
modulesPath = sources.home-manager + "/modules";
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
home-manager = {
|
||||
useUserPackages = true;
|
||||
useGlobalPkgs = true;
|
||||
|
||||
users = {
|
||||
kat = {
|
||||
imports = lib.optional (builtins.pathExists ./trusted/users/kat) (import ./trusted/users/kat);
|
||||
|
||||
options = {
|
||||
deploy.profile.gui = lib.mkEnableOption "graphical system";
|
||||
deploy.profile.sway = lib.mkEnableOption "sway wm";
|
||||
deploy.profile.laptop = lib.mkEnableOption "lappytop";
|
||||
};
|
||||
};
|
||||
kairi = {
|
||||
imports = lib.optional (builtins.pathExists ./trusted/users/kairi) (import ./trusted/users/kairi);
|
||||
|
||||
options = {
|
||||
deploy.profile.gui = lib.mkEnableOption "graphical system";
|
||||
deploy.profile.fvwm = lib.mkEnableOption "fvwm";
|
||||
deploy.profile.laptop = lib.mkEnableOption "lappytop";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
16
config/profiles/common/access.nix
Normal file
16
config/profiles/common/access.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
security.sudo.wheelNeedsPassword = lib.mkForce false;
|
||||
|
||||
users.users.root = {
|
||||
openssh.authorizedKeys.keys = with pkgs.lib;
|
||||
concatLists (mapAttrsToList
|
||||
(name: user:
|
||||
if elem "wheel" user.extraGroups then
|
||||
user.openssh.authorizedKeys.keys
|
||||
else
|
||||
[ ])
|
||||
config.users.users);
|
||||
};
|
||||
}
|
||||
10
config/profiles/common/base16.nix
Normal file
10
config/profiles/common/base16.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
base16 = {
|
||||
console = {
|
||||
enable = true;
|
||||
scheme = "rebecca.rebecca";
|
||||
};
|
||||
};
|
||||
}
|
||||
19
config/profiles/common/default.nix
Normal file
19
config/profiles/common/default.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{ config, users, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
users.kat.base
|
||||
users.kairi.base
|
||||
users.arc
|
||||
users.hexchen
|
||||
./system.nix
|
||||
./base16.nix
|
||||
./net.nix
|
||||
./access.nix
|
||||
./locale.nix
|
||||
./nix.nix
|
||||
./ssh.nix
|
||||
./packages.nix
|
||||
./secrets.nix
|
||||
];
|
||||
}
|
||||
13
config/profiles/common/locale.nix
Normal file
13
config/profiles/common/locale.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
fonts.fonts = [
|
||||
pkgs.tamzen
|
||||
];
|
||||
i18n.defaultLocale = "en_GB.UTF-8";
|
||||
time.timeZone = "Europe/London";
|
||||
console = {
|
||||
packages = [ pkgs.tamzen ];
|
||||
keyMap = "uk";
|
||||
};
|
||||
}
|
||||
5
config/profiles/common/net.nix
Normal file
5
config/profiles/common/net.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
kw.nftables.enable = lib.mkDefault true;
|
||||
}
|
||||
21
config/profiles/common/nix.nix
Normal file
21
config/profiles/common/nix.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs, sources, ... }:
|
||||
|
||||
{
|
||||
boot.loader.grub.configurationLimit = 8;
|
||||
boot.loader.systemd-boot.configurationLimit = 8;
|
||||
|
||||
nix = {
|
||||
nixPath = [
|
||||
"nixpkgs=${sources.nixpkgs}"
|
||||
"nur=${sources.nur}"
|
||||
"arc=${sources.nixexprs}"
|
||||
"ci=${sources.ci}"
|
||||
];
|
||||
binaryCaches = [ "https://arc.cachix.org" "https://kittywitch.cachix.org" ];
|
||||
binaryCachePublicKeys =
|
||||
[ "arc.cachix.org-1:DZmhclLkB6UO0rc0rBzNpwFbbaeLfyn+fYccuAy7YVY=" "kittywitch.cachix.org-1:KIzX/G5cuPw5WgrXad6UnrRZ8UDr7jhXzRTK/lmqyK0=" ];
|
||||
gc.automatic = lib.mkDefault true;
|
||||
gc.options = lib.mkDefault "--delete-older-than 1w";
|
||||
trustedUsers = [ "root" "@wheel" ];
|
||||
};
|
||||
}
|
||||
14
config/profiles/common/packages.nix
Normal file
14
config/profiles/common/packages.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
smartmontools
|
||||
hddtemp
|
||||
lm_sensors
|
||||
cachix
|
||||
pinentry-curses
|
||||
wezterm-terminfo
|
||||
kitty.terminfo
|
||||
gnupg
|
||||
];
|
||||
}
|
||||
9
config/profiles/common/secrets.nix
Normal file
9
config/profiles/common/secrets.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
secrets = {
|
||||
root = "/var/lib/kat/secrets";
|
||||
persistentRoot = "/var/lib/kat/secrets";
|
||||
external = true;
|
||||
};
|
||||
}
|
||||
26
config/profiles/common/ssh.nix
Normal file
26
config/profiles/common/ssh.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
kw.fw.public.udp.ranges = [{
|
||||
from = 60000;
|
||||
to = 61000;
|
||||
}];
|
||||
kw.fw.private.udp.ranges = [{
|
||||
from = 60000;
|
||||
to = 61000;
|
||||
}];
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = lib.mkDefault [ 62954 ];
|
||||
passwordAuthentication = false;
|
||||
challengeResponseAuthentication = false;
|
||||
permitRootLogin = lib.mkDefault "prohibit-password";
|
||||
kexAlgorithms = [ "curve25519-sha256@libssh.org" ];
|
||||
extraConfig = ''
|
||||
StreamLocalBindUnlink yes
|
||||
LogLevel VERBOSE
|
||||
'';
|
||||
};
|
||||
programs.mosh.enable = true;
|
||||
}
|
||||
9
config/profiles/common/system.nix
Normal file
9
config/profiles/common/system.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
|
||||
boot.tmpOnTmpfs = true;
|
||||
boot.zfs.enableUnstable = true;
|
||||
services.journald.extraConfig = "SystemMaxUse=512M";
|
||||
users.mutableUsers = false;
|
||||
}
|
||||
7
config/profiles/fvwm/default.nix
Normal file
7
config/profiles/fvwm/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./fvwm.nix ];
|
||||
|
||||
deploy.profile.fvwm = true;
|
||||
}
|
||||
10
config/profiles/fvwm/fvwm.nix
Normal file
10
config/profiles/fvwm/fvwm.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager.startx.enable = true;
|
||||
services.xserver.windowManager.fvwm = {
|
||||
enable = true;
|
||||
gestures = true;
|
||||
};
|
||||
}
|
||||
6
config/profiles/gui/adb.nix
Normal file
6
config/profiles/gui/adb.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
programs.adb.enable = true;
|
||||
users.users.kat.extraGroups = [ "adbusers" ];
|
||||
}
|
||||
23
config/profiles/gui/default.nix
Normal file
23
config/profiles/gui/default.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./adb.nix
|
||||
./fonts.nix
|
||||
./gpg.nix
|
||||
./firefox.nix
|
||||
./dns.nix
|
||||
./nfs.nix
|
||||
./nix-doc.nix
|
||||
./mpd.nix
|
||||
./nixpkgs.nix
|
||||
./mingetty.nix
|
||||
./sound.nix
|
||||
];
|
||||
|
||||
hardware.opengl.extraPackages = with pkgs; [ libvdpau-va-gl ];
|
||||
services.tumbler.enable = true;
|
||||
environment.systemPackages = with pkgs; [ ntfs3g exfat-utils ];
|
||||
|
||||
deploy.profile.gui = true;
|
||||
}
|
||||
37
config/profiles/gui/dns.nix
Normal file
37
config/profiles/gui/dns.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{ config, lib, pkgs, ... }: {
|
||||
networking = {
|
||||
# networkmanager.enable = true;
|
||||
resolvconf.useLocalResolver = true;
|
||||
networkmanager.dns = "none";
|
||||
};
|
||||
|
||||
services.dnscrypt-proxy2 = {
|
||||
enable = true;
|
||||
settings = {
|
||||
ipv6_servers = true;
|
||||
require_dnssec = true;
|
||||
|
||||
sources.public-resolvers = {
|
||||
urls = [
|
||||
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md"
|
||||
"https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md"
|
||||
];
|
||||
cache_file = "/var/lib/dnscrypt-proxy2/public-resolvers.md";
|
||||
minisign_key =
|
||||
"RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
|
||||
};
|
||||
|
||||
# You can choose a specific set of servers from https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v2/public-resolvers.md
|
||||
server_names = [
|
||||
"acsacsar-ams-ipv4"
|
||||
"acsacsar-ams-ipv6"
|
||||
"dnscrypt.eu-dk"
|
||||
"dnscrypt.eu-dk-ipv6"
|
||||
"dnscrypt.eu-nl"
|
||||
"dnscrypt.eu-nl-ipv6"
|
||||
"meganerd"
|
||||
"meganerd-ipv6"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
16
config/profiles/gui/firefox.nix
Normal file
16
config/profiles/gui/firefox.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
environment.variables = { BROWSER = "firefox"; };
|
||||
|
||||
xdg = {
|
||||
portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-wlr
|
||||
xdg-desktop-portal-gtk
|
||||
];
|
||||
gtkUsePortal = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
18
config/profiles/gui/fonts.nix
Normal file
18
config/profiles/gui/fonts.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
fonts.fontconfig = {
|
||||
enable = true;
|
||||
defaultFonts = {
|
||||
emoji = [
|
||||
"Twitter Color Emoji"
|
||||
];
|
||||
};
|
||||
};
|
||||
fonts.fonts = with pkgs; [
|
||||
font-awesome
|
||||
nerdfonts
|
||||
emacs-all-the-icons-fonts
|
||||
twitter-color-emoji
|
||||
];
|
||||
}
|
||||
12
config/profiles/gui/gpg.nix
Normal file
12
config/profiles/gui/gpg.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
services.pcscd.enable = true;
|
||||
services.udev.packages = [ pkgs.yubikey-personalization ];
|
||||
|
||||
programs.gnupg.agent = {
|
||||
enable = true;
|
||||
enableSSHSupport = true;
|
||||
pinentryFlavor = "gtk2";
|
||||
};
|
||||
}
|
||||
46
config/profiles/gui/mingetty.nix
Normal file
46
config/profiles/gui/mingetty.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
c1 = "\\e[22;34m";
|
||||
c2 = "\\e[1;35m";
|
||||
nixos = [
|
||||
" ${c1} ::::. ${c2}'::::: ::::' "
|
||||
" ${c1} '::::: ${c2}':::::. ::::' "
|
||||
" ${c1} ::::: ${c2}'::::.::::: "
|
||||
" ${c1} .......:::::..... ${c2}:::::::: "
|
||||
" ${c1} ::::::::::::::::::. ${c2}:::::: ${c1}::::. "
|
||||
" ${c1} ::::::::::::::::::::: ${c2}:::::. ${c1}.::::' "
|
||||
" ${c2} ..... ::::' ${c1}:::::' "
|
||||
" ${c2} ::::: '::' ${c1}:::::' "
|
||||
" ${c2} ........::::: ' ${c1}:::::::::::. "
|
||||
" ${c2}::::::::::::: ${c1}::::::::::::: "
|
||||
" ${c2} ::::::::::: ${c1}.. ${c1}::::: "
|
||||
" ${c2} .::::: ${c1}.::: ${c1}::::: "
|
||||
" ${c2} .::::: ${c1}::::: ${c1}''''' ${c2}..... "
|
||||
" ${c2} ::::: ${c1}':::::. ${c2}......:::::::::::::' "
|
||||
" ${c2} ::: ${c1}::::::. ${c2}':::::::::::::::::' "
|
||||
" ${c1} .:::::::: ${c2}':::::::::: "
|
||||
" ${c1} .::::''::::. ${c2}'::::. "
|
||||
" ${c1} .::::' ::::. ${c2}'::::. "
|
||||
" ${c1} .:::: :::: ${c2}'::::. "
|
||||
];
|
||||
in
|
||||
{
|
||||
console = {
|
||||
font = "Tamzen7x14";
|
||||
earlySetup = true;
|
||||
getty = {
|
||||
greetingPrefix =
|
||||
''\e[H\e[2J'' + # topleft
|
||||
''\e[9;10]''; # setterm blank/powersave = 10 minutes
|
||||
greeting =
|
||||
"\n" +
|
||||
lib.concatStringsSep "\n" nixos +
|
||||
"\n\n" +
|
||||
''\e[1;32m>>> NixOS ${config.system.nixos.label} (Linux \r) - \l\e[0m'';
|
||||
};
|
||||
};
|
||||
services.getty = {
|
||||
helpLine = lib.mkForce "";
|
||||
};
|
||||
}
|
||||
8
config/profiles/gui/mpd.nix
Normal file
8
config/profiles/gui/mpd.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 6600 32101 ];
|
||||
kw.fw.public.tcp.ports = [ 6600 32101 ];
|
||||
}
|
||||
23
config/profiles/gui/nfs.nix
Normal file
23
config/profiles/gui/nfs.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
boot.supportedFilesystems = [ "nfs" ];
|
||||
|
||||
fileSystems."/mnt/kat-nas" = {
|
||||
device = "samhain.net.kittywit.ch:/mnt/zraw/media";
|
||||
fsType = "nfs";
|
||||
options = [ "x-systemd.automount" "noauto" ];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/hex-corn" = {
|
||||
device = "storah.net.lilwit.ch:/data/cornbox";
|
||||
fsType = "nfs";
|
||||
options = [ "x-systemd.automount" "noauto" ];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/hex-tor" = {
|
||||
device = "storah.net.lilwit.ch:/data/torrents";
|
||||
fsType = "nfs";
|
||||
options = [ "x-systemd.automount" "noauto" ];
|
||||
};
|
||||
}
|
||||
11
config/profiles/gui/nix-doc.nix
Normal file
11
config/profiles/gui/nix-doc.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
nix.extraOptions = ''
|
||||
plugin-files = ${pkgs.nix-doc}/lib/libnix_doc_plugin.so
|
||||
'';
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
nix-doc
|
||||
];
|
||||
}
|
||||
8
config/profiles/gui/nixpkgs.nix
Normal file
8
config/profiles/gui/nixpkgs.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
|
||||
{
|
||||
nixpkgs.config = {
|
||||
allowUnfree = true;
|
||||
pulseaudio = true;
|
||||
};
|
||||
}
|
||||
43
config/profiles/gui/sound.nix
Normal file
43
config/profiles/gui/sound.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
sound = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
defaults.pcm.rate_converter "speexrate_best"
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ pavucontrol ];
|
||||
|
||||
security.rtkit.enable = true;
|
||||
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
config = {
|
||||
pipewire = {
|
||||
"context.properties" = {
|
||||
"log.level" = 2;
|
||||
"default.clock.min-quantum" =
|
||||
32; # default; going lower may cause crackles and distorted audio
|
||||
};
|
||||
pipewire-pulse = {
|
||||
"context.modules" = [{
|
||||
name = "libpipewire-module-protocol-pulse";
|
||||
args = {
|
||||
"pulse.min.quantum" = 32; # controls minimum playback quant
|
||||
"pulse.min.req" = 32; # controls minimum recording quant
|
||||
"pulse.min.frag" = 32; # controls minimum fragment size
|
||||
"server.address" =
|
||||
[ "unix:native" ]; # the default address of the server
|
||||
};
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
pulse.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
jack.enable = true;
|
||||
alsa.enable = true;
|
||||
};
|
||||
}
|
||||
7
config/profiles/laptop/default.nix
Normal file
7
config/profiles/laptop/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [ ./light.nix ];
|
||||
|
||||
deploy.profile.laptop = true;
|
||||
}
|
||||
5
config/profiles/laptop/light.nix
Normal file
5
config/profiles/laptop/light.nix
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
programs.light.enable = true;
|
||||
}
|
||||
7
config/profiles/sway/default.nix
Normal file
7
config/profiles/sway/default.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./sway.nix ];
|
||||
|
||||
deploy.profile.sway = true;
|
||||
}
|
||||
8
config/profiles/sway/sway.nix
Normal file
8
config/profiles/sway/sway.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
programs.sway = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; lib.mkForce [ xwayland swaylock swayidle ];
|
||||
};
|
||||
}
|
||||
57
config/services/asterisk.nix
Normal file
57
config/services/asterisk.nix
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
{ config, lib, pkgs, tf, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = [ 5160 5060 ];
|
||||
kw.fw.public.udp.ports = [ 5160 5060 ];
|
||||
|
||||
kw.fw.public.tcp.ranges = [{
|
||||
from = 10000;
|
||||
to = 20000;
|
||||
}];
|
||||
|
||||
kw.fw.public.udp.ranges = [{
|
||||
from = 10000;
|
||||
to = 20000;
|
||||
}];
|
||||
|
||||
services.fail2ban.jails = {
|
||||
asterisk = ''
|
||||
enabled = true
|
||||
filter = asterisk
|
||||
action = nftables-allports
|
||||
logpath = /var/log/asterisk/messages
|
||||
maxretry = 4
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ asterisk ];
|
||||
|
||||
users.groups.asterisk = {
|
||||
name = "asterisk";
|
||||
};
|
||||
|
||||
users.users.asterisk = {
|
||||
name = "asterisk";
|
||||
group = "asterisk";
|
||||
home = "/var/lib/asterisk";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
systemd.services.asterisk = {
|
||||
description = "Asterisk PBX Server";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
restartIfChanged = false;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.asterisk}/bin/asterisk -U asterisk -C /etc/asterisk/asterisk.conf -F";
|
||||
ExecReload = "${pkgs.asterisk}/bin/asterisk -x 'core reload'";
|
||||
Type = "forking";
|
||||
PIDFile = "/run/asterisk/asterisk.pid";
|
||||
};
|
||||
};
|
||||
}
|
||||
44
config/services/calendar.nix
Normal file
44
config/services/calendar.nix
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
mailAccounts = config.mailserver.loginAccounts;
|
||||
htpasswd = pkgs.writeText "radicale.users" (concatStrings
|
||||
(flip mapAttrsToList mailAccounts
|
||||
(mail: user: mail + ":" + user.hashedPassword + "\n")));
|
||||
|
||||
in
|
||||
{
|
||||
services.radicale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
auth = {
|
||||
type = "htpasswd";
|
||||
htpasswd_filename = toString htpasswd;
|
||||
htpasswd_encryption = "bcrypt";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"cal.kittywit.ch" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:5232/";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Script-Name /;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass_header Authorization;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_cal = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "cal";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
41
config/services/fail2ban.nix
Normal file
41
config/services/fail2ban.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
packageFirewall = pkgs.nftables;
|
||||
banaction = "nftables-multiport";
|
||||
banaction-allports = "nftables-allports";
|
||||
jails = {
|
||||
default = ''
|
||||
bantime = 7d
|
||||
blocktype = DROP
|
||||
action = nftables-allports
|
||||
logpath = /var/log/auth.log
|
||||
'';
|
||||
ssh = ''
|
||||
enabled = true
|
||||
filter = sshd
|
||||
maxretry = 4
|
||||
action = nftables-multiport[name=SSH, port=ssh, protocol=tcp]
|
||||
'';
|
||||
sshd-ddos = ''
|
||||
enabled = true
|
||||
filter = sshd-ddos
|
||||
maxretry = 4
|
||||
action = nftables-multiport[name=ssh, port=ssh, protocol=tcp]
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/sshd-ddos.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = sshd(?:\[\d+\])?: Did not receive identification string from <HOST>$
|
||||
ignoreregex =
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.fail2ban.serviceConfig.LimitSTACK = 128 * 1024;
|
||||
}
|
||||
59
config/services/gitea/default.nix
Normal file
59
config/services/gitea/default.nix
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "gitea" ];
|
||||
ensureUsers = [{
|
||||
name = "gitea";
|
||||
ensurePermissions."DATABASE gitea" = "ALL PRIVILEGES";
|
||||
}];
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
disableRegistration = true;
|
||||
domain = "git.kittywit.ch";
|
||||
rootUrl = "https://git.kittywit.ch";
|
||||
httpAddress = "127.0.0.1";
|
||||
appName = "kittywitch git";
|
||||
ssh = { clonePort = 62954; };
|
||||
database = {
|
||||
type = "postgres";
|
||||
name = "gitea";
|
||||
user = "gitea";
|
||||
};
|
||||
settings = {
|
||||
security = { DISABLE_GIT_HOOKS = false; };
|
||||
api = { ENABLE_SWAGGER = true; };
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
MAILER_TYPE = "sendmail";
|
||||
FROM = "gitea@kittywit.ch";
|
||||
SENDMAIL_PATH = "${pkgs.system-sendmail}/bin/sendmail";
|
||||
};
|
||||
ui = {
|
||||
THEMES = "gitea,arc-green";
|
||||
DEFAULT_THEME = "gitea";
|
||||
THEME_COLOR_META_TAG = "#222222";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.gitea.preStart = ''
|
||||
${pkgs.coreutils}/bin/ln -sfT ${./public} /var/lib/gitea/custom/public
|
||||
${pkgs.coreutils}/bin/ln -sfT ${./templates} /var/lib/gitea/custom/templates
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts."git.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = { "/".proxyPass = "http://127.0.0.1:3000"; };
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_git = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "git";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
1
config/services/gitea/public/img/favicon.svg
Normal file
1
config/services/gitea/public/img/favicon.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 171.19"><defs><style>.cls-1,.cls-3{stroke:#000;stroke-miterlimit:10;}.cls-2{fill:#ccc;}.cls-3,.cls-4{fill:#f2f2f2;}</style></defs><path class="cls-1" d="M403.84,463.72s13.51-20.52,9.51-44.75c0,0-22.62-2.63-38,12.5C361.41,402.18,345.28,369,369.47,345c0,0,8,5.45,8.47,12.71,2,31.08-1.18,31.53-1.18,31.53,25.3-3.77,32.51-45.12,9.89-59.77-55.53-26.12-63.59-4.21-71.3,42.35-3.2,27.07-3.83,41.66-8.19,62.74-13.46-15.72-38.59-14.19-38-14-3.4,25,7.88,45.73,9.45,46.09-15,4.55-37.67,6.71-73,11.28,75.87,17.66,199,11.15,274.58-4.94C468.23,470.85,414.31,471.71,403.84,463.72Z" transform="translate(-202.9 -317.79)"/><polygon class="cls-2" points="98.68 121.45 90.04 110.5 90.44 120.65 75.53 115.4 83.03 130.62 71.94 130.38 81.58 144.37 98.68 121.45"/><path class="cls-3" d="M305.65,436.85" transform="translate(-202.9 -317.79)"/><path class="cls-4" d="M301.65,439.44l-.07-.2a85.43,85.43,0,0,0-6.65-5.65l0,6.41s-6,1.47-10.83-1.78c0,0,7.18,11.33,1.07,11.54a40.37,40.37,0,0,0-5.48.5l4.78,11.9C299.42,459.81,301.81,444.69,301.65,439.44Z" transform="translate(-202.9 -317.79)"/><polygon class="cls-2" points="179.03 119.28 187.68 108.33 187.28 118.47 202.19 113.22 194.69 128.44 205.78 128.21 196.13 142.19 179.03 119.28"/><path class="cls-4" d="M381.87,437.27l.07-.2a83.13,83.13,0,0,1,6.65-5.66l0,6.41s6,1.47,10.83-1.78c0,0-7.18,11.33-1.07,11.55a38.39,38.39,0,0,1,5.48.5L399,460C384.1,457.63,381.71,442.51,381.87,437.27Z" transform="translate(-202.9 -317.79)"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
config/services/gitea/public/img/gitea-lg.png
Normal file
BIN
config/services/gitea/public/img/gitea-lg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
config/services/gitea/public/img/gitea-sm.png
Normal file
BIN
config/services/gitea/public/img/gitea-sm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
29
config/services/gitea/templates/admin/navbar.tmpl
Normal file
29
config/services/gitea/templates/admin/navbar.tmpl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsAdminDashboard}}acty{{end}}" href="{{AppSubUrl}}/admin">
|
||||
{{.i18n.Tr "admin.dashboard"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminUsers}}acty{{end}}" href="{{AppSubUrl}}/admin/users">
|
||||
{{.i18n.Tr "admin.users"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminOrganizations}}acty{{end}}" href="{{AppSubUrl}}/admin/orgs">
|
||||
{{.i18n.Tr "admin.organizations"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminRepositories}}acty{{end}}" href="{{AppSubUrl}}/admin/repos">
|
||||
{{.i18n.Tr "admin.repositories"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminHooks}}acty{{end}}" href="{{AppSubUrl}}/admin/hooks">
|
||||
{{.i18n.Tr "admin.hooks"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminAuthentications}}acty{{end}}" href="{{AppSubUrl}}/admin/auths">
|
||||
{{.i18n.Tr "admin.authentication"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminConfig}}acty{{end}}" href="{{AppSubUrl}}/admin/config">
|
||||
{{.i18n.Tr "admin.config"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminNotices}}acty{{end}}" href="{{AppSubUrl}}/admin/notices">
|
||||
{{.i18n.Tr "admin.notices"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsAdminMonitor}}acty{{end}}" href="{{AppSubUrl}}/admin/monitor">
|
||||
{{.i18n.Tr "admin.monitor"}}
|
||||
</a>
|
||||
</div>
|
||||
176
config/services/gitea/templates/custom/head.tmpl
Normal file
176
config/services/gitea/templates/custom/head.tmpl
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head data-suburl="{{AppSubUrl}}">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
||||
<link rel="manifest" href="{{AppSubUrl}}/manifest.json">
|
||||
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) {
|
||||
// Registration was successful
|
||||
console.log('ServiceWorker registration successful with scope: ', registration.scope);
|
||||
}, function(err) {
|
||||
// registration failed :(
|
||||
console.log('ServiceWorker registration failed: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
|
||||
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" />
|
||||
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" />
|
||||
<meta name="keywords" content="{{MetaKeywords}}">
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<meta name="_csrf" content="{{.CsrfToken}}" />
|
||||
<meta name="_suburl" content="{{AppSubUrl}}" />
|
||||
{{if .IsSigned}}
|
||||
<meta name="_uid" content="{{.SignedUser.ID}}" />
|
||||
{{end}}
|
||||
{{if .ContextUser}}
|
||||
<meta name="_context_uid" content="{{.ContextUser.ID}}" />
|
||||
{{end}}
|
||||
{{if .SearchLimit}}
|
||||
<meta name="_search_limit" content="{{.SearchLimit}}" />
|
||||
{{end}}
|
||||
{{if .GoGetImport}}
|
||||
<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">
|
||||
<meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}">
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
{{SafeJS `/*
|
||||
@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.
|
||||
|
||||
Copyright (c) 2016 The Gitea Authors
|
||||
Copyright (c) 2015 The Gogs Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
---
|
||||
Licensing information for additional javascript libraries can be found at:
|
||||
{{AppSubUrl}}/vendor/librejs.html
|
||||
|
||||
@licend The above is the entire license notice
|
||||
for the JavaScript code in this page.
|
||||
*/`}}
|
||||
</script>
|
||||
|
||||
<link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" />
|
||||
<link rel="mask-icon" href="{{AppSubUrl}}/img/gitea-safari.svg" color="#609926">
|
||||
<link rel="preload" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css" as="style" onload="this.rel='stylesheet'">
|
||||
<noscript><link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/font-awesome/css/font-awesome.min.css"></noscript>
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/assets/octicons/octicons.min.css">
|
||||
|
||||
{{if .RequireSimpleMDE}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.css">
|
||||
{{end}}
|
||||
|
||||
{{if .RequireGitGraph}}
|
||||
<!-- graph -->
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/gitgraph/gitgraph.css">
|
||||
{{end}}
|
||||
|
||||
{{if .RequireTribute}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/tribute/tribute.css">
|
||||
{{end}}
|
||||
|
||||
<!-- Stylesheet -->
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.css">
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/index.css?v={{MD5 AppVer}}">
|
||||
<noscript>
|
||||
<style>
|
||||
.dropdown:hover > .menu { display: block; }
|
||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
|
||||
</style>
|
||||
</noscript>
|
||||
|
||||
{{if .RequireHighlightJS}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/highlight/github.css">
|
||||
{{end}}
|
||||
{{if .RequireMinicolors}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
|
||||
{{end}}
|
||||
{{if .RequireDatetimepicker}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css">
|
||||
{{end}}
|
||||
{{if .RequireDropzone}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css">
|
||||
{{end}}
|
||||
{{if .EnableHeatmap}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/vendor/plugins/vue-calendar-heatmap/vue-calendar-heatmap.css">
|
||||
{{end}}
|
||||
<style class="list-search-style"></style>
|
||||
|
||||
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/loadCSS.min.js"></script>
|
||||
<script src="{{AppSubUrl}}/vendor/plugins/cssrelpreload/cssrelpreload.min.js"></script>
|
||||
{{if .PageIsUserProfile}}
|
||||
<meta property="og:title" content="{{.Owner.Name}}" />
|
||||
<meta property="og:type" content="profile" />
|
||||
<meta property="og:image" content="{{.Owner.AvatarLink}}" />
|
||||
<meta property="og:url" content="{{.Owner.HTMLURL}}" />
|
||||
<meta property="og:site_name" content="{{AppName}}" />
|
||||
{{else if .Repository}}
|
||||
<meta property="og:title" content="{{.Repository.Name}}" />
|
||||
<meta property="og:type" content="object" />
|
||||
<meta property="og:image" content="{{.Repository.Owner.AvatarLink}}" />
|
||||
<meta property="og:url" content="{{.Repository.HTMLURL}}" />
|
||||
{{if .Repository.Description}}
|
||||
<meta property="og:description" content="{{.Repository.Description}}" />
|
||||
{{end}}
|
||||
<meta property="og:site_name" content="{{AppName}}" />
|
||||
{{else}}
|
||||
<meta property="og:title" content="{{AppName}}">
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="{{AppSubUrl}}/img/gitea-lg.png" />
|
||||
<meta property="og:url" content="{{AppUrl}}" />
|
||||
<meta property="og:description" content="{{MetaDescription}}">
|
||||
{{end}}
|
||||
{{if .IsSigned }}
|
||||
{{ if ne .SignedUser.Theme "gitea" }}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css">
|
||||
{{end}}
|
||||
{{else if ne DefaultTheme "gitea"}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css">
|
||||
{{end}}
|
||||
{{template "custom/header" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "custom/body_outer_pre" .}}
|
||||
|
||||
<div class="full height">
|
||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript>
|
||||
|
||||
{{template "custom/body_inner_pre" .}}
|
||||
|
||||
{{if not .PageIsInstall}}
|
||||
<div class="ui top secondary stackable main menu following bar light">
|
||||
{{template "base/head_navbar" .}}
|
||||
</div><!-- end bar -->
|
||||
{{end}}
|
||||
{{/*
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
*/}}
|
||||
16
config/services/gitea/templates/explore/navbar.tmpl
Normal file
16
config/services/gitea/templates/explore/navbar.tmpl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless stackable menu navbar">
|
||||
<a class="item {{if .PageIsExploreRepositories}}acty{{end}}" href="{{AppSubUrl}}/explore/repos">
|
||||
{{svg "octicon-repo" 16}} {{.i18n.Tr "explore.repos"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsExploreUsers}}acty{{end}}" href="{{AppSubUrl}}/explore/users">
|
||||
{{svg "octicon-person" 16}} {{.i18n.Tr "explore.users"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsExploreOrganizations}}acty{{end}}" href="{{AppSubUrl}}/explore/organizations">
|
||||
{{svg "octicon-organization" 16}} {{.i18n.Tr "explore.organizations"}}
|
||||
</a>
|
||||
{{if .IsRepoIndexerEnabled}}
|
||||
<a class="item {{if .PageIsExploreCode}}acty{{end}}" href="{{AppSubUrl}}/explore/code">
|
||||
{{svg "octicon-code" 16}} {{.i18n.Tr "explore.code"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
18
config/services/gitea/templates/home.tmpl
Normal file
18
config/services/gitea/templates/home.tmpl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="home">
|
||||
<div class="ui stackable middle very relaxed page grid">
|
||||
<div class="sixteen wide center aligned centered column">
|
||||
<div>
|
||||
<img class="logo" src="{{StaticUrlPrefix}}/img/gitea-lg.png" />
|
||||
</div>
|
||||
<div class="hero">
|
||||
<br />
|
||||
<h1 class="ui icon header title">
|
||||
{{AppName}}
|
||||
</h1>
|
||||
<a href="https://kittywit.ch"><h2>back to home</h2></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
143
config/services/gitea/templates/repo/header.tmpl
Normal file
143
config/services/gitea/templates/repo/header.tmpl
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<div class="header-wrapper">
|
||||
{{with .Repository}}
|
||||
<div class="ui container">
|
||||
<div class="repo-header">
|
||||
<div class="ui huge breadcrumb repo-title">
|
||||
{{if .RelAvatarLink}}
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}">
|
||||
{{else if .IsTemplate}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-repo-template-private" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo-template" 32}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-lock" 32}}
|
||||
{{else if .IsMirror}}
|
||||
{{svg "octicon-repo-clone" 32}}
|
||||
{{else if .IsFork}}
|
||||
{{svg "octicon-repo-fork" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo" 32}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
|
||||
<div class="divider"> / </div>
|
||||
<a href="{{$.RepoLink}}">{{.Name}}</a>
|
||||
{{if .RelAvatarLink}}
|
||||
{{if .IsTemplate}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-repo-template-private" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo-template" 32}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .IsPrivate}}
|
||||
{{svg "octicon-lock" 32}}
|
||||
{{else if .IsMirror}}
|
||||
{{svg "octicon-repo-clone" 32}}
|
||||
{{else if .IsFork}}
|
||||
{{svg "octicon-repo-fork" 32}}
|
||||
{{else}}
|
||||
{{svg "octicon-repo" 32}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}
|
||||
{{if .IsMirror}}<div class="fork-flag">{{$.i18n.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}">{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}</a></div>{{end}}
|
||||
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}}
|
||||
{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}}
|
||||
</div>
|
||||
{{if not .IsBeingCreated}}
|
||||
<div class="repo-buttons">
|
||||
<div class="ui labeled button" tabindex="0">
|
||||
<a class="ui compact basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
|
||||
<i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/watchers">
|
||||
{{.NumWatches}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui labeled button" tabindex="0">
|
||||
<a class="ui compact basic button" href="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}">
|
||||
<i class="icon star{{if not $.IsStaringRepo}} outline{{end}}"></i>{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/stars">
|
||||
{{.NumStars}}
|
||||
</a>
|
||||
</div>
|
||||
{{if and (not .IsEmpty) ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
<div class="ui labeled button {{if and ($.IsSigned) (not $.CanSignedUserFork)}}disabled-repo-button{{end}}" tabindex="0">
|
||||
<a class="ui compact basic button {{if or (not $.IsSigned) (not $.CanSignedUserFork)}}poping up{{end}}" {{if $.CanSignedUserFork}}href="{{AppSubUrl}}/repo/fork/{{.ID}}"{{else if $.IsSigned}} data-content="{{$.i18n.Tr "repo.fork_from_self"}}" {{ else }} data-content="{{$.i18n.Tr "repo.fork_guest_user" }}" rel="nofollow" href="{{AppSubUrl}}/user/login?redirect_to={{AppSubUrl}}/repo/fork/{{.ID}}" {{end}} data-position="top center" data-variation="tiny">
|
||||
{{svg "octicon-repo-forked" 16}}{{$.i18n.Tr "repo.fork"}}
|
||||
</a>
|
||||
<a class="ui basic label" href="{{.Link}}/forks">
|
||||
{{.NumForks}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div><!-- end grid -->
|
||||
</div><!-- end container -->
|
||||
{{end}}
|
||||
<div class="ui tabs container">
|
||||
{{if not .Repository.IsBeingCreated}}
|
||||
<div class="ui tabular stackable menu navbar">
|
||||
{{if .Permission.CanRead $.UnitTypeCode}}
|
||||
<a class="item {{if .PageIsViewCode}}acty{{end}}" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">
|
||||
{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if .Permission.CanRead $.UnitTypeIssues}}
|
||||
<a class="item {{if .PageIsIssueList}}acty{{end}}" href="{{.RepoLink}}/issues">
|
||||
{{svg "octicon-issue-opened" 16}} {{.i18n.Tr "repo.issues"}} <span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if .Permission.CanRead $.UnitTypeExternalTracker}}
|
||||
<a class="item {{if .PageIsIssueList}}acty{{end}}" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer">
|
||||
{{svg "octicon-link-external" 16}} {{.i18n.Tr "repo.issues"}} </span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}}
|
||||
<a class="item {{if .PageIsPullList}}acty{{end}}" href="{{.RepoLink}}/pulls">
|
||||
{{svg "octicon-git-pull-request" 16}} {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo) }}
|
||||
<a class="item {{if .PageIsReleaseList}}acty{{end}}" href="{{.RepoLink}}/releases">
|
||||
{{svg "octicon-tag" 16}} {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .NumReleases}}gray{{else}}blue{{end}} small label">{{.NumReleases}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}}
|
||||
<a class="item {{if .PageIsWiki}}acty{{end}}" href="{{.RepoLink}}/wiki" {{if (.Permission.CanRead $.UnitTypeExternalWiki)}} target="_blank" rel="noopener noreferrer" {{end}}>
|
||||
{{svg "octicon-book" 16}} {{.i18n.Tr "repo.wiki"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}}
|
||||
<a class="item {{if .PageIsActivity}}acty{{end}}" href="{{.RepoLink}}/activity">
|
||||
{{svg "octicon-pulse" 16}} {{.i18n.Tr "repo.activity"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{template "custom/extra_tabs" .}}
|
||||
|
||||
{{if .Permission.IsAdmin}}
|
||||
<div class="right menu">
|
||||
<a class="item {{if .PageIsSettings}}acty{{end}}" href="{{.RepoLink}}/settings">
|
||||
{{svg "octicon-tools" 16}} {{.i18n.Tr "repo.settings"}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui tabs divider"></div>
|
||||
</div>
|
||||
153
config/services/gitea/templates/repo/home.tmpl
Normal file
153
config/services/gitea/templates/repo/home.tmpl
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="repository file list">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
<div class="ui repo-description">
|
||||
<div id="repo-desc">
|
||||
{{if .Repository.DescriptionHTML}}<span class="description has-emoji">{{.Repository.DescriptionHTML}}</span>{{else if .IsRepositoryAdmin}}<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span>{{end}}
|
||||
<a class="link" href="{{.Repository.Website}}">{{.Repository.Website}}</a>
|
||||
</div>
|
||||
{{if .RepoSearchEnabled}}
|
||||
<div class="ui repo-search">
|
||||
<form class="ui form ignore-dirty" action="{{.RepoLink}}/search" method="get">
|
||||
<div class="field">
|
||||
<div class="ui action input">
|
||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "repo.search.search_repo"}}">
|
||||
<button class="ui icon button" type="submit">
|
||||
<i class="search icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui" id="repo-topics">
|
||||
{{range .Topics}}<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}}
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<a id="manage_topic">{{.i18n.Tr "repo.topic.manage_topics"}}</a>{{end}}
|
||||
</div>
|
||||
{{if and .Permission.IsAdmin (not .Repository.IsArchived)}}
|
||||
<div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none">
|
||||
<div class="fourteen wide column">
|
||||
<div class="field">
|
||||
<div class="ui fluid multiple search selection dropdown">
|
||||
<input type="hidden" name="topics" value="{{range $i, $v := .Topics}}{{.Name}}{{if lt (Add $i 1) (len $.Topics)}},{{end}}{{end}}">
|
||||
{{range .Topics}}
|
||||
<div class="ui small label topic transition visible" data-value="{{.Name}}" style="display: inline-block !important; cursor: default;">{{.Name}}<i class="delete icon"></i></div>
|
||||
{{end}}
|
||||
<div class="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="two wide column">
|
||||
<a class="ui button primary" href="javascript:;" id="save_topic"
|
||||
data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="hide" id="validate_prompt">
|
||||
<span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span>
|
||||
<span id="format_prompt">{{.i18n.Tr "repo.topic.format_prompt"}}</span>
|
||||
</div>
|
||||
{{if .Repository.IsArchived}}
|
||||
<div class="ui warning message">
|
||||
{{.i18n.Tr "repo.archive.title"}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "repo/sub_menu" .}}
|
||||
<div class="ui stackable secondary menu mobile--margin-between-items mobile--no-negative-margins">
|
||||
{{template "repo/branch_dropdown" .}}
|
||||
{{ $n := len .TreeNames}}
|
||||
{{ $l := Subtract $n 1}}
|
||||
<!-- If home page, show new PR. If not, show breadcrumb -->
|
||||
{{if eq $n 0}}
|
||||
{{if and .PullRequestCtx.Allowed .IsViewBranch (not .Repository.IsArchived)}}
|
||||
<div class="fitted item">
|
||||
<a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}">
|
||||
<button id="new-pull-request" class="ui compact basic button">{{.i18n.Tr "repo.pulls.compare_changes"}}</button>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="fitted item"><span class="ui breadcrumb repo-path"><a class="section" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{ $p := index $.Paths $i}}<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
|
||||
{{end}}
|
||||
<div class="right fitted item" id="file-buttons">
|
||||
<div class="ui tiny blue buttons">
|
||||
{{if .Repository.CanEnableEditor}}
|
||||
{{if .CanAddFile}}
|
||||
<a href="{{.RepoLink}}/_new/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.editor.new_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .CanUploadFile}}
|
||||
<a href="{{.RepoLink}}/_upload/{{EscapePound .BranchName}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.editor.upload_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }}
|
||||
<a href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}" class="ui button">
|
||||
{{.i18n.Tr "repo.file_history"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="fitted item">
|
||||
{{if eq $n 0}}
|
||||
{{if .Repository.IsTemplate}}
|
||||
<div class="ui tiny blue buttons">
|
||||
<a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
|
||||
{{.i18n.Tr "repo.use_template"}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="fitted item">
|
||||
|
||||
<!-- Only show clone panel in repository home page -->
|
||||
{{if eq $n 0}}
|
||||
<div class="ui action tiny input" id="clone-panel">
|
||||
{{if not $.DisableHTTP}}
|
||||
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
|
||||
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
|
||||
<button class="ui basic clone button" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">
|
||||
SSH
|
||||
</button>
|
||||
{{end}}
|
||||
{{if not $.DisableHTTP}}
|
||||
<input id="repo-clone-url" value="{{$.CloneLink.HTTPS}}" readonly>
|
||||
{{else if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
|
||||
<input id="repo-clone-url" value="{{$.CloneLink.SSH}}" readonly>
|
||||
{{end}}
|
||||
{{if or (not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH))}}
|
||||
<button class="ui basic icon button poping up clipboard" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url">
|
||||
{{svg "octicon-clippy" 16}}
|
||||
</button>
|
||||
{{end}}
|
||||
<div class="ui basic jump dropdown icon button poping up" data-content="{{.i18n.Tr "repo.download_archive"}}" data-variation="tiny inverted" data-position="top right">
|
||||
<i class="download icon"></i>
|
||||
<div class="menu">
|
||||
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.zip">{{svg "octicon-file-zip" 16}} ZIP</a>
|
||||
<a class="item" href="{{$.RepoLink}}/archive/{{EscapePound $.BranchName}}.tar.gz">{{svg "octicon-file-zip" 16}} TAR.GZ</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsViewFile}}
|
||||
{{template "repo/view_file" .}}
|
||||
{{else if .IsBlame}}
|
||||
{{template "repo/blame" .}}
|
||||
{{else}}
|
||||
{{template "repo/view_list" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
29
config/services/gitea/templates/repo/settings/navbar.tmpl
Normal file
29
config/services/gitea/templates/repo/settings/navbar.tmpl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsSettingsOptions}}acty{{end}}" href="{{.RepoLink}}/settings">
|
||||
{{.i18n.Tr "repo.settings.options"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsCollaboration}}acty{{end}}" href="{{.RepoLink}}/settings/collaboration">
|
||||
{{.i18n.Tr "repo.settings.collaboration"}}
|
||||
</a>
|
||||
{{if not .Repository.IsEmpty}}
|
||||
<a class="item {{if .PageIsSettingsBranches}}acty{{end}}" href="{{.RepoLink}}/settings/branches">
|
||||
{{.i18n.Tr "repo.settings.branches"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item {{if .PageIsSettingsHooks}}acty{{end}}" href="{{.RepoLink}}/settings/hooks">
|
||||
{{.i18n.Tr "repo.settings.hooks"}}
|
||||
</a>
|
||||
{{if .SignedUser.CanEditGitHook}}
|
||||
<a class="item {{if .PageIsSettingsGitHooks}}acty{{end}}" href="{{.RepoLink}}/settings/hooks/git">
|
||||
{{.i18n.Tr "repo.settings.githooks"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item {{if .PageIsSettingsKeys}}acty{{end}}" href="{{.RepoLink}}/settings/keys">
|
||||
{{.i18n.Tr "repo.settings.deploy_keys"}}
|
||||
</a>
|
||||
{{if .LFSStartServer}}
|
||||
<a class="item {{if .PageIsSettingsLFS}}acty{{end}}" href="{{.RepoLink}}/settings/lfs">
|
||||
{{.i18n.Tr "repo.settings.lfs"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
132
config/services/gitea/templates/user/dashboard/dashboard.tmpl
Normal file
132
config/services/gitea/templates/user/dashboard/dashboard.tmpl
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
{{template "base/head" .}}
|
||||
<div class="dashboard feeds">
|
||||
{{template "user/dashboard/navbar" .}}
|
||||
<div class="ui container">
|
||||
{{template "base/alert" .}}
|
||||
<div class="ui mobile reversed stackable grid">
|
||||
<div class="ui container ten wide column">
|
||||
{{if .EnableHeatmap}}
|
||||
<div id="user-heatmap" style="padding-right: 40px">
|
||||
<activity-heatmap :locale="locale" :suburl="suburl" :user="heatmapUser">
|
||||
<div slot="loading">
|
||||
<div class="ui active centered inline indeterminate text loader" id="loading-heatmap">{{.i18n.Tr "user.heatmap.loading"}}</div>
|
||||
</div>
|
||||
</activity-heatmap>
|
||||
<div class="ui divider"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{template "user/dashboard/feeds" .}}
|
||||
</div>
|
||||
<div id="app" class="six wide column">
|
||||
<repo-search
|
||||
:search-limit="searchLimit"
|
||||
:suburl="suburl"
|
||||
:uid="uid"
|
||||
:more-repos-link="'{{.ContextUser.HomeLink}}'"
|
||||
{{if not .ContextUser.IsOrganization}}
|
||||
:organizations="[
|
||||
{{range .ContextUser.Orgs}}
|
||||
{name: '{{.Name}}', num_repos: '{{.NumRepos}}'},
|
||||
{{end}}
|
||||
]"
|
||||
:is-organization="false"
|
||||
:organizations-total-count="{{.ContextUser.GetOrganizationCount}}"
|
||||
:can-create-organization="{{.SignedUser.CanCreateOrganization}}"
|
||||
{{end}}
|
||||
inline-template
|
||||
v-cloak
|
||||
>
|
||||
<div>
|
||||
<div v-if="!isOrganization" class="ui two item tabable menu">
|
||||
<a :class="{item: true, acty: tab === 'repos'}" @click="changeTab('repos')">{{.i18n.Tr "repository"}}</a>
|
||||
<a :class="{item: true, acty: tab === 'organizations'}" @click="changeTab('organizations')">{{.i18n.Tr "organization"}}</a>
|
||||
</div>
|
||||
<div v-show="tab === 'repos'" class="ui tab active list dashboard-repos">
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "home.my_repos"}} <span class="ui grey label">${reposTotalCount}</span>
|
||||
{{if or (not .ContextUser.IsOrganization) .IsOrganizationOwner}}
|
||||
<div class="ui right">
|
||||
<a class="poping up" :href="suburl + '/repo/create{{if .ContextUser.IsOrganization}}?org={{.ContextUser.ID}}{{end}}'" data-content="{{.i18n.Tr "new_repo"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<i class="plus icon"></i>
|
||||
<span class="sr-only">{{.i18n.Tr "new_repo"}}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</h4>
|
||||
<div class="ui attached secondary segment repos-search">
|
||||
<div class="ui fluid icon input" :class="{loading: isLoading}">
|
||||
<input @input="searchRepos(reposFilter)" v-model="searchQuery" ref="search" placeholder="{{.i18n.Tr "home.search_repos"}}">
|
||||
<i class="search icon"></i>
|
||||
</div>
|
||||
<div class="ui secondary tiny pointing borderless menu center aligned grid repos-filter">
|
||||
<a class="item" :class="{acty: reposFilter === 'all'}" @click="changeReposFilter('all')">
|
||||
{{.i18n.Tr "all"}}
|
||||
<div v-show="reposFilter === 'all'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'sources'}" @click="changeReposFilter('sources')">
|
||||
{{.i18n.Tr "sources"}}
|
||||
<div v-show="reposFilter === 'sources'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'forks'}" @click="changeReposFilter('forks')">
|
||||
{{.i18n.Tr "forks"}}
|
||||
<div v-show="reposFilter === 'forks'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'mirrors'}" @click="changeReposFilter('mirrors')">
|
||||
{{.i18n.Tr "mirrors"}}
|
||||
<div v-show="reposFilter === 'mirrors'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
<a class="item" :class="{acty: reposFilter === 'collaborative'}" @click="changeReposFilter('collaborative')">
|
||||
{{.i18n.Tr "collaborative"}}
|
||||
<div v-show="reposFilter === 'collaborative'" class="ui circular mini grey label">${repoTypeCount}</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui attached table segment">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo, reposFilter)">
|
||||
<a :href="suburl + '/' + repo.full_name">
|
||||
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="staticPrefix + '/img/svg/icons.svg#' + repoClass(repo)" /></svg>
|
||||
<strong class="text truncate item-name">${repo.full_name}</strong>
|
||||
<i v-if="repo.archived" class="archive icon archived-icon"></i>
|
||||
<span class="ui right text light grey">
|
||||
${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="showMoreReposLink">
|
||||
<a :href="moreReposLink">{{.i18n.Tr "home.show_more_repos"}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isOrganization" v-show="tab === 'organizations'" class="ui tab active list">
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "home.my_orgs"}} <span class="ui grey label">${organizationsTotalCount}</span>
|
||||
<div v-if="canCreateOrganization" class="ui right">
|
||||
<a class="poping up" :href="suburl + '/org/create'" data-content="{{.i18n.Tr "new_org"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<i class="plus icon"></i>
|
||||
<span class="sr-only">{{.i18n.Tr "new_org"}}</span>
|
||||
</a>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<ul class="repo-owner-name-list">
|
||||
<li v-for="org in organizations">
|
||||
<a :href="suburl + '/' + org.name">
|
||||
{{svg "octicon-organization" 16}}
|
||||
<strong class="text truncate item-name">${org.name}</strong>
|
||||
<span class="ui right text light grey">
|
||||
${org.num_repos} <span class="rear">{{svg "octicon-repo" 16}}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</repo-search>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
23
config/services/gitea/templates/user/settings/navbar.tmpl
Normal file
23
config/services/gitea/templates/user/settings/navbar.tmpl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
|
||||
<a class="item {{if .PageIsSettingsProfile}}acty{{end}}" href="{{AppSubUrl}}/user/settings">
|
||||
{{.i18n.Tr "settings.profile"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsAccount}}acty{{end}}" href="{{AppSubUrl}}/user/settings/account">
|
||||
{{.i18n.Tr "settings.account"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsSecurity}}acty{{end}}" href="{{AppSubUrl}}/user/settings/security">
|
||||
{{.i18n.Tr "settings.security"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsApplications}}acty{{end}}" href="{{AppSubUrl}}/user/settings/applications">
|
||||
{{.i18n.Tr "settings.applications"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsKeys}}acty{{end}}" href="{{AppSubUrl}}/user/settings/keys">
|
||||
{{.i18n.Tr "settings.ssh_gpg_keys"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsOrganization}}acty{{end}}" href="{{AppSubUrl}}/user/settings/organization">
|
||||
{{.i18n.Tr "settings.organization"}}
|
||||
</a>
|
||||
<a class="item {{if .PageIsSettingsRepos}}acty{{end}}" href="{{AppSubUrl}}/user/settings/repos">
|
||||
{{.i18n.Tr "settings.repos"}}
|
||||
</a>
|
||||
</div>
|
||||
36
config/services/grafana.nix
Normal file
36
config/services/grafana.nix
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ "grafana" ];
|
||||
ensureUsers = [{
|
||||
name = "grafana";
|
||||
ensurePermissions."DATABASE grafana" = "ALL PRIVILEGES";
|
||||
}];
|
||||
};
|
||||
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
port = 3001;
|
||||
domain = "graph.kittywit.ch";
|
||||
rootUrl = "https://graph.kittywit.ch/";
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "/run/postgresql/";
|
||||
user = "grafana";
|
||||
name = "grafana";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."graph.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = { "/".proxyPass = "http://127.0.0.1:3001"; };
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_graph = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "graph";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
}
|
||||
25
config/services/logrotate.nix
Normal file
25
config/services/logrotate.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
services.logrotate = {
|
||||
enable = true;
|
||||
paths = {
|
||||
nginx = mkIf config.services.nginx.enable {
|
||||
path = "/var/log/nginx/*.log";
|
||||
user = "nginx";
|
||||
group = "nginx";
|
||||
frequency = "weekly";
|
||||
keep = 2;
|
||||
};
|
||||
asterisk = mkIf config.systemd.services.asterisk.enable {
|
||||
path = "/var/log/asterisk/messages";
|
||||
user = "asterisk";
|
||||
group = "asterisk";
|
||||
frequency = "daily";
|
||||
keep = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
62
config/services/loki.nix
Normal file
62
config/services/loki.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 3100 ];
|
||||
services.loki = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
auth_enabled = false;
|
||||
chunk_store_config = { max_look_back_period = "0s"; };
|
||||
ingester = {
|
||||
chunk_idle_period = "1h";
|
||||
chunk_retain_period = "30s";
|
||||
chunk_target_size = 1048576;
|
||||
lifecycler = {
|
||||
address = "0.0.0.0";
|
||||
final_sleep = "0s";
|
||||
ring = {
|
||||
kvstore = { store = "inmemory"; };
|
||||
replication_factor = 1;
|
||||
};
|
||||
};
|
||||
max_chunk_age = "1h";
|
||||
max_transfer_retries = 0;
|
||||
};
|
||||
limits_config = {
|
||||
reject_old_samples = true;
|
||||
reject_old_samples_max_age = "168h";
|
||||
};
|
||||
schema_config = {
|
||||
configs = [{
|
||||
from = "2020-10-24";
|
||||
index = {
|
||||
period = "24h";
|
||||
prefix = "index_";
|
||||
};
|
||||
object_store = "filesystem";
|
||||
schema = "v11";
|
||||
store = "boltdb-shipper";
|
||||
}];
|
||||
};
|
||||
compactor = {
|
||||
working_directory = "/tmp/loki-compactor-boltdb";
|
||||
shared_store = "filesystem";
|
||||
};
|
||||
server = { http_listen_port = 3100; };
|
||||
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"; };
|
||||
};
|
||||
table_manager = {
|
||||
retention_deletes_enabled = false;
|
||||
retention_period = "0s";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
106
config/services/mail.nix
Normal file
106
config/services/mail.nix
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{ config, lib, tf, pkgs, sources, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [ sources.nixos-mailserver.outPath ];
|
||||
|
||||
services.fail2ban.jails = {
|
||||
postfix = ''
|
||||
enabled = true
|
||||
filter = postfix
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=smtp, protocol=tcp]
|
||||
'';
|
||||
postfix-sasl = ''
|
||||
enabled = true
|
||||
filter = postfix-sasl
|
||||
port = postfix,imap3,imaps,pop3,pop3s
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=smtp, protocol=tcp]
|
||||
'';
|
||||
postfix-ddos = ''
|
||||
enabled = true
|
||||
filter = postfix-ddos
|
||||
maxretry = 3
|
||||
action = nftables-multiport[name=postfix, port=submission, protocol=tcp]
|
||||
bantime = 7200
|
||||
'';
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/postfix-sasl.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
# Fail2Ban filter for postfix authentication failures
|
||||
[INCLUDES]
|
||||
before = common.conf
|
||||
[Definition]
|
||||
daemon = postfix/smtpd
|
||||
failregex = ^%(__prefix_line)swarning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+/]*={0,2})?\s*$
|
||||
'';
|
||||
};
|
||||
|
||||
environment.etc."fail2ban/filter.d/postfix-ddos.conf" = {
|
||||
enable = true;
|
||||
text = ''
|
||||
[Definition]
|
||||
failregex = lost connection after EHLO from \S+\[<HOST>\]
|
||||
'';
|
||||
};
|
||||
|
||||
deploy.tf.variables.domainkey_kitty = {
|
||||
type = "string";
|
||||
value.shellCommand = "bitw get infra/domainkey-kitty";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_mx = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
mx = {
|
||||
priority = 10;
|
||||
target = "athame.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_spf = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
txt.value = "v=spf1 ip4:168.119.126.111 ip6:${
|
||||
(head config.networking.interfaces.enp1s0.ipv6.addresses).address
|
||||
} -all";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_dmarc = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "_dmarc";
|
||||
txt.value = "v=DMARC1; p=none";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_domainkey = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "mail._domainkey";
|
||||
txt.value = tf.variables.domainkey_kitty.ref;
|
||||
};
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "athame.kittywit.ch";
|
||||
domains = [ "kittywit.ch" "dork.dev" ];
|
||||
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
||||
# down nginx and opens port 80.
|
||||
certificateScheme = 3;
|
||||
|
||||
# Enable IMAP and POP3
|
||||
enableImap = true;
|
||||
enablePop3 = true;
|
||||
enableImapSsl = true;
|
||||
enablePop3Ssl = true;
|
||||
|
||||
# Enable the ManageSieve protocol
|
||||
enableManageSieve = true;
|
||||
|
||||
# whether to scan inbound emails for viruses (note that this requires at least
|
||||
# 1 Gb RAM for the server. Without virus scanning 256 MB RAM should be plenty)
|
||||
virusScanning = false;
|
||||
};
|
||||
}
|
||||
148
config/services/matrix.nix
Normal file
148
config/services/matrix.nix
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
environment.systemPackages = [ pkgs.mx-puppet-discord pkgs.mautrix-whatsapp ];
|
||||
|
||||
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||
TEMPLATE template0
|
||||
LC_COLLATE = "C"
|
||||
LC_CTYPE = "C";
|
||||
'';
|
||||
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
max_upload_size = "512M";
|
||||
server_name = "kittywit.ch";
|
||||
app_service_config_files = [
|
||||
"/var/lib/matrix-synapse/telegram-registration.yaml"
|
||||
"/var/lib/matrix-synapse/discord-registration.yaml"
|
||||
"/var/lib/matrix-synapse/whatsapp-registration.yaml"
|
||||
];
|
||||
rc_messages_per_second = mkDefault "0.1";
|
||||
rc_message_burst_count = mkDefault "25.0";
|
||||
url_preview_enabled = mkDefault true;
|
||||
enable_registration = mkDefault false;
|
||||
enable_metrics = mkDefault false;
|
||||
report_stats = mkDefault false;
|
||||
dynamic_thumbnails = mkDefault true;
|
||||
allow_guest_access = mkDefault true;
|
||||
extraConfig = ''
|
||||
suppress_key_server_warning: true
|
||||
'';
|
||||
listeners = [{
|
||||
port = 8008;
|
||||
bind_address = "::1";
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
resources = [{
|
||||
names = [ "client" "federation" ];
|
||||
compress = false;
|
||||
}];
|
||||
}];
|
||||
};
|
||||
|
||||
services.mautrix-telegram = {
|
||||
enable = true;
|
||||
settings = {
|
||||
homeserver = {
|
||||
address = "http://localhost:8008";
|
||||
domain = "kittywit.ch";
|
||||
};
|
||||
appservice = {
|
||||
provisioning.enabled = false;
|
||||
id = "telegram";
|
||||
public = {
|
||||
enabled = false;
|
||||
prefix = "/public";
|
||||
external = "https://kittywit.ch/public";
|
||||
};
|
||||
};
|
||||
bridge = {
|
||||
relaybot.authless_portals = false;
|
||||
permissions = {
|
||||
"@kat:kittywit.ch" = "admin";
|
||||
"kittywit.ch" = "full";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mx-puppet-discord = {
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
"${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -c /var/lib/mx-puppet-discord/config.yaml -f /var/lib/mx-puppet-discord/discord-registration.yaml";
|
||||
WorkingDirectory = "/var/lib/mx-puppet-discord";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "mx-puppet-discord";
|
||||
UMask = 27;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
};
|
||||
requisite = [ "matrix-synapse.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
};
|
||||
|
||||
systemd.services.mautrix-whatsapp = {
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
"${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp -c /var/lib/mautrix-whatsapp/config.yaml -r /var/lib/mautrix-whatsapp/registration.yaml";
|
||||
WorkingDirectory = "/var/lib/mautrix-whatsapp";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "mautrix-whatsapp";
|
||||
UMask = 27;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
};
|
||||
requisite = [ "matrix-synapse.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."kittywit.ch" = {
|
||||
# allegedly fixes https://github.com/poljar/weechat-matrix/issues/240
|
||||
extraConfig = ''
|
||||
keepalive_requests 100000;
|
||||
'';
|
||||
|
||||
locations = {
|
||||
"/_matrix" = { proxyPass = "http://[::1]:8008"; };
|
||||
"= /.well-known/matrix/server".extraConfig =
|
||||
let server = { "m.server" = "kittywit.ch:443"; };
|
||||
in
|
||||
''
|
||||
add_header Content-Type application/json;
|
||||
return 200 '${builtins.toJSON server}';
|
||||
'';
|
||||
"= /.well-known/matrix/client".extraConfig =
|
||||
let
|
||||
client = {
|
||||
"m.homeserver" = { "base_url" = "https://kittywit.ch"; };
|
||||
"m.identity_server" = { "base_url" = "https://vector.im"; };
|
||||
};
|
||||
in
|
||||
''
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '${builtins.toJSON client}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
60
config/services/murmur.nix
Normal file
60
config/services/murmur.nix
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
kw.fw.public.tcp.ports = singleton 64738;
|
||||
kw.fw.public.udp.ports = singleton 64738;
|
||||
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
hostName = "voice.kittywit.ch";
|
||||
bandwidth = 130000;
|
||||
welcometext = "mew!";
|
||||
extraConfig = ''
|
||||
sslCert=/var/lib/acme/voice.kittywit.ch/fullchain.pem
|
||||
sslKey=/var/lib/acme/voice.kittywit.ch/key.pem
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."voice.kittywit.ch" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
users.groups."voice-cert".members = [ "nginx" "murmur" ];
|
||||
|
||||
security.acme.certs = { "voice.kittywit.ch" = { group = "voice-cert"; }; };
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "voice";
|
||||
cname.target = "athame.kittywit.ch.";
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice_tcp = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "mumble";
|
||||
proto = "tcp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 64738;
|
||||
target = "voice.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
|
||||
deploy.tf.dns.records.kittywitch_voice_udp = {
|
||||
tld = "kittywit.ch.";
|
||||
domain = "@";
|
||||
srv = {
|
||||
service = "mumble";
|
||||
proto = "udp";
|
||||
priority = 0;
|
||||
weight = 5;
|
||||
port = 64738;
|
||||
target = "voice.kittywit.ch.";
|
||||
};
|
||||
};
|
||||
}
|
||||
18
config/services/netdata.nix
Normal file
18
config/services/netdata.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
kw.fw.private.tcp.ports = [ 19999 ];
|
||||
|
||||
services.netdata = { enable = true; };
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts = {
|
||||
"${config.networking.hostName}.net.kittywit.ch" = {
|
||||
useACMEHost = "${config.networking.hostName}.net.kittywit.ch";
|
||||
forceSSL = true;
|
||||
locations = { "/netdata" = { proxyPass = "http://[::1]:19999/"; }; };
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
43
config/services/nginx.nix
Normal file
43
config/services/nginx.nix
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{ config, lib, pkgs, tf, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
secrets.files.dns_creds = {
|
||||
text = ''
|
||||
RFC2136_NAMESERVER='ns1.as207960.net'
|
||||
RFC2136_TSIG_ALGORITHM='hmac-sha512.'
|
||||
RFC2136_TSIG_KEY='${tf.variables.glauca_key.ref}'
|
||||
RFC2136_TSIG_SECRET='${tf.variables.glauca_secret.ref}'
|
||||
'';
|
||||
};
|
||||
|
||||
kw.fw.public.tcp.ports = [ 443 80 ];
|
||||
kw.fw.private.tcp.ports = [ 443 80 ];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
commonHttpConfig = ''
|
||||
map $scheme $hsts_header {
|
||||
https "max-age=31536000; includeSubdomains; preload";
|
||||
}
|
||||
add_header Strict-Transport-Security $hsts_header;
|
||||
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
|
||||
add_header 'Referrer-Policy' 'origin-when-cross-origin';
|
||||
#add_header X-Frame-Options DENY;
|
||||
#add_header X-Content-Type-Options nosniff;
|
||||
#add_header X-XSS-Protection "1; mode=block";
|
||||
#proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
|
||||
'';
|
||||
clientMaxBodySize = "512m";
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
email = "acme@kittywit.ch";
|
||||
acceptTerms = true;
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue