stuff
This commit is contained in:
parent
f44a65d108
commit
e0f1f5b6fb
49 changed files with 10 additions and 2 deletions
6
hosts/headless/abacus/acme.nix
Normal file
6
hosts/headless/abacus/acme.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
security.acme = {
|
||||
defaults.email = "lukas@wrz.one";
|
||||
acceptTerms = true;
|
||||
};
|
||||
}
|
24
hosts/headless/abacus/backup.nix
Normal file
24
hosts/headless/abacus/backup.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
attrName,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
age.secrets = lib.mkSecrets {"restic-${attrName}" = {};};
|
||||
|
||||
services.restic.backups.${attrName} = {
|
||||
repository = "sftp:u385962@u385962.your-storagebox.de:/restic/${attrName}";
|
||||
initialize = true;
|
||||
paths = [
|
||||
config.services.vaultwarden.backupDir
|
||||
config.services.syncthing.dataDir
|
||||
];
|
||||
passwordFile = config.age.secrets."restic-${attrName}".path;
|
||||
pruneOpts = ["--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12"];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 03:00:00";
|
||||
Persistent = true;
|
||||
};
|
||||
extraOptions = ["sftp.args='-i /etc/ssh/ssh_host_ed25519_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'"];
|
||||
};
|
||||
}
|
87
hosts/headless/abacus/forgejo.nix
Normal file
87
hosts/headless/abacus/forgejo.nix
Normal file
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "tea.${domain}";
|
||||
in {
|
||||
age.secrets = lib.mkSecrets {
|
||||
forgejo-mailer = {
|
||||
mode = "400";
|
||||
owner = "forgejo";
|
||||
};
|
||||
forgejo-admin = {
|
||||
mode = "400";
|
||||
owner = "forgejo";
|
||||
};
|
||||
};
|
||||
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
database.type = "postgres";
|
||||
lfs.enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = virtualHostName;
|
||||
ROOT_URL = "https://${virtualHostName}/";
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 8060;
|
||||
};
|
||||
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
};
|
||||
|
||||
# TODO: Enable
|
||||
federation = {
|
||||
ENABLED = false;
|
||||
SHARE_USER_STATISTICS = false;
|
||||
};
|
||||
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
SMTP_ADDR = "smtp.fastmail.com";
|
||||
FROM = "tea@${domain}";
|
||||
USER = "lukas@${domain}";
|
||||
};
|
||||
};
|
||||
secrets.mailer.PASSWD = config.age.secrets.forgejo-mailer.path;
|
||||
};
|
||||
|
||||
systemd.services.forgejo.preStart = let
|
||||
forgejo = lib.getExe config.services.forgejo.package;
|
||||
passwordFile = config.age.secrets.forgejo-admin.path;
|
||||
user = "lukas";
|
||||
email = "lukas@wrz.one";
|
||||
in ''
|
||||
if ! \
|
||||
${forgejo} admin user change-password \
|
||||
--username ${lib.escapeShellArg user} \
|
||||
--password "$(cat -- ${lib.escapeShellArg passwordFile})"
|
||||
then
|
||||
${forgejo} admin user create \
|
||||
--admin \
|
||||
--email ${lib.escapeShellArg email} \
|
||||
--username ${lib.escapeShellArg user} \
|
||||
--password "$(cat -- ${lib.escapeShellArg passwordFile})"
|
||||
fi
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
extraConfig = ''
|
||||
client_max_body_size 512M;
|
||||
'';
|
||||
|
||||
locations."/".proxyPass = let
|
||||
inherit (config.services.forgejo.settings.server) HTTP_ADDR HTTP_PORT;
|
||||
in "http://${lib.formatHostPort {
|
||||
host = HTTP_ADDR;
|
||||
port = HTTP_PORT;
|
||||
}}";
|
||||
};
|
||||
}
|
7
hosts/headless/abacus/fs.nix
Normal file
7
hosts/headless/abacus/fs.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{config, ...}: {
|
||||
fileSystems.${config.services.navidrome.settings.MusicFolder} = {
|
||||
label = "music";
|
||||
fsType = "ext4";
|
||||
options = ["noatime"];
|
||||
};
|
||||
}
|
9
hosts/headless/abacus/hardware.nix
Normal file
9
hosts/headless/abacus/hardware.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{modulesPath, ...}: {
|
||||
imports = ["${modulesPath}/profiles/qemu-guest.nix"];
|
||||
|
||||
nixpkgs.hostPlatform = "aarch64-linux";
|
||||
|
||||
boot.initrd.availableKernelModules = ["xhci_pci" "virtio_pci" "virtio_scsi" "usbhid" "sr_mod"];
|
||||
|
||||
powerManagement.cpuFreqGovernor = "performance";
|
||||
}
|
49
hosts/headless/abacus/microbin.nix
Normal file
49
hosts/headless/abacus/microbin.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "bin.${domain}";
|
||||
in {
|
||||
age.secrets = lib.mkSecrets {microbin = {};};
|
||||
|
||||
services.microbin = {
|
||||
enable = true;
|
||||
passwordFile = config.age.secrets.microbin.path;
|
||||
settings = {
|
||||
MICROBIN_BIND = "127.0.0.1";
|
||||
MICROBIN_PORT = 8020;
|
||||
|
||||
MICROBIN_PUBLIC_PATH = "https://${virtualHostName}/";
|
||||
|
||||
MICROBIN_READONLY = true;
|
||||
|
||||
MICROBIN_EDITABLE = true;
|
||||
MICROBIN_ETERNAL_PASTA = true;
|
||||
MICROBIN_HIGHLIGHTSYNTAX = true;
|
||||
MICROBIN_PRIVATE = true;
|
||||
MICROBIN_ENABLE_BURN_AFTER = true;
|
||||
MICROBIN_QR = true;
|
||||
MICROBIN_NO_FILE_UPLOAD = false;
|
||||
MICROBIN_ENCRYPTION_CLIENT_SIDE = true;
|
||||
|
||||
MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB = 1024;
|
||||
MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_MB = 4096;
|
||||
|
||||
MICROBIN_DISABLE_UPDATE_CHECKING = true;
|
||||
MICROBIN_DISABLE_TELEMETRY = true;
|
||||
MICROBIN_LIST_SERVER = false;
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${lib.formatHostPort {
|
||||
host = config.services.microbin.settings.MICROBIN_BIND;
|
||||
port = config.services.microbin.settings.MICROBIN_PORT;
|
||||
}}";
|
||||
};
|
||||
}
|
29
hosts/headless/abacus/miniflux.nix
Normal file
29
hosts/headless/abacus/miniflux.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "flux.${domain}";
|
||||
in {
|
||||
age.secrets = lib.mkSecrets {miniflux = {};};
|
||||
|
||||
services.miniflux = {
|
||||
enable = true;
|
||||
createDatabaseLocally = true;
|
||||
adminCredentialsFile = config.age.secrets.miniflux.path;
|
||||
config = {
|
||||
LISTEN_ADDR = "localhost:8030";
|
||||
BASE_URL = "https://${virtualHostName}";
|
||||
CREATE_ADMIN = 1;
|
||||
WEBAUTHN = 1;
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${config.services.miniflux.config.LISTEN_ADDR}";
|
||||
};
|
||||
}
|
27
hosts/headless/abacus/navidrome.nix
Normal file
27
hosts/headless/abacus/navidrome.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "navi.${domain}";
|
||||
in {
|
||||
services.navidrome = {
|
||||
enable = true;
|
||||
settings = {
|
||||
Address = "localhost";
|
||||
Port = 8050;
|
||||
MusicFolder = "/srv/music";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${lib.formatHostPort {
|
||||
host = config.services.navidrome.settings.Address;
|
||||
port = config.services.navidrome.settings.Port;
|
||||
}}";
|
||||
};
|
||||
}
|
18
hosts/headless/abacus/networking.nix
Normal file
18
hosts/headless/abacus/networking.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
networking = let
|
||||
interface = "enp1s0";
|
||||
in {
|
||||
domain = "wrz.one";
|
||||
interfaces.${interface}.ipv6.addresses = [
|
||||
{
|
||||
address = "2a01:4f9:c012:92b5::2";
|
||||
prefixLength = 64;
|
||||
}
|
||||
];
|
||||
defaultGateway6 = {
|
||||
address = "fe80::1";
|
||||
inherit interface;
|
||||
};
|
||||
firewall.allowedTCPPorts = [80 443];
|
||||
};
|
||||
}
|
22
hosts/headless/abacus/nginx.nix
Normal file
22
hosts/headless/abacus/nginx.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{config, ...}: {
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
commonHttpConfig = ''
|
||||
error_log stderr;
|
||||
access_log /var/log/nginx/access.log;
|
||||
'';
|
||||
|
||||
virtualHosts."~.*" = {
|
||||
default = true;
|
||||
rejectSSL = true;
|
||||
|
||||
globalRedirect = config.networking.domain;
|
||||
};
|
||||
};
|
||||
}
|
31
hosts/headless/abacus/static.nix
Normal file
31
hosts/headless/abacus/static.nix
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
parent = "/var/www";
|
||||
sites = [
|
||||
domain
|
||||
"log.${domain}"
|
||||
];
|
||||
in
|
||||
lib.mkMerge (map (
|
||||
virtualHostName: let
|
||||
root = "${parent}/${virtualHostName}";
|
||||
in {
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
inherit root;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."10-static-sites".${root}.d = {
|
||||
user = config.users.mainUser;
|
||||
group = "users";
|
||||
mode = "0755";
|
||||
};
|
||||
}
|
||||
)
|
||||
sites)
|
18
hosts/headless/abacus/syncthing.nix
Normal file
18
hosts/headless/abacus/syncthing.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{config, ...}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "sync.${domain}";
|
||||
in {
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
systemService = true;
|
||||
openDefaultPorts = true;
|
||||
guiAddress = "localhost:8040";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${config.services.syncthing.guiAddress}";
|
||||
};
|
||||
}
|
3
hosts/headless/abacus/system.nix
Normal file
3
hosts/headless/abacus/system.nix
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
system.stateVersion = "24.11";
|
||||
}
|
48
hosts/headless/abacus/vaultwarden.nix
Normal file
48
hosts/headless/abacus/vaultwarden.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (config.networking) domain;
|
||||
virtualHostName = "vault.${domain}";
|
||||
backupDir = "/srv/backup/vaultwarden";
|
||||
in {
|
||||
age.secrets = lib.mkSecrets {vaultwarden = {};};
|
||||
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
|
||||
dbBackend = "sqlite";
|
||||
|
||||
inherit backupDir;
|
||||
|
||||
config = {
|
||||
DOMAIN = "https://${virtualHostName}";
|
||||
|
||||
SIGNUPS_ALLOWED = false;
|
||||
INVITATIONS_ALLOWED = false;
|
||||
|
||||
ENABLE_WEBSOCKET = true;
|
||||
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = 8000;
|
||||
};
|
||||
|
||||
environmentFile = config.age.secrets.vaultwarden.path;
|
||||
};
|
||||
|
||||
systemd.timers.backup-vaultwarden.timerConfig.OnCalendar = "*-*-* 02:00:00";
|
||||
|
||||
services.nginx.virtualHosts.${virtualHostName} = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://${lib.formatHostPort {
|
||||
host = config.services.vaultwarden.config.ROCKET_ADDRESS;
|
||||
port = config.services.vaultwarden.config.ROCKET_PORT;
|
||||
}}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
61
hosts/headless/vessel/backup.nix
Normal file
61
hosts/headless/vessel/backup.nix
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
attrName,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
backups = {
|
||||
music = "/srv/music";
|
||||
safe = "/srv/safe";
|
||||
storage = "/srv/storage";
|
||||
sync = config.services.syncthing.dataDir;
|
||||
};
|
||||
in {
|
||||
systemd = lib.mkMerge (map (
|
||||
backupName: let
|
||||
systemdName = "${backupName}-backup";
|
||||
in {
|
||||
timers.${systemdName} = {
|
||||
description = "Local rsync Backup ${backupName}";
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 03:00:00"; # TODO
|
||||
Persistent = true;
|
||||
Unit = "${systemdName}.service"; # TODO
|
||||
};
|
||||
};
|
||||
|
||||
services.${systemdName} = {
|
||||
description = "Local rsync Backup ${backupName}";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
# TODO
|
||||
script = ''
|
||||
${lib.getExe pkgs.rsync} --verbose --verbose --archive --update --delete --mkpath -- ${backups.${backupName}}/ /srv/backup/${backupName}/
|
||||
'';
|
||||
};
|
||||
}
|
||||
) (lib.attrNames backups));
|
||||
|
||||
age.secrets = lib.mkSecrets {"restic-${attrName}" = {};};
|
||||
|
||||
services.restic.backups.${attrName} = {
|
||||
repository = "sftp:u385962@u385962.your-storagebox.de:/restic/${attrName}";
|
||||
initialize = true;
|
||||
paths = [
|
||||
backups.safe
|
||||
backups.sync
|
||||
];
|
||||
passwordFile = config.age.secrets."restic-${attrName}".path;
|
||||
pruneOpts = ["--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12"];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 03:00:00"; # TODO
|
||||
Persistent = true;
|
||||
};
|
||||
extraOptions = ["sftp.args='-i /etc/ssh/ssh_host_ed25519_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'"];
|
||||
};
|
||||
}
|
27
hosts/headless/vessel/blocky.nix
Normal file
27
hosts/headless/vessel/blocky.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
let
|
||||
upstream = "https://one.one.one.one/dns-query";
|
||||
in {
|
||||
services = {
|
||||
resolved.extraConfig = "DNSStubListener=no";
|
||||
blocky = {
|
||||
enable = true;
|
||||
settings = {
|
||||
ports.dns = 53;
|
||||
upstreams.groups.default = [upstream];
|
||||
bootstrapDns = {
|
||||
inherit upstream;
|
||||
ips = ["1.1.1.1" "1.0.0.1"];
|
||||
};
|
||||
blocking = {
|
||||
denylists.ads = ["https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"];
|
||||
clientGroupsBlock.default = ["ads"];
|
||||
};
|
||||
caching = {
|
||||
minTime = "5m";
|
||||
maxTime = "30m";
|
||||
prefetching = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
7
hosts/headless/vessel/fs.nix
Normal file
7
hosts/headless/vessel/fs.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
fileSystems."/srv/backup" = {
|
||||
label = "backup";
|
||||
fsType = "ext4";
|
||||
options = ["noatime"];
|
||||
};
|
||||
}
|
22
hosts/headless/vessel/hardware.nix
Normal file
22
hosts/headless/vessel/hardware.nix
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
inputs,
|
||||
modulesPath,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
"${modulesPath}/installer/scan/not-detected.nix"
|
||||
|
||||
inputs.hardware.nixosModules.common-cpu-intel
|
||||
inputs.hardware.nixosModules.common-gpu-intel
|
||||
inputs.hardware.nixosModules.common-pc-ssd
|
||||
];
|
||||
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
|
||||
boot = {
|
||||
initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod"];
|
||||
kernelModules = ["kvm-intel"];
|
||||
};
|
||||
|
||||
powerManagement.cpuFreqGovernor = "powersave";
|
||||
}
|
32
hosts/headless/vessel/musicomp.nix
Normal file
32
hosts/headless/vessel/musicomp.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
self,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
services.musicomp.jobs.main = {
|
||||
music = "/srv/music";
|
||||
comp = "/srv/compmusic";
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
inhibitsSleep = true;
|
||||
post = let
|
||||
remoteDir = self.nixosConfigurations.abacus.config.services.navidrome.settings.MusicFolder;
|
||||
rsyncExe = lib.getExe pkgs.rsync;
|
||||
rsh = "${lib.getExe pkgs.openssh} -i /etc/ssh/ssh_host_ed25519_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
|
||||
in ''
|
||||
${rsyncExe} \
|
||||
--archive \
|
||||
--recursive \
|
||||
--delete \
|
||||
--update \
|
||||
--mkpath \
|
||||
--verbose --verbose \
|
||||
--exclude lost+found \
|
||||
--rsh ${lib.escapeShellArg rsh} \
|
||||
/srv/compmusic/ root@wrz.one:${remoteDir}
|
||||
'';
|
||||
};
|
||||
}
|
27
hosts/headless/vessel/storage.nix
Normal file
27
hosts/headless/vessel/storage.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
systemd.tmpfiles.settings = {
|
||||
"10-safe"."/srv/safe".d = {
|
||||
user = "lukas";
|
||||
group = "users";
|
||||
mode = "0755";
|
||||
};
|
||||
|
||||
"10-storage"."/srv/storage".d = {
|
||||
user = "lukas";
|
||||
group = "users";
|
||||
mode = "0755";
|
||||
};
|
||||
|
||||
"10-music"."/srv/music".d = {
|
||||
user = "lukas";
|
||||
group = "users";
|
||||
mode = "0755";
|
||||
};
|
||||
|
||||
"10-compmusic"."/srv/compmusic".d = {
|
||||
user = "lukas";
|
||||
group = "users";
|
||||
mode = "0755";
|
||||
};
|
||||
};
|
||||
}
|
15
hosts/headless/vessel/syncthing.nix
Normal file
15
hosts/headless/vessel/syncthing.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{lib, ...}: let
|
||||
guiPort = 8384;
|
||||
in {
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
systemService = true;
|
||||
openDefaultPorts = true;
|
||||
guiAddress = lib.formatHostPort {
|
||||
host = "0.0.0.0";
|
||||
port = guiPort;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [guiPort];
|
||||
}
|
3
hosts/headless/vessel/system.nix
Normal file
3
hosts/headless/vessel/system.nix
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
system.stateVersion = "24.11";
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue