{ pkgs, pkgs-unstable, config, inputs, ... }: let immichDataDir = "/mnt/storage/immich"; syncthingDataDir = "/mnt/storage/syncthing"; smtp = { host = "horologium.uberspace.de"; port = 587; username = "noreply@${config.networking.domain}"; from = "noreply@${config.networking.domain}"; heloName = config.networking.domain; }; secrets = config.age.secrets; in { imports = [ ./glance.nix ]; virtualisation.podman.enable = true; virtualisation.oci-containers.backend = "podman"; security.acme.defaults.environmentFile = secrets.hetzner.path; modules.storageBoxMounts = { ${immichDataDir} = { path = "/backup/immich"; user = "u407959"; uid = config.users.users.${config.services.immich.user}.uid; gid = config.users.groups.${config.services.immich.user}.gid; }; ${syncthingDataDir} = { path = "/backup/syncthing"; user = "u407959"; uid = config.users.users.${config.services.syncthing.user}.uid; gid = config.users.groups.${config.services.syncthing.user}.gid; }; }; services = { postgresql.package = pkgs.postgresql_16; octodns = { enable = true; records."".MX = { ttl = 86400; values = [ { exchange = "${smtp.host}."; } ]; }; defaults.CNAME.ttl = 60; }; hastebin = { enable = true; subdomain = "bin"; renderers = with pkgs; let hl = rustPlatform.buildRustPackage { name = "syntax-renderer"; src = inputs.syntax-renderer; cargoHash = "sha256-kZy+HVPcUfPDTBQZ8TQ/xlEEqmSIttzdGeRwX9EF4xU="; }; in { hl = "${hl}/bin/syntax-renderer"; sha = writeShellScript "sha-renderer" '' echo "Content-Type: text/plain" echo "---" ${coreutils}/bin/sha256sum - | cut -d' ' -f1 ''; stl = writeShellScript "stl-renderer" '' echo "Content-Type: model/stl" echo "Content-Disposition: attachment; filename=$(basename "$1" .scad).stl" echo "---" ${openscad}/bin/openscad --export-format stl -o - - ''; }; cleanup.enable = true; }; readeck = { enable = true; subdomain = "read"; settings.email = { host = smtp.host; port = smtp.port; username = smtp.username; encryption = "starttls"; from = smtp.from; from_noreply = smtp.from; }; }; donetick = { enable = true; subdomain = "do"; settings = { email = { host = smtp.host; port = smtp.port; email = smtp.username; }; }; }; grafana = { enable = true; subdomain = "graph"; settings = { server.http_port = 3005; smtp = { enabled = true; host = smtp.host; port = smtp.port; user = smtp.username; from_address = smtp.from; }; }; }; owncast = { enable = true; subdomain = "stream"; }; gtrackmap = { enable = true; subdomain = "trackmap"; port = 3001; }; invidious = { enable = true; subdomain = "vid"; }; syncthing = { enable = true; subdomain = "sync"; dataDir = syncthingDataDir; }; tailscale.enable = true; gotosocial = { enable = true; subdomain = "social"; settings = { port = 3002; smtp-host = smtp.host; smtp-port = smtp.port; smtp-username = smtp.username; smtp-from = smtp.from; instance-languages = [ "de" "fi" "en" ]; }; }; vaultwarden = { enable = true; subdomain = "pw"; config = { YUBICO_CLIENT_ID = 86799; SMTP_HOST = smtp.host; SMTP_FROM = smtp.from; SMTP_FROM_NAME = "Vaultwarden"; SMTP_USERNAME = smtp.username; SMTP_PORT = smtp.port; HELO_NAME = smtp.heloName; }; }; workout-tracker = { enable = true; subdomain = "fit"; port = 3004; }; workout-sync = { enable = true; subdomain = "ws"; }; immich = { enable = true; subdomain = "img"; mediaLocation = immichDataDir; timezone = "Europe/Helsinki"; settings.job = { thumbnailGeneration.concurrency = 8; videoConversion.concurrency = 2; }; }; dnote = { enable = true; subdomain = "note"; environment = { SmtpHost = smtp.host; SmtpPort = smtp.port; SmtpUsername = smtp.username; }; environmentFile = secrets.dnote.path; }; tailscaledAdguardhome = { enable = true; subdomain = "dns"; port = 3006; }; mealie = { enable = true; package = pkgs-unstable.mealie; subdomain = "cook"; credentialsFile = secrets.mealie.path; settings = { SMTP_HOST = smtp.host; SMTP_FROM_EMAIL = smtp.from; SMTP_USER = smtp.username; SMTP_PORT = smtp.port; }; }; uptime-kuma = { enable = true; subdomain = "status"; settings = { PORT = "3007"; }; }; mosquitto = { enable = true; listeners = [ { users = { homie = { acl = [ "readwrite homie/#" ]; hashedPasswordFile = secrets."mosquitto/homie".path; }; telegraf = { acl = [ "read openhab/#" "read homie/#" "read shellies/#" "read mokkimaatti/#" ]; hashedPasswordFile = secrets."mosquitto/telegraf".path; }; openhab = { acl = [ "readwrite openhab/#" ]; hashedPasswordFile = secrets."mosquitto/openhab".path; }; shelly = { acl = [ "readwrite shellies/#" ]; hashedPasswordFile = secrets."mosquitto/shelly".path; }; mokkimaatti = { acl = [ "readwrite mokkimaatti/#" ]; hashedPasswordFile = secrets."mosquitto/mokkimaatti".path; }; }; } ]; openFirewall = true; }; gitlab-runner = { enable = true; services = { default = { dockerImage = "alpine"; authenticationTokenConfigFile = secrets."gitlab-runner/default".path; }; docker = { dockerImage = "docker:stable"; dockerVolumes = [ "/var/run/docker.sock:/var/run/docker.sock" ]; tagList = [ "docker" ]; authenticationTokenConfigFile = secrets."gitlab-runner/docker".path; }; }; }; home-assistant = { enable = true; subdomain = "home"; config = { homeassistant = { name = "Koti"; unit_system = "metric"; time_zone = "Europe/Helsinki"; }; http = { server_port = 8123; use_x_forwarded_for = true; trusted_proxies = [ "127.0.0.1" "::1" ]; }; mqtt = [ { climate = { unique_id = "nappula"; name = "Nappula"; current_humidity_topic = "homie/nappula/humidity/value"; current_humidity_template = "{{ value | float }}"; current_temperature_topic = "homie/nappula/temperature/value"; current_temperature_template = "{{ value | float }}"; mode_state_topic = "homie/nappula/ac/trigger"; mode_state_template = "{% if value == 'true' %}heat{% else %}off{% endif %}"; availability = { topic = "homie/nappula/$online"; payload_available = "true"; payload_not_available = "false"; }; modes = [ "off" "heat" ]; }; } { button = { unique_id = "nappula_button"; name = "Nappula anschalten"; command_topic = "homie/nappula/button/trigger/set"; payload_press = "true"; availability = { topic = "homie/nappula/$online"; payload_available = "true"; payload_not_available = "false"; }; icon = "mdi:power"; }; } { sensor = { unique_id = "nappula_pressure"; name = "Luftdruck"; state_topic = "homie/nappula/pressure/value"; device_class = "atmospheric_pressure"; unit_of_measurement = "hPa"; state_class = "measurement"; value_template = "{{ value | float // 100 }}"; }; } ]; }; extraComponents = [ "default_config" "esphome" "met" "radio_browser" "mqtt" ]; extraPackages = ( python3Packages: with python3Packages; [ paho-mqtt ] ); }; weechat = { enable = true; subdomain = "irc"; }; nginx.virtualHosts."isarepomaa.com" = { forceSSL = true; enableACME = true; http2 = true; locations."/".root = "/var/www/isas-portfolio"; }; hledger-web = { enable = true; subdomain = "ledger"; stateDir = "${syncthingDataDir}/ledger"; user = config.systemd.services.syncthing.serviceConfig.User; group = config.systemd.services.syncthing.serviceConfig.Group; extraOptions = [ "--forecast" ]; journalFiles = [ "main.ldg" ]; }; webserver = { acme.dnsChallenge = true; tailscaleAuth.expectedTailnet = "tempel-vibes.ts.net"; }; }; }