Skip to content

Instantly share code, notes, and snippets.

@ibizaman
Last active June 13, 2026 21:06
Show Gist options
  • Select an option

  • Save ibizaman/83d13092e56e75f5c4abdc39f4ad4236 to your computer and use it in GitHub Desktop.

Select an option

Save ibizaman/83d13092e56e75f5c4abdc39f4ad4236 to your computer and use it in GitHub Desktop.
SelfHostBlocks example config
{
lib,
config,
utils,
pkgs,
...
}:
let
domain = "example.com";
dcdomain = "dc=example,dc=com";
friendlyName = "Example";
email = "me@example.com";
hostname = "mycomputer";
username = "myself";
firstName = "Me";
backupCfg =
{
enable ? true,
shbOpt ? null,
timerConfig ? {
OnBootSec = "15min";
OnUnitActiveSec = "1h";
RandomizedDelaySec = "7min";
},
s3TimerConfig ? {
OnCalendar = "*-*-* 03:00:00";
RandomizedDelaySec = "1h";
},
}:
name:
let
bck = (if shbOpt != null then shbOpt else config.shb.${name}).backup.request;
in
{
shb.restic.instances."${name}-local" = {
request = bck;
settings = {
enable = if enable then true else shbOpt.enable;
passphrase.result = config.shb.sops.secret."restic/passphrases/${name}".result;
repository = {
path = "/srv/backup/restic/${hostname}/${name}";
timerConfig = timerConfig // {
FixedRandomDelay = true;
};
};
retention = {
keep_within = "1d";
keep_hourly = 24;
keep_daily = 7;
keep_weekly = 4;
keep_monthly = 6;
};
limitUploadKiBs = 8000;
limitDownloadKiBs = 8000;
};
};
shb.restic.instances."${name}-s3" = {
request = bck;
settings = {
enable = if enable then true else shbOpt.enable;
passphrase.result = config.shb.sops.secret."restic/passphrases/${name}".result;
repository = {
path = "s3:s3.us-west-000.backblazeb2.com/${hostname}-backup/${name}";
timerConfig = s3TimerConfig // {
FixedRandomDelay = true;
};
secrets = {
AWS_ACCESS_KEY_ID.source = config.sops.secrets."backup/b2/access_key_id/${name}".path;
AWS_SECRET_ACCESS_KEY.source = config.sops.secrets."backup/b2/secret_access_key/${name}".path;
};
};
retention = {
keep_within = "1d";
keep_hourly = 24;
keep_daily = 7;
keep_weekly = 4;
keep_monthly = 6;
};
limitUploadKiBs = 3000;
limitDownloadKiBs = 3000;
};
};
shb.sops.secret."restic/passphrases/${name}" = {
request = config.shb.restic.instances."${name}-local".settings.passphrase.request;
};
shb.sops.secret."backup/b2/access_key_id/${name}" = {
request = config.shb.restic.instances."${name}-local".settings.passphrase.request;
settings.key = "backup/b2/access_key_id";
};
shb.sops.secret."backup/b2/secret_access_key/${name}" = {
request = config.shb.restic.instances."${name}-local".settings.passphrase.request;
settings.key = "backup/b2/secret_access_key";
};
};
in
{
config = lib.mkMerge [
{
networking.firewall.enable = false;
# DNS and DHCP
networking.firewall.allowedUDPPorts = [
53
67
];
}
{
powerManagement.cpuFreqGovernor = "performance";
hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware;
environment.systemPackages = with pkgs; [
curl
git
htop
jq
lsof
ncdu
sqlite
sysz
usbutils
vim
];
sops.defaultSopsFile = ../../secrets/secrets.yaml;
sops.age = {
sshKeyPaths = [ "/boot/host_key" ];
};
services.openssh.listenAddresses = [
{
addr = "0.0.0.0"; # Needs to be 0.0.0.0 otherwise it cannot bind on boot.
port = 22;
}
{
addr = "0.0.0.0";
port = 22345;
}
];
networking.firewall.allowedTCPPorts = [
22
22345
];
shb.nginx.accessLog = true;
shb.nginx.debugLog = false;
shb.postgresql.debug = false;
hardware.bluetooth.enable = true;
}
{
nix.settings.trusted-public-keys = [
"selfhostblocks.cachix.org-1:H5h6Uj188DObUJDbEbSAwc377uvcjSFOfpxyCFP7cVs="
];
nix.settings.substituters = [
"https://selfhostblocks.cachix.org"
];
}
{
skarabox = {
inherit hostname username;
hashedPasswordFile = config.sops.secrets."${hostname}/user/hashedPassword".path;
facter-config = ./facter.json;
sshAuthorizedKey = [
./ssh-key.pub
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcenez8sAc8eXutU8vji378LNMbgdQrZYVy3s0spEvR"
];
sshPort = 22345;
boot.sshPort = 22346;
disks = {
rootPool = {
disk1 = "/dev/nvme0n1";
reservation = "100G";
};
dataPool = {
enable = false;
name = "data";
reservation = "1T";
};
initialBackupDataset = false;
};
staticNetwork = {
ip = "192.168.1.30";
gateway = "192.168.1.1";
};
hostId = "2f44b30a";
machineId = "2f44b30a07b946e3a142fe2e44a9c6ea";
};
sops.secrets."${hostname}/user/hashedPassword" = {
neededForUsers = true;
};
users.users.root = {
hashedPasswordFile = config.sops.secrets."${hostname}/root/hashedPassword".path;
};
sops.secrets."${hostname}/root/hashedPassword" = {
neededForUsers = true;
};
}
(lib.optionalAttrs true {
networking.firewall.allowedUDPPorts = [ 53 ];
# Need to wait on auth endpoint to be available otherwise nginx can fail to start.
systemd.services.nginx = {
wants = [ "dnsmasq.service" ];
after = [ "dnsmasq.service" ];
};
services.resolved.enable = false;
services.dnsmasq = {
enable = true;
settings = {
cache-size = 1000;
# When switching DNS server, accept old leases from previous server.
dhcp-authoritative = true;
dhcp-range = "192.168.1.101,192.168.1.150,255.255.255.0,6h";
dhcp-host = [
"74:3a:f4:73:46:50,laspin,192.168.1.50,infinite"
"ca:6f:2a:43:12:50,timios,192.168.1.51,infinite"
"6c:a6:04:df:67:46,TVBox,192.168.1.70,infinite"
];
dhcp-option = [
"3,192.168.1.1"
];
server = [
# NextDNS
# "2a07:a8c1::"
# "45.90.30.0"
# "2a07:a8c0::"
# "45.90.28.0"
# Quad9
# https://quad9.net/service/service-addresses-and-features/#ip
# "9.9.9.9"
# "149.112.112.112"
# "2620:fe::fe"
# "2620:fe::9"
# Stubby
# Also https://wiki.archlinux.org/title/Stubby#Change_port
"127.0.0.1#53000"
"::1#53000"
];
log-queries = true;
# For stubby
proxy-dnssec = true;
inherit domain;
no-resolv = true;
bogus-priv = true;
# Got issues with bind-interface on startup, needing to restart dnsmasq for it to listen correctly.
# bind-interfaces = true;
# add-cpe-id = 858972;
address = [
"/.${domain}/${config.skarabox.staticNetwork.ip}"
];
cname = [
"blog.${domain},ibizaman.github.io"
];
};
};
services.stubby = {
enable = true;
# https://github.com/getdnsapi/stubby/blob/develop/stubby.yml.example
settings = pkgs.stubby.passthru.settingsExample // {
listen_addresses = [
"127.0.0.1@53000"
"0::1@53000"
];
# https://dnsprivacy.org/public_resolvers/
# digest from https://nixos.wiki/wiki/Encrypted_DNS#Stubby
upstream_recursive_servers = [
{
address_data = "9.9.9.9";
tls_auth_name = "dns.quad9.net";
tls_pubkey_pinset = [
{
digest = "sha256";
value = "i2kObfz0qIKCGNWt7MjBUeSrh0Dyjb0/zWINImZES+I=";
}
];
}
{
address_data = "149.112.112.112";
tls_auth_name = "dns.quad9.net";
tls_pubkey_pinset = [
{
digest = "sha256";
value = "i2kObfz0qIKCGNWt7MjBUeSrh0Dyjb0/zWINImZES+I=";
}
];
}
];
};
};
})
{
services.sanoid = {
enable = true;
templates.main = {
autosnap = true;
autoprune = true;
hourly = 5;
daily = 10;
monthly = 15;
yearly = 20;
};
};
shb.zfs.snapshotBeforeActivation = {
enable = true;
recursive = true;
};
shb.zfs.pools.backup.datasets."data" = {
path = "/srv/backup";
};
shb.zfs.pools.backup.datasets."syncoid" = {
path = "none";
};
shb.zfs.pools.backup.datasets."syncoid/root" = {
path = "none";
};
shb.zfs.pools.backup.datasets."syncoid/data" = {
path = "none";
};
services.syncoid = {
enable = true;
commands."root" = {
recursive = true;
target = "backup/syncoid/root";
};
commands."data/games" = {
recursive = true;
target = "backup/syncoid/data/games";
};
commands."data/music" = {
recursive = true;
target = "backup/syncoid/data/music";
};
commands."data/nextcloud" = {
recursive = true;
target = "backup/syncoid/data/nextcloud";
};
commands."data/pinchflat" = {
recursive = true;
target = "backup/syncoid/data/pinchflat";
};
commands."data/projects" = {
recursive = true;
target = "backup/syncoid/data/projects";
};
};
}
{
boot.swraid.enable = true;
environment.systemPackages = [ pkgs.borgbackup ];
users.users.vorta = {
isSystemUser = true;
useDefaultShell = true;
home = "/srv/backup/${username}";
homeMode = "770";
createHome = false;
group = "backup";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDXGZ+Sqlz8HmS3HDEIX0FXyDECmHMw9C6DaU84S2w8c"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEDKB9Jjd+S+wPfWDZYbN+f6xkf/HnpuU1JgplLCwFev"
];
};
users.groups.backup = { };
users.groups.media.members = [ "backup" ];
}
(
let
name = "postgres";
in
{
services.postgresql.package = pkgs.postgresql_15;
shb.zfs.pools.root.datasets."safe/postgresql".path = "/var/lib/postgresql";
shb.sanoid.backup."root/safe/postgresql" = {
request = config.shb.zfs.pools.root.datasets."safe/postgresql".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.restic.databases."postgres" = {
request = config.shb.postgresql.databasebackup.request;
settings = {
enable = true;
passphrase.result = config.shb.sops.secret."restic/passphrases/${name}".result;
repository = {
path = "/srv/backup/restic/${hostname}/${name}";
timerConfig = {
OnBootSec = "15min";
OnUnitActiveSec = "1h";
RandomizedDelaySec = "7min";
};
};
retention = {
keep_within = "1d";
keep_hourly = 24;
keep_daily = 7;
keep_weekly = 4;
keep_monthly = 6;
};
limitUploadKiBs = 8000;
limitDownloadKiBs = 8000;
};
};
shb.sops.secret."restic/passphrases/${name}".request =
config.shb.restic.databases.${name}.settings.passphrase.request;
shb.sops.secret."backup/b2/access_key_id/${name}" = {
request = config.shb.restic.databases.${name}.settings.passphrase.request;
settings.key = "backup/b2/access_key_id";
};
shb.sops.secret."backup/b2/secret_access_key/${name}" = {
request = config.shb.restic.databases.${name}.settings.passphrase.request;
settings.key = "backup/b2/secret_access_key";
};
shb.sops.secret."backup/skaraboxJean/access_key_id/${name}" = {
request = config.shb.restic.databases.${name}.settings.passphrase.request;
settings.key = "backup/skaraboxJean/access_key_id";
};
shb.sops.secret."backup/skaraboxJean/secret_access_key/${name}" = {
request = config.shb.restic.databases.${name}.settings.passphrase.request;
settings.key = "backup/skaraboxJean/secret_access_key";
};
}
)
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain} = {
inherit domain;
group = "nginx";
reloadServices = [ "nginx.service" ];
adminEmail = "shb@${domain}";
afterAndWants = lib.optionals config.services.dnsmasq.enable [ "dnsmasq.service" ];
};
shb.zfs.pools.root.datasets."safe/acme".path = "/var/lib/acme";
shb.sanoid.backup."root/safe/acme" = {
request = config.shb.zfs.pools.root.datasets."safe/acme".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
})
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "ldap.${domain}" ];
shb.lldap = {
enable = true;
inherit domain;
subdomain = "ldap";
ssl = config.shb.certs.certs.letsencrypt.${domain};
ldapPort = 3890;
webUIListenPort = 17170;
inherit dcdomain;
ldapUserPassword.result = config.shb.sops.secret."lldap/user_password".result;
jwtSecret.result = config.shb.sops.secret."lldap/jwt_secret".result;
# restrictAccessIPRange = "192.168.50.0/24";
debug = false;
ensureUsers = {
${username} = {
inherit email;
password.result = config.shb.sops.secret."users/${username}/password".result;
displayName = firstName;
groups = [
"arr_admin"
"arr_user"
"deluge_admin"
"deluge_user"
"forgejo_admin"
"forgejo_user"
"hledger_user"
"homeassistant_admin"
"homeassistant_user"
"jellyfin_admin"
"jellyfin_user"
"pinchflat_user"
"music-assistant_user"
"nextcloud_admin"
"nextcloud_user"
"vaultwarden_admin"
"vaultwarden_user"
];
};
};
};
shb.sops.secret."lldap/user_password".request = config.shb.lldap.ldapUserPassword.request;
shb.sops.secret."lldap/jwt_secret".request = config.shb.lldap.jwtSecret.request;
shb.sops.secret."users/${username}/password".request = config.shb.lldap.ensureUsers.${username}.password.request;
shb.zfs.pools.root.datasets."safe/lldap".path = "/var/lib/private/lldap";
shb.sanoid.backup."root/safe/lldap" = {
request = config.shb.zfs.pools.root.datasets."safe/lldap".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.homepage.servicesGroups.Admin.services.LLDAP = {
sortOrder = 2;
dashboard.request = config.shb.lldap.dashboard.request;
};
})
(backupCfg {
shbOpt.backup.request = {
user = "root";
sourceDirectories = [
"/var/lib/private/lldap"
];
};
} "lldap")
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "authelia.${domain}" ];
shb.authelia = {
enable = true;
inherit domain;
subdomain = "authelia";
ssl = config.shb.certs.certs.letsencrypt.${domain};
debug = false;
ldapHostname = "127.0.0.1";
ldapPort = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
smtp = {
host = "smtp.mailgun.org";
port = 587;
username = "postmaster@mg.${domain}";
from_address = "authelia@${domain}";
password.result = config.shb.sops.secret."authelia/smtp_password".result;
};
secrets = {
jwtSecret.result = config.shb.sops.secret."authelia/jwt_secret".result;
ldapAdminPassword.result = config.shb.sops.secret."authelia/ldap_admin_password".result;
sessionSecret.result = config.shb.sops.secret."authelia/session_secret".result;
storageEncryptionKey.result = config.shb.sops.secret."authelia/storage_encryption_key".result;
identityProvidersOIDCHMACSecret.result = config.shb.sops.secret."authelia/hmac_secret".result;
identityProvidersOIDCIssuerPrivateKey.result = config.shb.sops.secret."authelia/private_key".result;
};
};
shb.sops.secret."authelia/jwt_secret".request = config.shb.authelia.secrets.jwtSecret.request;
shb.sops.secret."authelia/ldap_admin_password".request =
config.shb.authelia.secrets.ldapAdminPassword.request;
shb.sops.secret."authelia/session_secret".request =
config.shb.authelia.secrets.sessionSecret.request;
shb.sops.secret."authelia/storage_encryption_key".request =
config.shb.authelia.secrets.storageEncryptionKey.request;
shb.sops.secret."authelia/hmac_secret".request =
config.shb.authelia.secrets.identityProvidersOIDCHMACSecret.request;
shb.sops.secret."authelia/private_key".request =
config.shb.authelia.secrets.identityProvidersOIDCIssuerPrivateKey.request;
shb.sops.secret."authelia/smtp_password".request = config.shb.authelia.smtp.password.request;
shb.zfs.pools.root.datasets."safe/redis-authelia".path = "/var/lib/redis-authelia";
shb.zfs.pools.root.datasets."safe/authelia-authelia.${domain}" = config.shb.authelia.mount;
shb.sanoid.backup."root/safe/redis-authelia" = {
request = config.shb.zfs.pools.root.datasets."safe/redis-authelia".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/authelia-authelia.${domain}" = {
request =
config.shb.zfs.pools.root.datasets."safe/authelia-authelia.${domain}".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.homepage.servicesGroups.Admin.services.Authelia = {
sortOrder = 2;
dashboard.request = config.shb.authelia.dashboard.request;
};
})
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "vaultwarden.${domain}" ];
shb.vaultwarden = {
enable = true;
inherit domain;
subdomain = "vaultwarden";
ssl = config.shb.certs.certs.letsencrypt.${domain};
port = 8222;
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
databasePassword.result = config.shb.sops.secret."vaultwarden/db".result;
smtp = {
from_address = "vaultwarden@${domain}";
host = "smtp.mailgun.org";
port = 587;
username = "postmaster@mg.${domain}";
password.result = config.shb.sops.secret."vaultwarden/smtp".result;
};
};
shb.sops.secret."vaultwarden/db".request = config.shb.vaultwarden.databasePassword.request;
shb.sops.secret."vaultwarden/smtp".request = config.shb.vaultwarden.smtp.password.request;
shb.zfs.pools.root.datasets."safe/postgresql".path = "/var/lib/postgresql";
shb.zfs.pools.root.datasets."safe/bitwarden_rs" = config.shb.vaultwarden.mount;
shb.sanoid.backup."root/safe/postgresql" = {
request = config.shb.zfs.pools.root.datasets."safe/postgresql".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/bitwarden_rs" = {
request = config.shb.zfs.pools.root.datasets."safe/bitwarden_rs".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureGroups = {
vaultwarden_user = { };
vaultwarden_admin = { };
};
shb.homepage.servicesGroups.Documents.services.Vaultwarden = {
sortOrder = 10;
dashboard.request = config.shb.vaultwarden.dashboard.request;
};
})
(backupCfg { } "vaultwarden")
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"ha.${domain}"
"ma.${domain}"
];
shb.home-assistant = {
enable = true;
inherit domain;
subdomain = "ha";
ssl = config.shb.certs.certs.letsencrypt.${domain};
config = {
name = friendlyName;
country.source = config.shb.sops.secret."home-assistant/country".result.path;
latitude.source = config.shb.sops.secret."home-assistant/latitude_home".result.path;
longitude.source = config.shb.sops.secret."home-assistant/longitude_home".result.path;
time_zone.source = config.shb.sops.secret."home-assistant/time_zone".result.path;
unit_system = "metric";
};
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.webUIListenPort;
userGroup = "homeassistant_user";
};
};
shb.sops.secret."home-assistant/country".request = {
mode = "0440";
owner = "hass";
group = "hass";
restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/latitude_home".request = {
mode = "0440";
owner = "hass";
group = "hass";
restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/longitude_home".request = {
mode = "0440";
owner = "hass";
group = "hass";
restartUnits = [ "home-assistant.service" ];
};
shb.sops.secret."home-assistant/time_zone".request = {
mode = "0440";
owner = "hass";
group = "hass";
restartUnits = [ "home-assistant.service" ];
};
services.home-assistant = {
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix
extraComponents = [
"accuweather"
"apple_tv"
"asuswrt"
"backup"
"bluetooth"
"cast"
"co2signal"
"deluge"
"esphome"
"ibeacon"
"icloud"
"ipp"
"jellyfin"
"kegtron"
"kodi"
"matter"
"mqtt"
"music_assistant"
"nmap_tracker"
"ollama"
"openweathermap"
"oralb"
"overkiz"
"philips_js"
"radarr"
"simplisafe"
"sonarr"
"sonos"
"subaru"
"tradfri"
"wled"
"zha"
"assist_pipeline"
"conversation"
"piper"
"wake_word"
"whisper"
"wyoming"
];
customComponents = with pkgs.home-assistant-custom-components; [
adaptive_lighting
# auth-header
(pkgs.buildHomeAssistantComponent rec {
owner = "rstrouse";
domain = "espsomfy_rts";
version = "v2.4.7";
src = pkgs.fetchFromGitHub {
owner = "ibizaman";
repo = "ESPSomfy-RTS-HA";
# rev = "refs/tags/${version}";
rev = "861a607fec5d7b72d093e83de0c34a6ca5a31b93";
hash = "sha256-12TF73Xr7gunfsDOmzH+VpfXjyhCA6RirPck8kF7tKM=";
};
buildInputs = [
pkgs.python314Packages.aiofiles
pkgs.python314Packages.websocket-client
];
meta = with lib; {
changelog = "https://github.com/rstrouse/ESPSomfy-RTS-HA/releases/tag/${version}";
description = "Home Assistant Somfy integration";
homepage = "https://github.com/rstrouse/ESPSomfy-RTS-HA";
maintainers = with maintainers; [ ibizaman ];
# license = licenses.unlicense;
};
})
(pkgs.buildHomeAssistantComponent rec {
owner = "JaccoR";
domain = "entsoe";
version = "v0.6.3";
src = pkgs.fetchFromGitHub {
owner = "JaccoR";
repo = "hass-entso-e";
rev = "refs/tags/${version}";
hash = "sha256-BOFXy2KlpMBLGHjq9oSAW34408tlS68Zl6L9c8+mXjI=";
};
buildInputs = [
pkgs.python314Packages.requests
# pkgs.python312Packages.websocket-client
];
meta = with lib; {
changelog = "https://github.com/JaccoR/hass-entso-e/releases/tag/${version}";
description = "Home Assistant ENTSO-e Transparency Platform Energy Prices";
homepage = "https://github.com/JaccoR/hass-entso-e";
maintainers = with maintainers; [ ibizaman ];
# license = licenses.unlicense;
};
})
];
# Need to add them manually by enabling advanced mode in user profile
# then adding in Settings > Dashboards > Resources:
# - /local/nixos-lovelace-modules/mini-graph-card-bundle.js
# - /local/nixos-lovelace-modules/mini-media-player-bundle.js
# - /local/nixos-lovelace-modules/hourly-weather.js
# - /local/nixos-lovelace-modules/weather-card.js
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
clock-weather-card
mini-graph-card
mini-media-player
horizon-card
hourly-weather
weather-card
mushroom
scheduler-card
];
extraPackages = python3Packages: [
];
};
# nixpkgs.config.permittedInsecurePackages = [
# "openssl-1.1.1w"
# ];
users.users.hass.extraGroups = [ "dialout" ];
shb.home-assistant.voice.text-to-speech = {
"fr" = {
enable = true;
voice = "fr-siwis-medium";
uri = "tcp://0.0.0.0:10200";
speaker = 0;
};
# "en" = {
# enable = true;
# voice = "en_GB-alba-medium";
# uri = "tcp://0.0.0.0:10201";
# speaker = 0;
# };
};
shb.home-assistant.voice.speech-to-text = {
"tiny-fr" = {
enable = true;
model = "base-int8";
language = "fr";
uri = "tcp://0.0.0.0:10300";
device = "cpu";
};
# "tiny-en" = {
# enable = true;
# model = "base-int8";
# language = "en";
# uri = "tcp://0.0.0.0:10301";
# device = "cpu";
# };
};
systemd.services.wyoming-faster-whisper-tiny-en.environment."HF_HUB_CACHE" = "/tmp";
systemd.services.wyoming-faster-whisper-tiny-fr.environment."HF_HUB_CACHE" = "/tmp";
shb.home-assistant.voice.wakeword = {
enable = true;
uri = "tcp://127.0.0.1:10400";
};
# nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [
# "python-nest"
# ];
services.matter-server = {
enable = true;
openFirewall = true;
};
services.music-assistant = {
enable = true;
providers = [
# https://github.com/NixOS/nixpkgs/commit/a9691ce732e26df12f0f2cbe4a91dc9f3d375527
# "airplay"
"hass"
"hass_players"
"jellyfin"
"radiobrowser"
"sonos"
"spotify"
];
};
shb.nginx.vhosts = [
{
subdomain = "ma";
inherit domain;
ssl = config.shb.certs.certs.letsencrypt.${domain};
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
upstream = "http://127.0.0.1:8095";
autheliaRules = [
{
domain = "ma.${domain}";
policy = "two_factor";
subject = [ "group:music-assistant_user" ];
}
];
}
];
shb.zfs.pools.root.datasets."safe/music-assistant".path = "/var/lib/private/music-assistant";
shb.sanoid.backup."root/safe/music-assistant" = {
request = config.shb.zfs.pools.root.datasets."safe/music-assistant".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureGroups = {
homeassistant_admin = { };
homeassistant_user = { };
music-assistant_user = { };
};
shb.homepage.servicesGroups.Home.services.HomeAssistant = {
sortOrder = 1;
dashboard.request = config.shb.home-assistant.dashboard.request;
apiKey.result = config.shb.sops.secret."home-assistant/homepageApiKey".result;
settings.icon = "si-homeassistant";
settings.widget.custom = [
{
template = "{{ states('sensor.power_consumption_power_consumption', with_unit=True, rounded=True) }}";
label = "energy now";
}
{
state = "sensor.power_consumption_daily_power_consumption";
label = "energy today";
}
];
};
shb.sops.secret."home-assistant/homepageApiKey".request =
config.shb.homepage.servicesGroups.Home.services.HomeAssistant.apiKey.request;
})
(backupCfg { shbOpt = config.shb.home-assistant; } "homeassistant")
(lib.optionalAttrs true {
users.groups.media.gid = 980;
})
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "jellyfin.${domain}" ];
shb.jellyfin = {
enable = true;
inherit domain;
subdomain = "jellyfin";
ssl = config.shb.certs.certs.letsencrypt.${domain};
admin = {
username = "jellyfin";
password.result = config.shb.sops.secret."jellyfin/admin/password".result;
};
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secret."jellyfin/ldap_password".result;
userGroup = "jellyfin_user";
adminGroup = "jellyfin_admin";
};
sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
clientID = "jellyfin";
sharedSecret.result = config.shb.sops.secret."jellyfin/sso_secret".result;
sharedSecretForAuthelia.result = config.shb.sops.secret."jellyfin/authelia/sso_secret".result;
};
};
shb.sops.secret."jellyfin/admin/password".request = config.shb.jellyfin.admin.password.request;
shb.sops.secret."jellyfin/ldap_password" = {
request = config.shb.jellyfin.ldap.adminPassword.request;
settings.key = "lldap/user_password";
};
shb.sops.secret."jellyfin/sso_secret".request = config.shb.jellyfin.sso.sharedSecret.request;
shb.sops.secret."jellyfin/authelia/sso_secret" = {
request = config.shb.jellyfin.sso.sharedSecretForAuthelia.request;
settings.key = "jellyfin/sso_secret";
};
shb.zfs.pools.root.datasets."safe/jellyfin".path = "/var/lib/jellyfin";
shb.sanoid.backup."root/safe/jellyfin" = {
request = config.shb.zfs.pools.root.datasets."safe/jellyfin".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureGroups = {
jellyfin_admin = { };
jellyfin_user = { };
};
shb.homepage.servicesGroups.Media.services.Jellyfin = {
sortOrder = 1;
dashboard.request = config.shb.jellyfin.dashboard.request;
apiKey.result = config.shb.sops.secret."jellyfin/homepageApiKey".result;
};
shb.sops.secret."jellyfin/homepageApiKey".request =
config.shb.homepage.servicesGroups.Media.services.Jellyfin.apiKey.request;
})
(backupCfg { } "jellyfin")
(lib.optionalAttrs true {
shb.zfs.pools.data.datasets."pinchflat-data" = {
path = config.shb.pinchflat.mediaDir;
};
shb.zfs.pools.data.datasets."pinchflat" = {
path = "/var/lib/pinchflat";
};
shb.sanoid.backup."root/safe/pinchflat-data" = {
request = config.shb.zfs.pools.root.datasets."safe/pinchflat-data".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/pinchflat" = {
request = config.shb.zfs.pools.root.datasets."safe/pinchflat".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "pinchflat.${domain}" ];
shb.pinchflat = {
enable = true;
inherit domain;
subdomain = "pinchflat";
ssl = config.shb.certs.certs.letsencrypt.${domain};
secretKeyBase.result = config.shb.sops.secret."pinchflat/secretKeyBase".result;
timeZone = "Europe/Zurich";
mediaDir = "/srv/pinchflat";
ldap = {
enable = true;
userGroup = "pinchflat_user";
};
sso = {
enable = true;
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
};
};
shb.sops.secret."pinchflat/secretKeyBase".request = config.shb.pinchflat.secretKeyBase.request;
shb.homepage.servicesGroups.Media.services.Pinchflat = {
sortOrder = 2;
dashboard.request = config.shb.pinchflat.dashboard.request;
};
})
# For Intel
(lib.optionalAttrs false {
# Verify configuration with `nix shell nixpkgs#libva-utils --command vainfo`
# see https://nixos.wiki/wiki/Accelerated_Video_Playback
nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
};
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver
vaapiIntel
vaapiVdpau
libvdpau-va-gl
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
];
};
})
# For AMD Ryzen 5
(lib.optionalAttrs true {
# Verify configuration with `nix shell nixpkgs#libva-utils --command vainfo`
# see https://nixos.wiki/wiki/Accelerated_Video_Playback
hardware.firmware = [ pkgs.linux-firmware ];
hardware.graphics.enable = true;
hardware.graphics.enable32Bit = true;
hardware.amdgpu.initrd.enable = true;
})
(lib.optionalAttrs true {
shb.zfs.pools.root.datasets."safe/nextcloud".path = "/var/lib/nextcloud";
shb.zfs.pools.root.datasets."safe/redis-nextcloud".path = "/var/lib/redis-nextcloud";
shb.sanoid.backup."root/safe/nextcloud" = {
request = config.shb.zfs.pools.root.datasets."safe/nextcloud".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/redis-nextcloud" = {
request = config.shb.zfs.pools.root.datasets."safe/redis-nextcloud".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "n.${domain}" ];
shb.nextcloud = {
enable = true;
debug = false;
inherit domain;
subdomain = "n";
ssl = config.shb.certs.certs.letsencrypt.${domain};
defaultPhoneRegion = "US";
version = 32;
dataDir = "/var/lib/nextcloud";
# mountPointServices = [ "srv-nextcloud.mount" ];
adminPass.result = config.shb.sops.secret."nextcloud/adminpass".result;
apps = {
previewgenerator.enable = true;
externalStorage = {
enable = true;
userLocalMount.directory = "/srv/nextcloud/data/$user/files";
userLocalMount.mountName = "/";
};
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminName = "admin";
adminPassword.result = config.shb.sops.secret."nextcloud/ldap_admin_password".result;
userGroup = "nextcloud_user";
};
sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
clientID = "nextcloud";
secret.result = config.shb.sops.secret."nextcloud/sso/secret".result;
secretForAuthelia.result = config.shb.sops.secret."authelia/nextcloud_sso_secret".result;
fallbackDefaultAuth = true;
};
memories = {
enable = false;
vaapi = true;
};
recognize = {
enable = false;
};
# mediadc.enable = true;
# mediadc.debug = true;
};
extraApps = apps: {
inherit (apps)
bookmarks
calendar
contacts
deck
groupfolders
mail
notes
tasks
;
};
# tracing = "debug_me";
postgresSettings = {
# From https://pgtune.leopard.in.ua/ with:
# DB Version: 14
# OS Type: linux
# DB Type: dw
# Total Memory (RAM): 12 GB
# CPUs num: 4
# Connections num: <none>
# Data Storage: ssd
max_connections = "400";
shared_buffers = "3GB";
effective_cache_size = "9GB";
maintenance_work_mem = "768MB";
checkpoint_completion_target = "0.9";
wal_buffers = "16MB";
default_statistics_target = "100";
random_page_cost = "1.1";
effective_io_concurrency = "200";
work_mem = "7864kB";
huge_pages = "off";
min_wal_size = "1GB";
max_wal_size = "4GB";
max_worker_processes = "4";
max_parallel_workers_per_gather = "2";
max_parallel_workers = "4";
max_parallel_maintenance_workers = "2";
};
# Chose static and small number of children to avoid too much I/O strain on hard drives.
phpFpmPoolSettings = {
"pm" = "static";
"pm.max_children" = 150;
# "pm.start_servers" = 50;
# "pm.min_spare_servers" = 30;
# "pm.max_spare_servers" = 70;
# "pm.max_spawn_rate" = 10;
# "pm.max_requests" = 100;
# "pm.process_idle_timeout" = "20s";
};
};
systemd.services.postgresql.serviceConfig.Restart = "always";
# Secret needed for services.nextcloud.config.adminpassFile.
shb.sops.secret."nextcloud/adminpass".request = config.shb.nextcloud.adminPass.request;
shb.sops.secret."nextcloud/ldap_admin_password" = {
request = config.shb.nextcloud.apps.ldap.adminPassword.request;
settings.key = "lldap/user_password";
};
shb.sops.secret."nextcloud/sso/secret".request = config.shb.nextcloud.apps.sso.secret.request;
shb.sops.secret."authelia/nextcloud_sso_secret" = {
request = config.shb.nextcloud.apps.sso.secretForAuthelia.request;
settings.key = "nextcloud/sso/secret";
};
# nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [
# "corefonts" # For onlyoffice
# ];
shb.lldap.ensureGroups = {
nextcloud_admin = { };
nextcloud_user = { };
};
shb.homepage.servicesGroups.Documents.services.Nextcloud = {
sortOrder = 1;
dashboard.request = config.shb.nextcloud.dashboard.request;
# apiKey.result = config.shb.sops.secret."nextcloud/homepageApiKey".result;
settings.username = username;
# settings.widget.type = "firefly";
};
# shb.sops.secret."nextcloud/homepageApiKey".request =
# config.shb.homepage.servicesGroups.Documents.services.Nextcloud.apiKey.request;
})
# (backupCfg { enable = false; } "nextcloud")
(lib.optionalAttrs false (
backupCfg {
shbOpt.backup.request = {
user = "nextcloud";
sourceDirectories = [
"/srv/nextcloud/data"
];
};
timerConfig = {
OnBootSec = "1h";
OnUnitActiveSec = "8h";
RandomizedDelaySec = "2h";
};
} "nextcloud-data"
))
(lib.optionalAttrs true {
shb.lldap.ensureUsers.${username}.groups = [
"monitoring_admin"
"monitoring_user"
];
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"grafana.${domain}"
"scrutiny.${domain}"
];
shb.monitoring = {
enable = true;
inherit domain;
subdomain = "grafana";
ssl = config.shb.certs.certs.letsencrypt.${domain};
contactPoints = [ email ];
adminPassword.result = config.shb.sops.secret."monitoring/admin_password".result;
secretKey.result = config.shb.sops.secret."monitoring/secret_key".result;
smtp = {
from_address = "grafana@${domain}";
from_name = "Grafana";
host = "smtp.mailgun.org";
port = 587;
username = "postmaster@mg.${domain}";
passwordFile = config.shb.sops.secret."monitoring/smtp".result.path;
};
sso = {
enable = true;
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
sharedSecret.result = config.shb.sops.secret."monitoring/ssoSecret".result;
sharedSecretForAuthelia.result = config.shb.sops.secret."monitoring/authelia/ssoSecret".result;
};
};
shb.sops.secret."monitoring/smtp".request = {
mode = "0400";
owner = "grafana";
group = "grafana";
restartUnits = [ "grafana.service" ];
};
shb.sops.secret."monitoring/admin_password".request = config.shb.monitoring.adminPassword.request;
shb.sops.secret."monitoring/secret_key".request = config.shb.monitoring.secretKey.request;
shb.sops.secret."monitoring/ssoSecret".request = config.shb.monitoring.sso.sharedSecret.request;
shb.sops.secret."monitoring/authelia/ssoSecret" = {
request = config.shb.monitoring.sso.sharedSecretForAuthelia.request;
settings.key = "monitoring/ssoSecret";
};
services.prometheus.retentionTime = "180d";
shb.zfs.pools.root.datasets."safe/grafana".path = "/var/lib/grafana";
shb.zfs.pools.root.datasets."safe/loki".path = "/var/lib/loki";
shb.zfs.pools.root.datasets."safe/netdata".path = "/var/lib/netdata";
shb.sanoid.backup."root/safe/grafana" = {
request = config.shb.zfs.pools.root.datasets."safe/grafana".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/loki" = {
request = config.shb.zfs.pools.root.datasets."safe/loki".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/netdata" = {
request = config.shb.zfs.pools.root.datasets."safe/netdata".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.homepage.servicesGroups.Admin.services.Grafana = {
sortOrder = 10;
dashboard.request = config.shb.monitoring.dashboard.request;
# apiKey.result = config.shb.sops.secret."homepage/grafanaApiKey".result;
};
shb.homepage.servicesGroups.Admin.services.Scrutiny = {
sortOrder = 11;
dashboard.request = config.shb.monitoring.scrutiny.dashboard.request;
};
# shb.sops.secret."homepage/grafanaApiKey" = {
# settings.key = "monitoring/homepageApiKey";
# request = config.shb.homepage.servicesGroups.Admin.services.Grafana.apiKey.request;
# };
})
{
users.users.hledger.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPghxSnq3K7t2Wjwdg7v9MGKM8BnuY28IVpo4yLYqv3W"
];
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "hledger.${domain}" ];
shb.hledger = {
enable = true;
inherit domain;
subdomain = "hledger";
ssl = config.shb.certs.certs.letsencrypt.${domain};
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
localNetworkIPRange = "192.168.1.0/24";
extraArguments = [
"--forecast"
"--auto"
"-X"
"CHF"
];
};
shb.zfs.pools.root.datasets."safe/hledger".path = "/var/lib/hledger";
shb.sanoid.backup."root/safe/hledger" = {
request = config.shb.zfs.pools.root.datasets."safe/hledger".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureGroups = {
hledger_user = { };
};
shb.homepage.servicesGroups.Finance.services.Hledger = {
sortOrder = 1;
dashboard.request = config.shb.hledger.dashboard.request;
# settings.widget.type = "hledger";
};
}
(backupCfg { } "hledger")
(lib.optionalAttrs true {
# Find best server: https://nordvpn.com/fr/servers/tools/
# Then ~/org/bin/nordvpnremoteip.sh y us8575
# shb.vpn.nordvpnus = {
# enable = true;
# provider = "nordvpn";
# dev = "tun1";
# routingNumber = 10;
# remoteServerIP = "91.196.220.28";
# authFile = config.sops.secrets."nordvpnus/auth".path;
# proxyPort = 12000;
# };
# sops.secrets."nordvpnus/auth" = {
# mode = "0440";
# restartUnits = [ "openvpn-nordvpnus.service" ];
# };
shb.vpn.nordvpnfr = {
enable = true;
provider = "nordvpn";
dev = "tun2";
routingNumber = 11;
remoteServerIP = "37.120.204.147";
authFile = config.shb.sops.secret."nordvpnfr/auth".result.path;
proxyPort = 12001;
};
shb.sops.secret."nordvpnfr/auth".request = {
mode = "0440";
restartUnits = [ "openvpn-nordvpnfr.service" ];
};
})
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "forgejo.${domain}" ];
shb.forgejo = {
enable = true;
subdomain = "forgejo";
inherit domain;
ssl = config.shb.certs.certs.letsencrypt."${domain}";
databasePassword.result = config.shb.sops.secret."forgejo/databasePassword".result;
repositoryRoot = "/srv/projects";
users = {
"forgejoadmin" = {
isAdmin = true;
email = "forgejoadmin@${domain}";
password.result = config.shb.sops.secret."forgejo/adminPassword".result;
};
};
smtp = {
host = "smtp.mailgun.org";
port = 587;
username = "postmaster@mg.${domain}";
from_address = "authelia@${domain}";
password.result = config.shb.sops.secret."forgejo/smtpPassword".result;
};
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminPassword.result = config.shb.sops.secret."forgejo/ldap_admin_password".result;
};
sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
clientID = "forgejo";
sharedSecret.result = config.shb.sops.secret."forgejo/ssoSecret".result;
sharedSecretForAuthelia.result = config.shb.sops.secret."forgejo/authelia/ssoSecret".result;
};
hostPackages = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nix
nodejs
openssh
wget
];
};
services.forgejo.settings.repository.ENABLE_PUSH_CREATE_USER = true;
nix.settings.trusted-users = [ "forgejo" ];
users.users.forgejo.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICIPM0UrnUQqX7sScEtGj27uxS6FRhvpNTh1YF0E4NzM fogejo@${hostname}"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIgmFPtRC0soKC7hxCIYutHSkLIyN/d6F9d1woUivHz4"
];
shb.sops.secret."forgejo/adminPassword".request =
config.shb.forgejo.users."forgejoadmin".password.request;
shb.sops.secret."forgejo/databasePassword".request = config.shb.forgejo.databasePassword.request;
shb.sops.secret."forgejo/smtpPassword" = {
request = config.shb.forgejo.smtp.password.request;
settings.key = "authelia/smtp_password";
};
shb.sops.secret."forgejo/ldap_admin_password" = {
request = config.shb.forgejo.ldap.adminPassword.request;
settings.key = "lldap/user_password";
};
shb.sops.secret."forgejo/ssoSecret".request = config.shb.forgejo.sso.sharedSecret.request;
shb.sops.secret."forgejo/authelia/ssoSecret" = {
request = config.shb.forgejo.sso.sharedSecretForAuthelia.request;
settings.key = "forgejo/ssoSecret";
};
shb.zfs.pools.root.datasets."safe/forgejo" = config.shb.forgejo.mount;
shb.sanoid.backup."root/safe/forgejo" = {
request = config.shb.zfs.pools.root.datasets."safe/forgejo".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureGroups = {
forgejo_admin = { };
forgejo_user = { };
};
shb.homepage.servicesGroups.Admin.services.Forgejo = {
sortOrder = 1;
dashboard.request = config.shb.forgejo.dashboard.request;
};
})
(backupCfg { } "forgejo")
(lib.optionalAttrs true {
shb.davfs.mounts = [
{
remoteUrl = "https://n.${domain}/remote.php/dav/files/124eb1fb-49f6-3511-b4e4-c6626c749940";
mountPoint = "/srv/syncthing/photoframe";
# Must match the username in Nextcloud when creating a token
username = "photoframe";
passwordFile = config.shb.sops.secret."photoframe".result.path;
uid = 10001;
gid = 10002;
}
];
# Secret must be in the format:
# <mountPoint> <user> <secret>
# /srv/syncthing/photoframe photoframe xyz...
shb.sops.secret."webdav/nextcloud" = {
request.mode = "0600";
settings.path = "/etc/davfs2/secrets";
};
})
(lib.optionalAttrs true (
let
vhost =
{ folder, certs }:
{
forceSSL = true;
sslCertificate = certs.paths.cert;
sslCertificateKey = certs.paths.key;
locations."/" = {
root = "/srv/${folder}/";
extraConfig = ''
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header Cache-Control "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400, must-revalidate, public";
'';
};
};
in
{
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"skarabox.${domain}"
];
shb.certs.certs.letsencrypt."skarabox.com" = {
inherit domain;
group = "nginx";
reloadServices = [ "nginx.service" ];
adminEmail = "shb@${domain}";
afterAndWants = lib.optionals config.services.dnsmasq.enable [ "dnsmasq.service" ];
};
services.dnsmasq.settings.address = [
"/skarabox.${domain}/${config.skarabox.staticNetwork.ip}"
"/skarabox.com/${config.skarabox.staticNetwork.ip}"
];
services.nginx = {
enable = true;
virtualHosts."skarabox.${domain}" = vhost {
folder = "skarabox-website-staging";
certs = config.shb.certs.certs.letsencrypt."${domain}";
};
virtualHosts."skarabox.com" = vhost {
folder = "skarabox-website";
certs = config.shb.certs.certs.letsencrypt."skarabox.com";
};
};
systemd.tmpfiles.rules = lib.mkBefore [
"d '/srv/skarabox-website-staging' 0755 ${username} nginx - -"
"d '/srv/skarabox-website' 0755 ${username} nginx - -"
];
shb.zfs.pools.root.datasets."safe/skarabox-website".path = "/srv/skarabox-website";
shb.zfs.pools.root.datasets."safe/skarabox-website-staging".path = "/srv/skarabox-website-staging";
shb.sanoid.backup."root/safe/skarabox-website" = {
request = config.shb.zfs.pools.root.datasets."safe/skarabox-website".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/skarabox-website-staging" = {
request = config.shb.zfs.pools.root.datasets."safe/skarabox-website-staging".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
}
))
{
services.thermald.enable = true;
services.fstrim.enable = true;
# It monitors the acceleration values through the various motion interfaces and automatically
# initiates disk head parking if a fall or sliding of the laptop is detected.
services.hdapsd.enable = false;
nixpkgs.overlays = [
(final: prev: {
pythonPackagesOverlays = (prev.pythonPackagesOverlays or [ ]) ++ [
(python-final: python-prev: {
})
];
python3 =
let
self = prev.python3.override {
inherit self;
packageOverrides = prev.lib.composeManyExtensions final.pythonPackagesOverlays;
};
in
self;
python3Packages = final.python3.pkgs;
})
];
}
(lib.optionalAttrs true {
shb.zfs.pools.root.datasets."safe/minecraft" = {
path = config.services.minecraft-servers.dataDir;
owner = "minecraft";
group = "minecraft";
};
shb.sanoid.backup."root/safe/minecraft" = {
request = config.shb.zfs.pools.root.datasets."safe/minecraft".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
services.minecraft-servers = {
enable = true;
eula = true;
openFirewall = true;
servers.main = {
enable = true;
whitelist = {
};
package = pkgs.neoforgeServers.neoforge-1_21_1;
serverProperties = {
server-port = 43000;
difficulty = "hard";
gamemode = "survival";
max-players = 5;
motd = "${friendlyName} Minecraft server!";
enforce-secure-profile = false;
online-mode = false;
white-list = true;
};
jvmOpts = "-Xms4092M -Xmx4092M -XX:+UseG1GC -XX:ParallelGCThreads=2 -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10";
symlinks = {
# nix shell github:Infinidoge/nix-minecraft#nix-modrinth-prefetch
# nix-modrinth-prefetch KSgki4uc
mods = pkgs.linkFarmFromDrvs "mods" (
builtins.attrValues {
# https://modrinth.com/mod/journeymap
JourneyMap = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/lfHFW1mp/versions/E44vwUJO/journeymap-neoforge-1.21.1-6.0.0-beta.66.jar";
sha512 = "a6e6fc436020c4d4d3625147c271b04535765e0ae9c59703aa66cd1d3c986e077ddafe2daf9c00b45fd9f4dfbf82ab0f1ca1ea730253ea9e0b4d954729b2c632";
# url = "https://cdn.modrinth.com/data/lfHFW1mp/versions/HSajmA5j/journeymap-neoforge-1.21.5-6.0.0-beta.52.jar";
# sha512 = "sha512-EBX4pZkqYNM2zIs2RRXR0W6bW5wrTlJIqGJ3ScXsI7msAylAdpfjHkgxjINVDspePTGoOnBrlq4gnDPpuLPZww==";
};
# https://modrinth.com/mod/sophisticated-backpacks
SophisticatedBackpacks = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/TyCTlI4b/versions/ZMuJ1TI7/sophisticatedbackpacks-1.21.1-3.25.44.1736.jar";
sha512 = "0704060b2d0e2e88bc771da1b26fe262563ac6a814f129a1207782d7edbac8bdc1b4057669c5bc94976e6eb74c6386c0735f93628b2d1f23e7eac4ae6562e185";
# url = "https://cdn.modrinth.com/data/TyCTlI4b/versions/TbHJGS23/sophisticatedbackpacks-1.21.5-3.25.45.1737.jar";
# sha512 = "sha512-y+zMncOEF2squyfjOZ4PdWWHSOK2Lx0vF20U1krkC0fPoxc5g2Fw+f5M/uPXURVvxBWxEsXTZb/OtBYsJ95z3w==";
};
# https://modrinth.com/mod/sophisticated-core
SophisticatedCore = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/nmoqTijg/versions/ErcuCe4o/sophisticatedcore-1.21.1-1.4.35.1823.jar";
sha512 = "c2c9c4e9e99a43292297f92b1f4dcfa1c9000d9aa684fed07153a4896ae9791d90f29cf0d8365c61d1915c5a6ee4c5cb881eee6c2385b562770281c3b700c0f0";
};
# https://modrinth.com/mod/jei
JustEnoughItems = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/u6dRKJwZ/versions/YAcQ6elZ/jei-1.21.1-neoforge-19.27.0.340.jar";
sha512 = "8bad8eb3c8e974f867e23e4d74598f603c5fbf03eb5356a386dd37cb9fa23e08ad1f58be6b7be50d2fbf9d3fbfaeac8584c70ced736df4b8f82c7c75be242998";
# url = "https://cdn.modrinth.com/data/u6dRKJwZ/versions/Up8I2nu2/jei-1.21.5-neoforge-21.4.0.27.jar";
# sha512 = "sha512-qVyHvI7XUqD2s1pyFeY2IpOuerSWaL0c0hdrCNoMLXfjQFG7HW+utFB1Ggnssuc1cYKz/857n9M6JmeBOowk3A==";
};
# https://modrinth.com/mod/citadel
Citadel = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/jJfV67b1/versions/uzrkhBpn/citadel-2.7.0-1.21.1.jar";
sha512 = "d77d8d25279d877ef94f1e48e770547ba2fbee2f01ed151aa932c6e36ed5dd7f846db096f7b1f9c13f49a3e2fd5de434d20a0924a3232e06d20c7ca5f46e47f6";
};
# https://modrinth.com/mod/alexs-mobs(1.21.1)
AlexsMobs = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/EmNhnNnt/versions/KSgki4uc/alexsmobs-1.22.17.jar";
sha512 = "9f57f20693bb187c54f6d68dc34592b87d0e55a5a4628ad097b0aa39afe165f4a834b83b6590d803e64bac0b1230a8f46369bfe45851a3cc964cf3d88f235277";
} ;
# https://modrinth.com/mod/farmers-delight
FarmersDelight = pkgs.fetchurl {
url = "https://cdn.modrinth.com/data/R2OftAxM/versions/9gp7w8NC/FarmersDelight-1.21.1-1.3.1.jar";
sha512 = "596340db019049e8da066df13cedb76eb06a8e877c86fd10b38332317b5fd5001cad485a6de87e3a8bf0423d87a1ffbdd51a86f6c06560f40995d68fe05edf95";
};
}
);
};
};
};
allowedUnfreePackagesRegexs = [
"neoforge"
];
})
(lib.optionalAttrs false (
backupCfg {
shbOpt.backup.request = {
user = "minecraft";
sourceDirectories = [
config.services.minecraft-server.dataDir
];
};
} "minecraft"
))
{
hardware.amdgpu.opencl.enable = true;
environment.systemPackages = [
pkgs.clinfo
pkgs.radeontop
pkgs.rocmPackages.rocminfo
];
}
# Using ollama to download models
(
let
defaultModel = "phi3:3.8b";
in
lib.optionalAttrs true {
shb.zfs.pools.root.datasets."safe/ollama".path = "/var/lib/private/ollama";
shb.sanoid.backup."root/safe/ollama" = {
request = config.shb.zfs.pools.root.datasets."safe/ollama".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
services.ollama = {
enable = true;
# https://wiki.nixos.org/wiki/Ollama#AMD_GPU_with_open_source_driver
package = pkgs.ollama-rocm;
# The logs show:
# compute=gfx900
# gfx900:xnack+
environmentVariables = {
OLLAMA_DEBUG = "2";
# This is maybe not needed anymore
HCC_AMDGPU_TARGET = "gfx900";
OLLAMA_KEEP_ALIVE = "24h";
OLLAMA_LOW_VRAM = "1"; # We have < 20Gb VRAM
OLLAMA_OUTPUT_ON_CPU = "1";
GPU_MAX_HW_QUEUES = "1"; # prevents GPU hang at 100%
};
# https://www.phoronix.com/forums/forum/software/programming-compilers/1459983-gcc-14-adds-gfx90c-for-openmp-offloading-to-apus-with-gfx9-vega-graphics?p=1460199#post1460199
rocmOverrideGfx = "9.0.0";
# https://ollama.com/library
loadModels = [
defaultModel
"llama3.1:8b"
"llama3.2:3b"
"mistral:7b-instruct"
"nomic-embed-text:v1.5"
"phi3:3.8b"
"qwen2.5:7b-instruct"
];
};
# systemd.services.ollama.serviceConfig.TimeoutStartSec = "5min";
# systemd.services.ollama.postStart = ''
# ${pkgs.ollama}/bin/ollama show ${defaultModel} && ${pkgs.ollama}/bin/ollama run ${defaultModel} "" || echo "Model is maybe still downloading"
# '';
}
)
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "openwebui.${domain}" ];
shb.zfs.pools.root.datasets."safe/open-webui".path = "/var/lib/private/open-webui";
shb.sanoid.backup."root/safe/open-webui" = {
request = config.shb.zfs.pools.root.datasets."safe/open-webui".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureUsers.${username}.groups = [
"open-webui_admin"
"open-webui_user"
];
shb.open-webui = {
enable = true;
inherit domain;
subdomain = "openwebui";
ssl = config.shb.certs.certs.letsencrypt.${domain};
# https://docs.openwebui.com/getting-started/env-configuration
environment = {
WEBUI_NAME = friendlyName;
CORS_ALLOW_ORIGIN = "https://${config.shb.open-webui.subdomain}.${config.shb.open-webui.domain}";
# ENABLE_OPENAI_API = "True";
# OPENAI_API_BASE_URL = "http://127.0.0.1:${toString config.services.llama-cpp.port}";
OLLAMA_BASE_URL = "http://127.0.0.1:${toString config.services.ollama.port}";
OFFLINE_MODE = "True";
# https://github.com/open-webui/open-webui/discussions/8530#discussioncomment-12691642
# RAG_EMBEDDING_ENGINE = "openai";
RAG_OLLAMA_BASE_URL = "http://127.0.0.1:${toString config.services.ollama.port}";
RAG_EMBEDDING_MODEL = "nomic-embed-text:v1.5";
ENABLE_ASYNC_EMBEDDING = "true";
# ENABLE_WEB_SEARCH = "True";
# TODO: use https://github.com/searxng/searxng
# TODO: setup audio
};
sso = {
enable = true;
authEndpoint = "https://authelia.${domain}";
sharedSecret.result = config.shb.sops.secret."open-webui/sso_secret".result;
sharedSecretForAuthelia.result = config.shb.sops.secret."open-webui/authelia/sso_secret".result;
};
};
shb.sops.secret."open-webui/sso_secret".request = config.shb.open-webui.sso.sharedSecret.request;
shb.sops.secret."open-webui/authelia/sso_secret" = {
request = config.shb.open-webui.sso.sharedSecretForAuthelia.request;
settings.key = "open-webui/sso_secret";
};
allowedUnfreePackagesRegexs = [
"open-webui"
];
shb.homepage.servicesGroups.Documents.services.OpenWebUI = {
sortOrder = 4;
dashboard.request = config.shb.open-webui.dashboard.request;
settings.icon = "sh-open-webui";
};
})
(backupCfg { } "open-webui")
(lib.optionalAttrs true {
shb.certs.certs.letsencrypt.${domain}.extraDomains = [ "karakeep.${domain}" ];
shb.zfs.pools.root.datasets."safe/karakeep".path = "/var/lib/karakeep";
shb.zfs.pools.root.datasets."safe/meilisearch".path = "/var/lib/private/meilisearch";
shb.sanoid.backup."root/safe/karakeep" = {
request = config.shb.zfs.pools.root.datasets."safe/karakeep".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/meilisearch" = {
request = config.shb.zfs.pools.root.datasets."safe/meilisearch".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureUsers.${username}.groups = [
"karakeep_user"
];
shb.karakeep = {
enable = true;
port = 12445;
inherit domain;
subdomain = "karakeep";
ssl = config.shb.certs.certs.letsencrypt.${domain};
nextauthSecret.result = config.shb.sops.secret."karakeep/nextauth_secret".result;
meilisearchMasterKey.result = config.shb.sops.secret."karakeep/meilisearch_master_key".result;
# https://docs.karakeep.app/configuration/
environment = {
OLLAMA_BASE_URL = "http://127.0.0.1:${toString config.services.ollama.port}";
INFERENCE_TEXT_MODEL = "deepseek-r1:1.5b";
INFERENCE_IMAGE_MODEL = "llava";
EMBEDDING_TEXT_MODEL = "nomic-embed-text:v1.5";
INFERENCE_ENABLE_AUTO_SUMMARIZATION = "true";
INFERENCE_JOB_TIMEOUT_SEC = "200";
};
sso = {
enable = true;
authEndpoint = "https://authelia.${domain}";
sharedSecret.result = config.shb.sops.secret."karakeep/sso_secret".result;
sharedSecretForAuthelia.result = config.shb.sops.secret."karakeep/authelia/sso_secret".result;
};
};
shb.sops.secret."karakeep/meilisearch_master_key".request =
config.shb.karakeep.meilisearchMasterKey.request;
shb.sops.secret."karakeep/nextauth_secret".request = config.shb.karakeep.nextauthSecret.request;
shb.sops.secret."karakeep/sso_secret".request = config.shb.karakeep.sso.sharedSecret.request;
shb.sops.secret."karakeep/authelia/sso_secret" = {
request = config.shb.karakeep.sso.sharedSecretForAuthelia.request;
settings.key = "karakeep/sso_secret";
};
services.meilisearch.package = pkgs.meilisearch;
systemd.services.meilisearch.environment.RUST_BACKTRACE = "1";
systemd.services.meilisearch.serviceConfig.ProcSubset = lib.mkForce "all";
shb.homepage.servicesGroups.Documents.services.Karakeep = {
sortOrder = 3;
dashboard.request = config.shb.karakeep.dashboard.request;
apiKey.result = config.shb.sops.secret."karakeep/homepageApiKey".result;
};
shb.sops.secret."karakeep/homepageApiKey".request =
config.shb.homepage.servicesGroups.Documents.services.Karakeep.apiKey.request;
})
(backupCfg { } "karakeep")
(lib.optionalAttrs false {
shb.authelia.oidcClients = [
{
client_id = "kbyuFDidLLm280LIwVFiazOqjO3ty8KH";
client_secret.source = pkgs.writeText "karakeep_client_secret" "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa";
scopes = [
"openid"
"email"
"profile"
"groups"
];
token_endpoint_auth_method = "client_secret_post";
redirect_uris = [
"https://openidconnect.net/callback"
];
}
];
})
{
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"${config.shb.firefly-iii.subdomain}.${config.shb.firefly-iii.domain}"
"${config.shb.firefly-iii.importer.subdomain}.${config.shb.firefly-iii.domain}"
];
shb.zfs.pools.root.datasets."safe/firefly-iii".path = config.shb.firefly-iii.impermanence;
shb.sanoid.backup."root/safe/firefly-iii" = {
request = config.shb.zfs.pools.root.datasets."safe/firefly-iii".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.lldap.ensureUsers.${username}.groups = [
config.shb.firefly-iii.ldap.userGroup
config.shb.firefly-iii.ldap.adminGroup
];
shb.firefly-iii = {
enable = true;
debug = false;
appKey.result = config.shb.sops.secret."firefly-iii/appKey".result;
dbPassword.result = config.shb.sops.secret."firefly-iii/dbPassword".result;
inherit domain;
subdomain = "firefly-iii";
siteOwnerEmail = email;
ssl = config.shb.certs.certs.letsencrypt.${domain};
smtp = {
host = "smtp.mailgun.org";
port = 587;
username = "postmaster@mg.${domain}";
from_address = "firefly-iii@${domain}";
password.result = config.shb.sops.secret."firefly-iii/smtpPassword".result;
};
sso = {
enable = true;
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
};
importer = {
firefly-iii-accessToken.result = config.shb.sops.secret."firefly-iii/importerAccessToken".result;
};
};
shb.sops.secret."firefly-iii/appKey".request = config.shb.firefly-iii.appKey.request;
shb.sops.secret."firefly-iii/dbPassword".request = config.shb.firefly-iii.dbPassword.request;
shb.sops.secret."firefly-iii/smtpPassword" = {
request = config.shb.firefly-iii.smtp.password.request;
settings.key = "authelia/smtp_password";
};
shb.sops.secret."firefly-iii/importerAccessToken".request =
config.shb.firefly-iii.importer.firefly-iii-accessToken.request;
shb.homepage.servicesGroups.Finance.services.Firefly-iii = {
sortOrder = 2;
dashboard.request = config.shb.firefly-iii.dashboard.request;
apiKey.result = config.shb.sops.secret."firefly-iii/homepageApiKey".result;
settings.widget.type = "firefly";
};
shb.sops.secret."firefly-iii/homepageApiKey".request =
config.shb.homepage.servicesGroups.Finance.services.Firefly-iii.apiKey.request;
}
(backupCfg { } "firefly-iii")
{
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"${config.shb.mailserver.subdomain}.${config.shb.mailserver.domain}"
];
shb.lldap.ensureUsers.${username}.groups = [
config.shb.mailserver.ldap.userGroup
];
shb.zfs.pools.root.datasets."safe/mailserver".path = config.shb.mailserver.impermanence.mail;
shb.zfs.pools.root.datasets."safe/mailserver/sieve".path = config.shb.mailserver.impermanence.sieve;
shb.zfs.pools.root.datasets."safe/mailserver/dkim".path = config.shb.mailserver.impermanence.dkim;
shb.sanoid.backup."root/safe/mailserver" = {
request = config.shb.zfs.pools.root.datasets."safe/mailserver".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/mailserver/sieve" = {
request = config.shb.zfs.pools.root.datasets."safe/mailserver/sieve".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.sanoid.backup."root/safe/mailserver/dkim" = {
request = config.shb.zfs.pools.root.datasets."safe/mailserver/dkim".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
shb.mailserver = {
enable = true;
inherit domain;
subdomain = "imap";
ssl = config.shb.certs.certs.letsencrypt.${domain};
imapSync = {
syncTimer = "10s";
debug = false;
accounts.fastmail = {
host = "imap.fastmail.com";
port = 993;
username = email;
password.result = config.shb.sops.secret."mailserver/imap/fastmail/password".result;
mapSpecialJunk = "Spam";
};
};
smtpRelay = {
host = "smtp.fastmail.com";
port = 587;
username = email;
password.result = config.shb.sops.secret."mailserver/smtp/fastmail/password".result;
};
ldap = {
enable = true;
host = "127.0.0.1";
port = config.shb.lldap.ldapPort;
dcdomain = config.shb.lldap.dcdomain;
adminName = "admin";
adminPassword.result = config.shb.sops.secret."mailserver/ldap_admin_password".result;
account = "fastmail";
};
};
mailserver.mailboxes = {
Drafts = {
auto = "subscribe";
special_use = "\\Drafts";
};
Junk = {
auto = "subscribe";
special_use = "\\Junk";
};
Sent = {
auto = "subscribe";
special_use = "\\Sent";
};
Trash = {
auto = "subscribe";
special_use = "\\Trash";
};
Archive = {
auto = "subscribe";
special_use = "\\Archive";
};
};
shb.sops.secret."mailserver/smtp/fastmail/password".request =
config.shb.mailserver.smtpRelay.password.request;
shb.sops.secret."mailserver/imap/fastmail/password".request =
config.shb.mailserver.imapSync.accounts.fastmail.password.request;
shb.sops.secret."mailserver/ldap_admin_password" = {
request = config.shb.mailserver.ldap.adminPassword.request;
settings.key = "lldap/user_password";
};
shb.homepage.servicesGroups.Admin.services.Email = {
sortOrder = 10;
dashboard.request = config.shb.mailserver.dashboard.request;
};
}
(backupCfg { } "mailserver")
(backupCfg {
shbOpt.backup.request = config.shb.mailserver.backupDKIM.request;
} "mailserver-dkim")
{
shb.certs.certs.letsencrypt.${domain}.extraDomains = [
"${config.shb.homepage.subdomain}.${config.shb.homepage.domain}"
];
shb.lldap.ensureUsers.${username}.groups = [
config.shb.homepage.ldap.userGroup
];
shb.homepage = {
enable = true;
subdomain = "home";
inherit domain;
ssl = config.shb.certs.certs.letsencrypt.${domain};
sso = {
enable = true;
authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
};
servicesGroups = {
Home.sortOrder = 1;
Documents.sortOrder = 2;
Finance.sortOrder = 3;
Media.sortOrder = 4;
Admin.sortOrder = 5;
};
};
services.homepage-dashboard = {
settings = {
statusStyle = "dot";
disableIndexing = true;
};
widgets = [
{
datetime = {
locale = "fr";
format = {
dateStyle = "long";
timeStyle = "long";
};
};
}
];
};
}
{
users.users.nextcloud.extraGroups = [ "syncthing" ];
shb.zfs.pools.root.datasets."syncthing" = {
path = "/srv/syncthing";
mode = "ug=rwx,g+s,o=";
defaultACLs = "g:syncthing:rwX";
owner = "syncthing";
group = "syncthing";
};
shb.sanoid.backup."root/syncthing" = {
request = config.shb.zfs.pools.root.datasets."syncthing".datasetBackup.request;
settings.useTemplate = [ "main" ];
};
services.syncthing = {
enable = true;
openDefaultPorts = true;
guiAddress = "127.0.0.1:8384";
settings.guiPasswordFile = config.shb.sops.secret."syncthing/gui/password".result.path;
key = config.shb.sops.secret."syncthing/certs/key".result.path;
cert = config.shb.sops.secret."syncthing/certs/cert".result.path;
settings = {
devices = {
"batocera" = {
id = "...";
};
};
folders = {
"pygame" = {
path = "/srv/syncthing/pygame";
devices = [ "batocera" ];
};
};
};
};
shb.sops.secret."syncthing/gui/password".request = {
owner = "syncthing";
};
shb.sops.secret."syncthing/certs/key".request = {
owner = "syncthing";
};
shb.sops.secret."syncthing/certs/cert".request = {
owner = "syncthing";
};
networking.firewall.allowedTCPPorts = [ 8384 ];
}
];
}
{
description = "ibizaman's NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
selfhostblocks.url = "github:ibizaman/selfhostblocks";
skarabox.url = "github:ibizaman/skarabox";
nixos-generators.url = "github:nix-community/nixos-generators";
nixos-generators.inputs.nixpkgs.follows = "nixpkgs";
nixos-anywhere.url = "github:nix-community/nixos-anywhere";
nixos-anywhere.inputs.nixpkgs.follows = "nixpkgs";
nixos-facter-modules.url = "github:numtide/nixos-facter-modules";
deploy-rs.url = "github:serokell/deploy-rs";
colmena.url = "github:zhaofengli/colmena";
sops-nix.url = "github:Mic92/sops-nix";
nix-minecraft.url = "github:Infinidoge/nix-minecraft";
};
outputs =
inputs@{
self,
nixpkgs,
deploy-rs,
selfhostblocks,
flake-parts,
skarabox,
...
}:
flake-parts.lib.mkFlake { inherit inputs; } (
let
system = "x86_64-linux";
in
{
imports = [
skarabox.flakeModules.default
skarabox.flakeModules.deploy-rs
];
systems = [
"x86_64-linux"
"aarch64-linux"
];
skarabox.hosts = {
${hostname} = {
inherit system;
nixpkgs = inputs.selfhostblocks.lib.${system}.patchedNixpkgs;
hostKeyPath = "./machines/${hostname}_host_key";
hostKeyPub = ./machines/${hostname}/host_key.pub;
ip = "192.168.1.50";
sshBootPort = 22346;
sshPort = 22345;
knownHosts = ./machines/${hostname}/known_hosts;
knownHostsPath = "./machines/${hostname}/known_hosts";
sshPrivateKeyPath = "./machines/${hostname}/ssh-key";
secretsFilePath = "./secrets/secrets.yaml";
extraSecretsPassphrasesPath = {
"backup_passphrase" = "['${hostname}']['disks']['backupPassphrase']";
};
modules = [
inputs.selfhostblocks.nixosModules.default
inputs.selfhostblocks.nixosModules.sops
inputs.sops-nix.nixosModules.default
inputs.nix-minecraft.nixosModules.minecraft-servers
{
nixpkgs.overlays = [ inputs.nix-minecraft.overlay ];
}
self.nixosModules.${hostname}
];
};
};
perSystem =
{
self',
system,
inputs',
pkgs,
...
}:
{
formatter = nixpkgs.legacyPackages.${system}.nixfmt-tree;
};
flake = {
nixosModules.${hostname} = {
imports = [
./machines/${hostname}/default.nix
{
nixpkgs.config.permittedInsecurePackages = [
# https://github.com/NixOS/nixpkgs/issues/360592
"aspnetcore-runtime-6.0.36"
"aspnetcore-runtime-wrapped-6.0.36"
];
}
];
};
colmena = {
meta =
let
system = "x86_64-linux";
patches = [
# {
# url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/268168.patch";
# hash = "sha256-WIMDnmZV0eL1eFVD0ldHUBrulZWsjdFOmcN4i8+RgFA=";
# }
# {
# url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/365751.patch";
# hash = "sha256-2egcjmS9pxtVSUe696nq920uLSP6/kuw0KSCLfTneU0=";
# }
];
originPkgs = selfhostblocks.inputs.nixpkgs;
nixpkgs' = originPkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched";
src = originPkgs;
patches =
selfhostblocks.patches.${system} ++ map originPkgs.legacyPackages.${system}.fetchpatch patches;
};
in
{
nixpkgs = import nixpkgs' {
inherit system;
config = {
permittedInsecurePackages = [
# https://github.com/NixOS/nixpkgs/issues/360592
"aspnetcore-runtime-6.0.36"
"aspnetcore-runtime-wrapped-6.0.36"
];
};
};
specialArgs = inputs;
};
};
};
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment