{ config, pkgs, ... }: { ######################################## # Samba File Sharing ######################################## services.samba = { enable = true; openFirewall = true; # Enable nmbd for NetBIOS name resolution and browsing (legacy Windows/macOS) nmbd.enable = true; # Enable WSD discovery (Windows) and mDNS/NetBIOS advertisement improvements via wsdd + Avahi. # "smb encrypt" set to desired to avoid discovery issues with some clients while still allowing encryption. settings = { global = { workgroup = "WORKGROUP"; "server string" = "NixFiles"; "netbios name" = "fileserver"; security = "user"; "map to guest" = "bad user"; "unix extensions" = "no"; # macOS optimizations "vfs objects" = "catia fruit streams_xattr"; "fruit:aapl" = "yes"; "fruit:metadata" = "stream"; "fruit:resource" = "stream"; "fruit:model" = "MacSamba"; "fruit:advertise_fullsync" = "yes"; "ea support" = "yes"; # Time Machine support "fruit:time machine" = "yes"; "fruit:time machine max size" = "500G"; # Prefer encryption but do not require it for basic browsing/guest visibility "smb encrypt" = "desired"; # Better macOS discovery "min protocol" = "SMB2"; "max protocol" = "SMB3"; "server role" = "standalone server"; # Allow Apple extended attributes & full sync advertisement already configured above. }; daten = { path = "/data/daten"; browseable = "yes"; "read only" = "no"; "valid users" = "danlin"; "fruit:time machine" = "no"; }; daten-share = { path = "/data/daten/share"; browseable = "yes"; "read only" = "no"; "guest ok" = "yes"; # Gastzugriff erlaubt public = "yes"; # Alias für guest ok # Removed "valid users" to allow true guest access; danlin can still write via group permissions "fruit:time machine" = "no"; }; timemachine = { path = "/data/backup/timemachine"; browseable = "yes"; "read only" = "no"; "valid users" = "danlin"; "fruit:time machine" = "yes"; "fruit:time machine max size" = "500G"; }; }; }; ######################################## # Network Discovery Services (Avahi + WSD) ######################################## # Avahi for macOS Finder discovery (mDNS) and general _smb._tcp advertising services.avahi = { enable = true; nssmdns4 = true; # Provide .local resolution openFirewall = true; publish = { enable = true; userServices = true; }; # Explicit SMB service advertisement for macOS Finder extraServiceFiles = { smb = '' %h _smb._tcp 445 _device-info._tcp 0 model=TimeCapsule8,119 _adisk._tcp 9 sys=waMa=0,adVF=0x100 dk0=adVN=timemachine,adVF=0x82 ''; }; }; # Windows network neighborhood discovery via Web Services for Devices (WSD) # NixOS does not provide a `services.wsdd` option in this release, so define a systemd unit. systemd.services.wsdd = { description = "Web Services Discovery daemon for Samba (wsdd)"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" "samba.service" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.wsdd}/bin/wsdd --hostname fileserver --workgroup WORKGROUP --interface ens18"; Restart = "on-failure"; RestartSec = 5; }; }; ######################################## # Directory Structure ######################################## systemd.tmpfiles.rules = [ "d /data 0775 root root -" "d /data/daten 0775 danlin users -" "d /data/daten/share 0775 danlin users -" # Gitea (runs as git user inside container, uid 1000) "d /data/gitea 0755 root root -" # DJ-Struktur "d /data/daten/DJing 0775 danlin users -" "d /data/daten/DJing/Music 0775 danlin users -" "d /data/daten/DJing/Data 0775 danlin users -" "d /data/daten/DJing/Inbox 0775 danlin users -" # Time Machine backup "d /data/backup 0775 root root -" "d /data/backup/timemachine 0775 danlin users -" # FileBrowser config "d /data/filebrowser 0755 root root -" # Secrets "d /data/secrets 0700 root root -" ]; ######################################## # Virtualization & Containers ######################################## # Virtualization virtualisation.podman.enable = true; virtualisation.oci-containers.backend = "podman"; virtualisation.oci-containers.containers.filebrowser = { image = "gtstef/filebrowser:stable"; autoStart = true; ports = [ "8080:80" ]; volumes = [ "/data:/srv" "/data/filebrowser:/config" ]; environment = { TZ = "Europe/Berlin"; FB_DATABASE = "/config/filebrowser.db"; }; environmentFiles = [ "/data/secrets/filebrowser.env" ]; }; virtualisation.oci-containers.containers.gitea = { image = "gitea/gitea:latest"; autoStart = true; ports = [ "3000:3000" "2222:2222" ]; volumes = [ "/data/gitea:/data" ]; environment = { USER_UID = "1000"; USER_GID = "1000"; TZ = "Europe/Berlin"; GITEA__server__DOMAIN = "git.home.lindenfelser.de"; GITEA__server__ROOT_URL = "https://git.home.lindenfelser.de/"; GITEA__server__SSH_DOMAIN = "git.home.lindenfelser.de"; GITEA__server__SSH_PORT = "2222"; GITEA__server__SSH_LISTEN_PORT = "2222"; GITEA__server__START_SSH_SERVER = "true"; # Actions (CI) aktivieren — Voraussetzung für den act_runner unten. GITEA__actions__ENABLED = "true"; }; }; ######################################## # Gitea Actions Runner ######################################## # Docker-Daemon für die Job-Container des Runners (läuft parallel zu Podman, # das weiterhin die App-Container betreibt). virtualisation.docker.enable = true; services.gitea-actions-runner = { package = pkgs.gitea-actions-runner; instances.fileserver = { enable = true; name = "fileserver"; # Interne LAN-URL — vom Host UND aus den Docker-Job-Containern erreichbar # (localhost/127.0.0.1 würde im Job-Container auf den Container selbst zeigen). url = "http://10.202.82.6:3000"; # Registration-Token: in Gitea unter Site Admin → Actions → Runners → # "Create new Runner" erzeugen und in diese Datei schreiben (0600 root). tokenFile = "/data/secrets/gitea-runner-token"; labels = [ "ubuntu-latest:docker://node:20-bookworm" "ubuntu-22.04:docker://node:20-bookworm" "alpine:docker://alpine:3.19" ]; }; }; ######################################## # Backup Services ######################################## systemd.services.rclone-backup = { description = "Backup /data to Google Drive via rclone"; serviceConfig = { Type = "oneshot"; ExecStart = '' ${pkgs.rclone}/bin/rclone sync /data gdrive:backup-daten \ --fast-list \ --drive-stop-on-upload-limit \ --log-file=/var/log/rclone-backup.log \ --log-level=INFO ''; User = "root"; }; }; systemd.timers.rclone-backup = { wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = "03:00"; Persistent = true; }; }; ######################################## # System Packages ######################################## environment.systemPackages = [ pkgs.git pkgs.tmux pkgs.htop pkgs.podman-compose ]; ######################################## # Firewall ######################################## networking.firewall.enable = true; networking.firewall.allowedTCPPorts = [ 22 139 445 8080 5357 3000 2222 ]; # 5357 WSD networking.firewall.allowedUDPPorts = [ 137 138 3702 5353 ]; # NetBIOS + WSD (3702) + mDNS (5353) }