Compare commits
90 Commits
75c5775369
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| df3c3d1c08 | |||
| e98263b100 | |||
| 0500445003 | |||
| ce4fa00b77 | |||
| ec9b8f7d55 | |||
| 0cc60dcd29 | |||
| 3b432d8bd4 | |||
| 19b2459f65 | |||
| 76fbcd86db | |||
| d1e511bfc0 | |||
| 090cb2a7e4 | |||
| c994337e1f | |||
| f1e24678b9 | |||
| dcde9fad01 | |||
| 3c41c307ee | |||
| 7e4ef7b679 | |||
| 3e927af8f9 | |||
| 6de5f0cd28 | |||
| 5394287b3a | |||
| a4c0c2b051 | |||
| 7933a3aa57 | |||
| b5bece34ed | |||
| 4ab54cae0a | |||
| e6907ddd0a | |||
| 5bf87a1f83 | |||
| cca3e0d42b | |||
| f190eb2040 | |||
| 96d049d486 | |||
| e09301c493 | |||
| 3721e41e94 | |||
| 5b604fac08 | |||
| e1ddf88300 | |||
| 07e7084b1b | |||
| e46ee8495c | |||
| 5cd7f661c0 | |||
| 4d1448189c | |||
| 501383bc8d | |||
| 331b686bae | |||
| ca8e8c967e | |||
| 487889e3c6 | |||
| de6c80d7b4 | |||
| d384fe1f7c | |||
| 65e1ba4ed2 | |||
| 6705329887 | |||
| ae00cb69de | |||
| 19b2ac7426 | |||
| b12f081bc3 | |||
| 0ff3ec0e1b | |||
| 45495b114f | |||
| 3bfaf5fa6f | |||
| bbe269bfcd | |||
| af4f384797 | |||
| 68949dc81b | |||
| fad1f51323 | |||
| ab886a8a0b | |||
| 87b857071d | |||
| ea86da660d | |||
| 41f8298078 | |||
| 60bf000973 | |||
| 384f8cf1ce | |||
| d753c34e37 | |||
| e3e6cac8a3 | |||
| 25820b8578 | |||
| 33766aaded | |||
| 98f727c904 | |||
| 3558fc5d5c | |||
| af86328ec1 | |||
| d7a28f93f1 | |||
| d9ee1967fd | |||
| 346c2094a9 | |||
| 42f463152f | |||
| bf753471ba | |||
| c2b49d7d67 | |||
| df165acd1c | |||
| 88bfa9d1ec | |||
| d98fd8cebf | |||
| 8bd9f05621 | |||
| acbc0ce72d | |||
| 260807ea82 | |||
| bd91b1e8bf | |||
| 5220822812 | |||
| 1697952fc4 | |||
| 329355d6c0 | |||
| a98e25abe5 | |||
| 38154bbd0d | |||
| 16c1517d95 | |||
| b68deed2e7 | |||
| 169ead06a4 | |||
| 6e9ea3fde3 | |||
| 30e4291089 |
@@ -2,7 +2,7 @@
|
||||
description = "Numbus Server Module";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }: {
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
./boot.nix
|
||||
./cpu.nix
|
||||
./disks.nix
|
||||
./pcie-coral.nix
|
||||
];
|
||||
}
|
||||
@@ -265,7 +265,7 @@ in
|
||||
|
||||
services.snapraid = {
|
||||
enable = true;
|
||||
contentFiles = [ "/mnt/content-0/snapraid.content" ] ++
|
||||
contentFiles = (optionals (length cfg.dataDisksList == 1) [ "/mnt/content-0/snapraid.content" ]) ++
|
||||
(map (i: "/mnt/content-${toString i}/snapraid.content") (range 1 (length cfg.dataDisksList)));
|
||||
parityFiles = map (i: "/mnt/parity-${toString i}/snapraid.parity") (range 1 (length cfg.parityDisksList));
|
||||
dataDisks = listToAttrs (imap1 (i: _: nameValuePair "d${toString i}" "/mnt/content-${toString i}") cfg.dataDisksList);
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.numbus.hardware.pcie-coral;
|
||||
|
||||
gasket-driver = { stdenv, lib, fetchFromGitHub, kernel }: stdenv.mkDerivation rec {
|
||||
pname = "gasket";
|
||||
version = "1.0-18";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "google";
|
||||
repo = "gasket-driver";
|
||||
rev = "97aeba584efd18983850c36dcf7384b0185284b3";
|
||||
sha256 = "pJwrrI7jVKFts4+bl2xmPIAD01VKFta2SRuElerQnTo=";
|
||||
};
|
||||
|
||||
makeFlags = [
|
||||
"-C"
|
||||
"${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
|
||||
"M=$(PWD)"
|
||||
];
|
||||
buildFlags = [ "modules" ];
|
||||
|
||||
installFlags = [ "INSTALL_MOD_PATH=${placeholder "out"}" ];
|
||||
installTargets = [ "modules_install" ];
|
||||
|
||||
sourceRoot = "source/src";
|
||||
hardeningDisable = [ "pic" "format" ];
|
||||
nativeBuildInputs = kernel.moduleBuildDependencies;
|
||||
|
||||
meta = with lib; {
|
||||
description = "The Coral Gasket Driver allows usage of the Coral EdgeTPU on Linux systems.";
|
||||
homepage = "https://github.com/google/gasket-driver";
|
||||
license = licenses.gpl2;
|
||||
maintainers = [ maintainers.kylehendricks ];
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
};
|
||||
|
||||
libedgetpu-pkg = { stdenv, lib, fetchFromGitHub, libusb1, abseil-cpp, flatbuffers, xxd }:
|
||||
let
|
||||
flatbuffers_1_12 = flatbuffers.overrideAttrs (oldAttrs: rec {
|
||||
version = "1.12.0";
|
||||
NIX_CFLAGS_COMPILE = "-Wno-error=class-memaccess -Wno-error=maybe-uninitialized";
|
||||
cmakeFlags = (oldAttrs.cmakeFlags or []) ++ ["-DFLATBUFFERS_BUILD_SHAREDLIB=ON"];
|
||||
NIX_CXXSTDLIB_COMPILE = "-std=c++17";
|
||||
configureFlags = (oldAttrs.configureFlags or []) ++ ["--enable-shared"];
|
||||
src = fetchFromGitHub {
|
||||
owner = "google";
|
||||
repo = "flatbuffers";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-L1B5Y/c897Jg9fGwT2J3+vaXsZ+lfXnskp8Gto1p/Tg=";
|
||||
};
|
||||
});
|
||||
|
||||
in stdenv.mkDerivation rec {
|
||||
pname = "libedgetpu";
|
||||
version = "grouper";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "google-coral";
|
||||
repo = pname;
|
||||
rev = "release-${version}";
|
||||
sha256 = "sha256-73hwItimf88Iqnb40lk4ul/PzmCNIfdt6Afi+xjNiBE=";
|
||||
};
|
||||
|
||||
makeFlags = ["-f" "makefile_build/Makefile" "libedgetpu" ];
|
||||
|
||||
buildInputs = [
|
||||
libusb1
|
||||
abseil-cpp
|
||||
flatbuffers_1_12
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
xxd
|
||||
];
|
||||
|
||||
NIX_CXXSTDLIB_COMPILE = "-std=c++17";
|
||||
|
||||
TFROOT = "${fetchFromGitHub {
|
||||
owner = "tensorflow";
|
||||
repo = "tensorflow";
|
||||
rev = "v2.7.4";
|
||||
sha256 = "sha256-liDbUAdaVllB0b74aBeqNxkYNu/zPy7k3CevzRF5dk0=";
|
||||
}}";
|
||||
|
||||
enableParallelBuilding = false;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/lib
|
||||
cp out/direct/k8/libedgetpu.so.1.0 $out/lib
|
||||
ln -s $out/lib/libedgetpu.so.1.0 $out/lib/libedgetpu.so.1
|
||||
mkdir -p $out/lib/udev/rules.d
|
||||
cp debian/edgetpu-accelerator.rules $out/lib/udev/rules.d/99-edgetpu-accelerator.rules
|
||||
'';
|
||||
};
|
||||
|
||||
gasket = config.boot.kernelPackages.callPackage gasket-driver {};
|
||||
libedgetpu = pkgs.callPackage libedgetpu-pkg {};
|
||||
in
|
||||
|
||||
{
|
||||
options.numbus.hardware.pcie-coral = lib.mkEnableOption "PCIe Coral TPU support";
|
||||
|
||||
config = lib.mkIf cfg {
|
||||
services.udev.packages = [ libedgetpu ];
|
||||
users.groups.plugdev = {};
|
||||
boot.extraModulePackages = [ gasket ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.numbus.services.clamav;
|
||||
clamav_notifier = pkgs.writeScript "clamav-notify.sh" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
|
||||
# Check if triggered by Real-time event (file exists)
|
||||
if [ -f /var/lib/clamav/virus_event.env ]; then
|
||||
source /var/lib/clamav/virus_event.env
|
||||
rm /var/lib/clamav/virus_event.env
|
||||
fi
|
||||
|
||||
ADMIN_EMAIL="${config.numbus.mail.adminAddress}"
|
||||
USER_EMAIL="${config.numbus.mail.userAddress}"
|
||||
OWNER_NAME="${config.numbus.owner}"
|
||||
|
||||
if [ -n "$CLAM_VIRUSEVENT_VIRUSNAME" ]; then
|
||||
# --- Real-time / VirusEvent Mode ---
|
||||
SUBJECT="Numbus Server Alert: Virus Detected (Real-time)"
|
||||
|
||||
# Retrieve logs from clamav-daemon
|
||||
LOGS=$(journalctl -u clamav-daemon.service -n 50 --no-pager | grep "FOUND")
|
||||
|
||||
TECH_BODY="
|
||||
ClamAV Real-time Alert:
|
||||
Server owner: $OWNER_NAME
|
||||
|
||||
Virus detected: $CLAM_VIRUSEVENT_VIRUSNAME
|
||||
File: $CLAM_VIRUSEVENT_FILENAME
|
||||
|
||||
Logs:
|
||||
$LOGS
|
||||
|
||||
Action taken: Access blocked (OnAccessPrevention).
|
||||
Please investigate manually.
|
||||
"
|
||||
|
||||
FRIENDLY_BODY="Cher/Chère $OWNER_NAME,
|
||||
|
||||
L'antivirus de votre serveur a détecté et bloqué une menace en temps réel.
|
||||
Fichier : $CLAM_VIRUSEVENT_FILENAME
|
||||
|
||||
Votre administrateur a été notifié.
|
||||
"
|
||||
else
|
||||
# --- Scheduled Scan Summary Mode ---
|
||||
SUBJECT="Numbus Server Alert: Virus Detected during Scheduled Scan"
|
||||
|
||||
# Retrieve logs (clamdscan prints FOUND when a virus is detected)
|
||||
LOGS=$(journalctl -u clamav-periodic-scan.service -n 100 --no-pager | grep "FOUND")
|
||||
|
||||
TECH_BODY="
|
||||
ClamAV Scan Alert:
|
||||
Server owner: $OWNER_NAME
|
||||
|
||||
Viruses detected:
|
||||
$LOGS
|
||||
|
||||
Action taken: Detection only.
|
||||
Please investigate manually.
|
||||
"
|
||||
|
||||
FRIENDLY_BODY="Cher/Chère $OWNER_NAME,
|
||||
|
||||
L'antivirus de votre serveur a détecté une menace potentielle lors de l'analyse périodique.
|
||||
Votre administrateur a été notifié avec les détails techniques.
|
||||
Nous vous conseillons d'être prudent avec vos fichiers récents.
|
||||
"
|
||||
fi
|
||||
|
||||
printf "Subject: [ADMIN] %s\n\n%s" "$SUBJECT" "$TECH_BODY" | /run/wrappers/bin/sendmail -t "$ADMIN_EMAIL"
|
||||
printf "Subject: [Alerte] Menace détectée sur votre serveur Numbus\n\n%s\n\nMerci de votre confiance,\nL'équipe de support,\nNumbus-Server." "$FRIENDLY_BODY" | /run/wrappers/bin/sendmail -t "$USER_EMAIL"
|
||||
'';
|
||||
in
|
||||
|
||||
{
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.clamav-virus-notify = {
|
||||
description = "Email notification for ClamAV virus detection";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${clamav_notifier}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./clamav.nix
|
||||
./smart.nix
|
||||
./systemd.nix
|
||||
./smtp.nix
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ config, ... }:
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
screen
|
||||
ncdu
|
||||
fastfetch
|
||||
tpm2-tss
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.podman.defaultNetwork.settings.dns_enabled = true;
|
||||
|
||||
virtualisation.containers.containersConf.settings = {
|
||||
network.default_rootless_network_cmd = "slirp4netns";
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
podman
|
||||
podman-compose
|
||||
podman-tui
|
||||
slirp4netns
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# Version tagging
|
||||
adguardVersion = "latest";
|
||||
# Helper
|
||||
helper = import ./lib.nix { inherit config pkgs lib; };
|
||||
cfg = config.numbus.services.adguard;
|
||||
# Container config
|
||||
name = "adguard";
|
||||
in
|
||||
|
||||
helper.mkPodmanService {
|
||||
inherit name;
|
||||
description = "AdGuard, feature-rich DNS service";
|
||||
pod = "false";
|
||||
defaultPort = "3000";
|
||||
scheme = "http";
|
||||
dependencies = [ "network.target" ];
|
||||
dataDirEnabled = false;
|
||||
startDelay = 10;
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"100999:100 ${cfg.configDir}"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
composeText = ''
|
||||
services:
|
||||
adguardhome:
|
||||
image: adguard/adguardhome:${adguardVersion}
|
||||
container_name: adguard
|
||||
hostname: adguard
|
||||
network_mode: pasta
|
||||
user: '1000:1000'
|
||||
ports:
|
||||
- "3000:3000/tcp"
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
volumes:
|
||||
- ${cfg.configDir}/work:/opt/adguardhome/work
|
||||
- ${cfg.configDir}/config:/opt/adguardhome/conf
|
||||
cap_add:
|
||||
- SYS_NICE
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
restart: unless-stopped
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.numbus.services.clamav;
|
||||
onAccessPaths = lib.mapAttrsToList (n: v: v.dataDir) (lib.filterAttrs (n: v:
|
||||
v ? enable && v.enable && v ? dataDir && v.dataDir != null && v.dataDir != false
|
||||
) config.numbus.services);
|
||||
clamonacc_virus_notifier = pkgs.writeScript "clamonacc_virus_notifier.sh" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
|
||||
echo "CLAM_VIRUSEVENT_VIRUSNAME=\"$CLAM_VIRUSEVENT_VIRUSNAME\"" > /var/lib/clamav/virus_event.env
|
||||
echo "CLAM_VIRUSEVENT_FILENAME=\"$CLAM_VIRUSEVENT_FILENAME\"" >> /var/lib/clamav/virus_event.env
|
||||
|
||||
/run/wrappers/bin/sudo /run/current-system/sw/bin/systemctl start clamav-virus-notify.service
|
||||
'';
|
||||
in
|
||||
|
||||
{
|
||||
options.numbus.services.clamav = {
|
||||
enable = mkEnableOption "ClamAV open-source anti-virus software";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.clamav pkgs.curl ];
|
||||
|
||||
system.activationScripts.clamav-quarantine = ''
|
||||
mkdir -p /quarantine
|
||||
chown clamav:clamav /quarantine
|
||||
chmod 440 /quarantine
|
||||
'';
|
||||
|
||||
security.sudo.extraRules = [{
|
||||
users = [ "clamav" ];
|
||||
commands = [{
|
||||
command = "/run/current-system/sw/bin/systemctl start clamav-virus-notify.service";
|
||||
options = [ "NOPASSWD" ];
|
||||
}];
|
||||
}];
|
||||
|
||||
services.clamav = {
|
||||
updater.enable = true;
|
||||
clamonacc.enable = true;
|
||||
|
||||
scanner = {
|
||||
enable = true;
|
||||
interval = "*-*-* 04:00:00"; # Everyday at 4am
|
||||
scanDirectories = [
|
||||
"/etc"
|
||||
"/home"
|
||||
"/var/lib"
|
||||
"/var/tmp"
|
||||
"/tmp"
|
||||
];
|
||||
};
|
||||
|
||||
daemon = {
|
||||
enable = true;
|
||||
settings = {
|
||||
OnAccessPrevention = true;
|
||||
OnAccessIncludePath = onAccessPaths;
|
||||
VirusEvent = "${clamonacc_virus_notifier}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.clamav-periodic-scan = mkIf (onAccessPaths != []) {
|
||||
description = "Periodic ClamAV virus scan";
|
||||
after = [ "clamav-daemon.service" "clamav-freshclam.service" ];
|
||||
requires = [ "clamav-daemon.service" ];
|
||||
wants = [ "clamav-freshclam.service" ];
|
||||
onFailure = [ "clamav-virus-notify.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.clamav}/bin/clamdscan --multiscan --fdpass --infected --allmatch --move=/quarantine ${lib.escapeShellArgs onAccessPaths}";
|
||||
Slice = "system-clamav.slice";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.clamav-periodic-scan = mkIf (onAccessPaths != []) {
|
||||
description = "Timer for ClamAV periodic scan";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-1/3-01 04:00:00";
|
||||
Persistent = true;
|
||||
Unit = "clamav-periodic-scan.service";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
{
|
||||
imports = [
|
||||
# ./adguard.nix
|
||||
./clamav.nix
|
||||
./frigate.nix
|
||||
./gitea.nix
|
||||
./home-assistant.nix
|
||||
@@ -12,5 +13,6 @@
|
||||
./passbolt.nix
|
||||
./pi-hole.nix
|
||||
./traefik.nix
|
||||
./virtualization.nix
|
||||
];
|
||||
}
|
||||
@@ -18,8 +18,13 @@ helper.mkPodmanService {
|
||||
pod = "home-assistant";
|
||||
defaultPort = "8971";
|
||||
scheme = "https";
|
||||
dependencies = [ "traefik.service" "${config.numbus.services.dns}.service" "home-assistant.service" ];
|
||||
envFile = "/var/lib/numbus-server/home-assistant/.env";
|
||||
dependencies = [ "traefik.service" "${config.numbus.services.dns}.service" "home-assistant.service" ];
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"1000:100 ${cfg.configDir}"
|
||||
"1000:100 ${cfg.dataDir}"
|
||||
];
|
||||
|
||||
extraOptions = {
|
||||
devices = mkOption {
|
||||
@@ -52,10 +57,10 @@ helper.mkPodmanService {
|
||||
environment:
|
||||
- FRIGATE_MQTT_USER=$HOME_ASSISTANT_MQTT_USER
|
||||
- FRIGATE_MQTT_PASSWORD=$HOME_ASSISTANT_MQTT_PASSWORD
|
||||
${lib.optionalString (cfg.devices != []) ''
|
||||
devices:
|
||||
${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
''}
|
||||
${lib.optionalString (cfg.devices != []) ''
|
||||
devices:
|
||||
${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
''}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
|
||||
@@ -23,8 +23,12 @@ helper.mkPodmanService {
|
||||
DB_USERNAME = "xkcdpass -n 2 -d -";
|
||||
DB_PASSWORD = "xkcdpass -n 8 -d -";
|
||||
};
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"100999:users ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}/data"
|
||||
"100999:100 ${cfg.configDir}/config"
|
||||
"100999:100 ${cfg.configDir}/database"
|
||||
];
|
||||
|
||||
composeText = ''
|
||||
@@ -49,7 +53,7 @@ helper.mkPodmanService {
|
||||
- GITEA__database__USER=$DB_USERNAME
|
||||
- GITEA__database__PASSWD=$DB_PASSWORD
|
||||
- GITEA__server__SSH_PORT=2424
|
||||
- GITEA__server__ROOT_URL=${cfg.subdomain}.${config.numbus.services.domain}
|
||||
- GITEA__server__ROOT_URL=https://${cfg.subdomain}.${config.numbus.services.domain}
|
||||
depends_on:
|
||||
- gitea-database
|
||||
security_opt:
|
||||
|
||||
@@ -22,9 +22,11 @@ helper.mkPodmanService {
|
||||
HOME_ASSISTANT_MQTT_USER = "xkcdpass -n 2 -d -";
|
||||
HOME_ASSISTANT_MQTT_PASSWORD = "xkcdpass -n 8 -d -";
|
||||
};
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"numbus-admin:users ${cfg.configDir}/home-assistant"
|
||||
"100999:users ${cfg.configDir}/mqtt"
|
||||
"1000:100 ${cfg.configDir}"
|
||||
"1000:100 ${cfg.configDir}/config"
|
||||
"100999:100 ${cfg.configDir}/mqtt"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
@@ -39,13 +41,13 @@ helper.mkPodmanService {
|
||||
ports:
|
||||
- "${cfg.port}:8123/tcp"
|
||||
volumes:
|
||||
- ${cfg.configDir}/home-assistant:/config
|
||||
- ${cfg.configDir}/config:/config
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /run/dbus:/run/dbus:ro
|
||||
${lib.optionalString (cfg.devices != []) ''
|
||||
devices:
|
||||
${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
''}
|
||||
${lib.optionalString (cfg.devices != []) ''
|
||||
devices:
|
||||
${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
''}
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
@@ -81,8 +83,8 @@ ${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
};
|
||||
|
||||
extraConfig = {
|
||||
systemd.services."${name}-quirk-1" = {
|
||||
description = "Podman container quirk 1 : ${name}";
|
||||
systemd.services."${name}-quirk" = {
|
||||
description = "Podman container quirk : ${name}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "${name}.service" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
@@ -95,31 +97,37 @@ ${lib.concatStringsSep "\n" (map (d: " - \"${d}\"") cfg.devices)}
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /var/lib/numbus-server/${name}
|
||||
if [[ -e /var/lib/numbus-server/${name}/quirk-1.true ]]; then
|
||||
exit 0
|
||||
if [[ -e ${cfg.configDir}/config/configuration.yaml ]]; then
|
||||
if grep -qF "${config.numbus.networking.ipAddress}/24" ${cfg.configDir}/config/configuration.yaml; then
|
||||
exit 0
|
||||
elif grep -qF "use_x_forwarded_for" ${cfg.configDir}/config/configuration.yaml && ! grep -qF "${config.numbus.networking.ipAddress}/24" ${cfg.configDir}/config/configuration.yaml; then
|
||||
tmp=$(mktemp)
|
||||
head -n -6 ${cfg.configDir}/config/configuration.yaml > "$tmp"
|
||||
mv "$tmp" ${cfg.configDir}/config/configuration.yaml
|
||||
fi
|
||||
fi
|
||||
until [[ -e ${cfg.configDir}/home-assistant/configuration.yaml ]]; do
|
||||
|
||||
until [[ -e ${cfg.configDir}/config/configuration.yaml ]]; do
|
||||
sleep 15
|
||||
done
|
||||
cat << 'EOF' >> ${cfg.configDir}/home-assistant/configuration.yaml
|
||||
cat << 'EOF' >> ${cfg.configDir}/config/configuration.yaml
|
||||
|
||||
http:
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies: ${config.numbus.networking.ipAddress}/24
|
||||
trusted_proxies: 10.89.0.0/16
|
||||
|
||||
zha:
|
||||
EOF
|
||||
systemctl restart ${name}.service
|
||||
touch /var/lib/numbus-server/${name}/quirk-1.true
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services."${name}-quirk-2" = {
|
||||
description = "Podman container quirk 2 : ${name}";
|
||||
wantedBy = [ "multi-user.target" "${name}.service" ];
|
||||
after = [ "${name}-secrets.service" ];
|
||||
before = [ "${name}.service" "${name}-permissions.service" ];
|
||||
systemd.services."mqtt-quirk" = {
|
||||
description = "Podman container quirk : Home-assistant MQTT";
|
||||
wantedBy = [ "multi-user.target" "mqtt.service" ];
|
||||
after = [ "mqtt-secrets.service" ];
|
||||
before = [ "mqtt.service" "mqtt-permissions.service" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
startLimitBurst = 5;
|
||||
startLimitIntervalSec = 600;
|
||||
@@ -129,10 +137,17 @@ EOF
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /var/lib/numbus-server/${name}
|
||||
if [[ -e /var/lib/numbus-server/${name}/quirk-2.true ]]; then
|
||||
exit 0
|
||||
if [[ -e ${cfg.configDir}/mqtt/mosquitto.conf && ${cfg.configDir}/mqtt/password.txt ]]; then
|
||||
if grep -qF "listener 1883" ${cfg.configDir}/mqtt/mosquitto.conf; then
|
||||
exit 0
|
||||
else
|
||||
rm ${cfg.configDir}/mqtt/mosquitto.conf
|
||||
rm ${cfg.configDir}/mqtt/password.txt
|
||||
touch ${cfg.configDir}/mqtt/mosquitto.conf
|
||||
touch ${cfg.configDir}/mqtt/password.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
cat << EOF >> ${cfg.configDir}/mqtt/mosquitto.conf
|
||||
persistence true
|
||||
persistence_location /mosquitto/data/
|
||||
@@ -142,10 +157,9 @@ listener 1883
|
||||
allow_anonymous false
|
||||
password_file /mosquitto/password.txt
|
||||
EOF
|
||||
source /var/lib/numbus-server/${name}/.env
|
||||
source /var/lib/numbus-server/mqtt/.env
|
||||
mosquitto_passwd -b ${cfg.configDir}/mqtt/password.txt "$HOME_ASSISTANT_MQTT_USER" "$HOME_ASSISTANT_MQTT_PASSWORD"
|
||||
chmod 600 ${cfg.configDir}/mqtt/password.txt
|
||||
touch /var/lib/numbus-server/${name}/quirk-2.true
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ with lib;
|
||||
|
||||
let
|
||||
# Version tagging
|
||||
immichVersion = "v2.5.6";
|
||||
immichVersion = "v2.7.5";
|
||||
redisVersion = "9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63";
|
||||
databaseVersion = "14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23";
|
||||
# Helper
|
||||
@@ -19,7 +19,7 @@ helper.mkPodmanService {
|
||||
description = "Immich, Google Photos but better";
|
||||
defaultPort = "2283";
|
||||
generatedSecrets = {
|
||||
DB_NAME = "xkcdpass -n 2 -d -";
|
||||
DB_DATABASE_NAME = "xkcdpass -n 2 -d -";
|
||||
DB_USERNAME = "xkcdpass -n 2 -d -";
|
||||
DB_PASSWORD = "xkcdpass -n 8 -d -";
|
||||
};
|
||||
@@ -29,10 +29,17 @@ helper.mkPodmanService {
|
||||
UPLOAD_LOCATION = "${cfg.dataDir}";
|
||||
DB_DATA_LOCATION = "${cfg.configDir}/database";
|
||||
TZ = "${config.time.timeZone}";
|
||||
IMMICH_VERSION = "v2.7.5";
|
||||
};
|
||||
middlewares = [ "immichSecureHeaders" ];
|
||||
dirPermissions = [
|
||||
"100999:users ${cfg.dataDir}"
|
||||
"100999:users ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}/redis"
|
||||
"100999:100 ${cfg.configDir}/model-cache"
|
||||
"100999:100 ${cfg.configDir}/machine-learning-cache"
|
||||
"100999:100 ${cfg.configDir}/machine-learning-config"
|
||||
"100999:100 ${cfg.configDir}/database"
|
||||
"100999:100 ${cfg.dataDir}"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
@@ -51,7 +58,15 @@ helper.mkPodmanService {
|
||||
- $UPLOAD_LOCATION:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
env_file:
|
||||
- .env
|
||||
- /var/lib/numbus-server/immich/.env
|
||||
environment:
|
||||
TZ: $TZ
|
||||
REDIS_HOSTNAME: $REDIS_HOSTNAME
|
||||
DB_HOSTNAME: $DB_HOSTNAME
|
||||
DB_DATABASE_NAME: $DB_DATABASE_NAME
|
||||
DB_USERNAME: $DB_USERNAME
|
||||
DB_PASSWORD: $DB_PASSWORD
|
||||
IMMICH_TRUSTED_PROXIES: ${config.numbus.networking.ipAddress}
|
||||
depends_on:
|
||||
- immich-redis
|
||||
- immich-database
|
||||
@@ -74,7 +89,7 @@ helper.mkPodmanService {
|
||||
- ${cfg.configDir}/machine-learning-config:/usr/src/.config
|
||||
- ${cfg.configDir}/machine-learning-cache:/usr/src/.cache/
|
||||
env_file:
|
||||
- .env
|
||||
- /var/lib/numbus-server/immich/.env
|
||||
healthcheck:
|
||||
disable: false
|
||||
security_opt:
|
||||
@@ -89,6 +104,8 @@ helper.mkPodmanService {
|
||||
user: '1000:1000'
|
||||
networks:
|
||||
immich:
|
||||
volumes:
|
||||
- ${cfg.configDir}/redis:/data
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
restart: unless-stopped
|
||||
@@ -102,7 +119,7 @@ helper.mkPodmanService {
|
||||
environment:
|
||||
POSTGRES_PASSWORD: $DB_PASSWORD
|
||||
POSTGRES_USER: $DB_USERNAME
|
||||
POSTGRES_DB: $DB_NAME
|
||||
POSTGRES_DB: $DB_DATABASE_NAME
|
||||
POSTGRES_INITDB_ARGS: '--data-checksums'
|
||||
volumes:
|
||||
- $DB_DATA_LOCATION:/var/lib/postgresql/data
|
||||
@@ -119,4 +136,30 @@ helper.mkPodmanService {
|
||||
name: immich
|
||||
driver: bridge
|
||||
'';
|
||||
|
||||
extraConfig = {
|
||||
environment.etc."traefik/rules/immichSecureHeaders.yaml".text = ''
|
||||
http:
|
||||
middlewares:
|
||||
immichSecureHeaders:
|
||||
headers:
|
||||
FrameDeny: true
|
||||
AccessControlAllowMethods: 'GET,POST,PUT,DELETE,OPTIONS'
|
||||
AccessControlAllowOriginList:
|
||||
- https://${cfg.subdomain}.${config.numbus.services.domain}
|
||||
- origin-list-or-null
|
||||
AccessControlMaxAge: 100
|
||||
AddVaryHeader: true
|
||||
BrowserXssFilter: true
|
||||
ContentTypeNosniff: true
|
||||
ForceSTSHeader: true
|
||||
STSIncludeSubdomains: true
|
||||
STSPreload: true
|
||||
ContentSecurityPolicy: "default-src 'self'; base-uri 'self'; img-src 'self' https://static.immich.cloud https://tiles.immich.cloud data: blob:; connect-src 'self' https://${cfg.subdomain}.${config.numbus.services.domain} wss://${cfg.subdomain}.${config.numbus.services.domain} https://static.immich.cloud https://tiles.immich.cloud; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob: https://${cfg.subdomain}.${config.numbus.services.domain}; frame-ancestors 'self';"
|
||||
CustomFrameOptionsValue: SAMEORIGIN
|
||||
ReferrerPolicy: same-origin
|
||||
PermissionsPolicy: vibrate 'self'
|
||||
STSSeconds: 315360000
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -17,8 +17,9 @@ helper.mkPodmanService {
|
||||
description = "IT-tools, useful tools when doing IT";
|
||||
pod = "false";
|
||||
defaultPort = "8880";
|
||||
configDir = false;
|
||||
dataDir = false;
|
||||
configDirEnabled = false;
|
||||
dataDirEnabled = false;
|
||||
middlewares = [ "secureHeaders" ];
|
||||
|
||||
# Compose file good
|
||||
composeText = ''
|
||||
|
||||
+21
-16
@@ -12,7 +12,7 @@ with lib;
|
||||
reverseProxied ? true,
|
||||
composeText,
|
||||
scheme ? "http",
|
||||
middlewares ? [ "secureHeaders" ],
|
||||
middlewares ? null,
|
||||
dependencies ? [ "traefik.service" "${config.numbus.services.dns}.service" ],
|
||||
extraOptions ? {},
|
||||
extraConfig ? {},
|
||||
@@ -87,7 +87,7 @@ with lib;
|
||||
- "websecure"
|
||||
service: ${name}
|
||||
middlewares:
|
||||
${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
tls:
|
||||
certresolver: "cloudflare"
|
||||
options: "secureTLS"
|
||||
@@ -101,22 +101,21 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
|
||||
systemd.services."${name}" = {
|
||||
description = "Podman container : ${name}";
|
||||
requires = dependencies;
|
||||
after = dependencies;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
startLimitBurst = 5;
|
||||
startLimitIntervalSec = 600;
|
||||
path = [ pkgs.podman pkgs.podman-compose pkgs.coreutils pkgs.sudo ];
|
||||
path = [ pkgs.podman pkgs.podman-compose pkgs.slirp4netns pkgs.su pkgs.sudo pkgs.coreutils ];
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
TimeoutStartSec = "1000";
|
||||
ExecStartPre = [
|
||||
"${pkgs.bash}/bin/bash -c 'sleep $((RANDOM % ${toString startDelay}))'"
|
||||
"${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose ${envFileArg} -f /etc/podman/${name}/compose.yaml pull"
|
||||
"${pkgs.bash}/bin/bash -c 'export PATH=/run/wrappers/bin:$PATH; exec ${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose -f /etc/podman/${name}/compose.yaml pull'"
|
||||
];
|
||||
ExecStart = "${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose ${envFileArg} --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml up --remove-orphans";
|
||||
ExecStop = "${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose ${envFileArg} --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml down";
|
||||
ExecStart = "${pkgs.bash}/bin/bash -c 'export PATH=/run/wrappers/bin:$PATH; exec ${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose ${envFileArg} --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml up --remove-orphans'";
|
||||
ExecStop = "${pkgs.bash}/bin/bash -c 'export PATH=/run/wrappers/bin:$PATH; exec ${pkgs.sudo}/bin/sudo -u numbus-admin podman-compose ${envFileArg} --in-pod ${toString pod} -f /etc/podman/${name}/compose.yaml down'";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "3m";
|
||||
};
|
||||
@@ -137,15 +136,21 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
RestartSec = "5m";
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /var/lib/numbus-server/${name}
|
||||
${concatStringsSep "\n" (map (perm: ''
|
||||
set -- ${perm}
|
||||
MARKER="/var/lib/numbus-server/${name}/.perm-fixed-$(echo "$1:$2" | md5sum | cut -d' ' -f1)"
|
||||
if [ ! -f "$MARKER" ]; then
|
||||
rm -f /var/lib/numbus-server/${name}/.perm-fixed-*
|
||||
mkdir -p "$2"
|
||||
chown -R "$1" "$2"
|
||||
touch "$MARKER"
|
||||
WANTED_PERMISSIONS=$1
|
||||
FOLDER_PATH=$2
|
||||
|
||||
if [[ ! -e "$FOLDER_PATH" ]]; then
|
||||
mkdir -p "$FOLDER_PATH"
|
||||
elif [[ ! -d "$FOLDER_PATH" ]]; then
|
||||
rm "$FOLDER_PATH"
|
||||
mkdir -p "$FOLDER_PATH"
|
||||
fi
|
||||
|
||||
ACTUAL_PERMISSIONS=$(stat -c '%u:%g' "$FOLDER_PATH")
|
||||
if [[ "$ACTUAL_PERMISSIONS" != "$WANTED_PERMISSIONS" ]]; then
|
||||
chown -R "$WANTED_PERMISSIONS" "$FOLDER_PATH"
|
||||
fi
|
||||
'') dirPermissions)}
|
||||
exit 0
|
||||
@@ -177,7 +182,7 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
# Generated Secrets (only if missing)
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: ''
|
||||
if ! grep -q "^${k}=" "$SECRETS_FILE"; then
|
||||
echo "${k}=$(${v})" >> "$SECRETS_FILE"
|
||||
echo "${k}=\"$(${v})\"" >> "$SECRETS_FILE"
|
||||
fi
|
||||
'') generatedSecrets)}
|
||||
|
||||
@@ -187,7 +192,7 @@ ${concatStringsSep "\n" (map (m: " - ${m}") middlewares)}
|
||||
grep -v "^${k}=" "$SECRETS_FILE" > "$SECRETS_FILE.tmp"
|
||||
mv "$SECRETS_FILE.tmp" "$SECRETS_FILE"
|
||||
fi
|
||||
echo "${k}=${lib.escapeShellArg v}" >> "$SECRETS_FILE"
|
||||
echo "${k}=\"${lib.escapeShellArg v}\"" >> "$SECRETS_FILE"
|
||||
'') importedSecrets)}
|
||||
|
||||
chown numbus-admin:users "$SECRETS_FILE"
|
||||
|
||||
+116
-43
@@ -4,11 +4,11 @@ with lib;
|
||||
|
||||
let
|
||||
# Version tagging
|
||||
nextcloudVersion = "32.0.6";
|
||||
nextcloudVersion = "33.0.5-apache";
|
||||
redisVersion = "8.6-alpine";
|
||||
databaseVersion = "11.8";
|
||||
onlyofficeVersion = "9.2";
|
||||
whiteboardVersion = "v1.5.6";
|
||||
onlyofficeVersion = "9.4.0";
|
||||
whiteboardVersion = "v1.5.9";
|
||||
# Helper
|
||||
helper = import ./lib.nix { inherit config pkgs lib; };
|
||||
cfg = config.numbus.services.nextcloud;
|
||||
@@ -29,12 +29,18 @@ helper.mkPodmanService {
|
||||
WHITEBOARD_PASSWORD = "xkcdpass -n 10 -d -";
|
||||
SMTP_PASSWORD = "cat ${config.numbus.mail.smtpPasswordPath}";
|
||||
};
|
||||
middlewares = [ "nextcloudSecureHeaders" ];
|
||||
dirPermissions = [
|
||||
"100032:users ${cfg.configDir}/web"
|
||||
"100999:users ${cfg.configDir}/redis"
|
||||
"100999:users ${cfg.configDir}/database"
|
||||
"100999:users ${cfg.configDir}/onlyoffice"
|
||||
"100032:users ${cfg.dataDir}"
|
||||
"100032:100 ${cfg.dataDir}"
|
||||
"100032:100 ${cfg.configDir}"
|
||||
"100032:100 ${cfg.configDir}/web"
|
||||
"100999:100 ${cfg.configDir}/redis"
|
||||
"100999:100 ${cfg.configDir}/database"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/log"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/cache"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/data"
|
||||
"1000:100 ${cfg.configDir}/onlyoffice/database"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
@@ -52,7 +58,7 @@ helper.mkPodmanService {
|
||||
- ${cfg.configDir}/web:/var/www/html
|
||||
- ${cfg.dataDir}:/mnt/ncdata
|
||||
environment:
|
||||
MYSQL_HOST: nextcloud-database
|
||||
MYSQL_HOST: nextcloud-database:3306
|
||||
MYSQL_DATABASE: $DB_NAME
|
||||
MYSQL_USER: $DB_USERNAME
|
||||
MYSQL_PASSWORD: $DB_PASSWORD
|
||||
@@ -68,13 +74,15 @@ helper.mkPodmanService {
|
||||
MAIL_FROM_ADDRESS: nextcloud-noreply
|
||||
MAIL_DOMAIN: ${config.numbus.services.domain}
|
||||
APACHE_DISABLE_REWRITE_IP: 1
|
||||
TRUSTED_PROXIES: ${config.numbus.networking.ipAddress}
|
||||
OVERWRITEPROTOCOL: https
|
||||
TRUSTED_PROXIES: 10.89.0.0/16
|
||||
NC_default_phone_region: "${config.numbus.language}"
|
||||
NC_default_language: "${config.numbus.language}"
|
||||
NC_default_locale: "${config.numbus.locale}"
|
||||
NC_default_timezone: "${config.time.timeZone}"
|
||||
NC_maintenance_window_start: "1"
|
||||
PHP_MEMORY_LIMIT: 1024M
|
||||
PHP_OPCACHE_MEMORY_CONSUMPTION: 256
|
||||
depends_on:
|
||||
- nextcloud-database
|
||||
security_opt:
|
||||
@@ -107,15 +115,17 @@ helper.mkPodmanService {
|
||||
volumes:
|
||||
- ${cfg.configDir}/database:/var/lib/mysql
|
||||
environment:
|
||||
MARIADB_DATABASE: $MYSQL_DATABASE
|
||||
MARIADB_USER: $MYSQL_USER
|
||||
MARIADB_PASSWORD: $MYSQL_PASSWORD
|
||||
MARIADB_DATABASE: $DB_NAME
|
||||
MARIADB_USER: $DB_USERNAME
|
||||
MARIADB_PASSWORD: $DB_PASSWORD
|
||||
MARIADB_RANDOM_ROOT_PASSWORD: true
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
|
||||
command:
|
||||
- "--transaction-isolation=READ-COMMITTED"
|
||||
- "--binlog-format=ROW"
|
||||
restart: unless-stopped
|
||||
nextcloud-onlyoffice:
|
||||
container_name: nextcloud-onlyoffice
|
||||
@@ -123,14 +133,19 @@ helper.mkPodmanService {
|
||||
image: docker.io/onlyoffice/documentserver:${onlyofficeVersion}
|
||||
environment:
|
||||
- JWT_SECRET=$ONLYOFFICE_PASSWORD
|
||||
- REDIS_SERVER_HOST=nextcloud-redis
|
||||
- REDIS_SERVER_PORT=6379
|
||||
- REDIS_SERVER_PASS=$REDIS_PASSWORD
|
||||
- ADMINPANEL_ENABLED=false
|
||||
- EXAMPLE_ENABLED=false
|
||||
- METRICS_ENABLED=false
|
||||
ports:
|
||||
- "9980:80/tcp"
|
||||
volumes:
|
||||
- ${cfg.configDir}/onlyoffice/log:/var/log/onlyoffice
|
||||
- ${cfg.configDir}/onlyoffice/cache:/var/lib/onlyoffice
|
||||
- ${cfg.configDir}/onlyoffice/data:/var/www/onlyoffice/Data
|
||||
- ${cfg.configDir}/onlyoffice/database:/var/lib/postgresql
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
restart: unless-stopped
|
||||
@@ -165,7 +180,7 @@ helper.mkPodmanService {
|
||||
- "websecure"
|
||||
service: nextcloud-onlyoffice
|
||||
middlewares:
|
||||
- "secureHeaders"
|
||||
- "nextcloudSecureHeaders"
|
||||
tls:
|
||||
certresolver: "cloudflare"
|
||||
options: "secureTLS"
|
||||
@@ -196,6 +211,39 @@ helper.mkPodmanService {
|
||||
- url: "http://host.containers.internal:3002"
|
||||
'';
|
||||
|
||||
environment.etc."traefik/rules/nextcloudSecureHeaders.yaml".text = ''
|
||||
http:
|
||||
middlewares:
|
||||
nextcloudSecureHeaders:
|
||||
headers:
|
||||
FrameDeny: false
|
||||
CustomFrameOptionsValue: "SAMEORIGIN"
|
||||
AddVaryHeader: true
|
||||
BrowserXssFilter: true
|
||||
ContentTypeNosniff: true
|
||||
ForceSTSHeader: true
|
||||
STSSeconds: 315360000
|
||||
STSIncludeSubdomains: true
|
||||
STSPreload: true
|
||||
AccessControlAllowMethods: "GET,OPTIONS,PUT"
|
||||
AccessControlAllowOriginList:
|
||||
- origin-list-or-null
|
||||
AccessControlMaxAge: 100
|
||||
ReferrerPolicy: same-origin
|
||||
PermissionsPolicy: "vibrate=()"
|
||||
ContentSecurityPolicy: >-
|
||||
default-src https://onlyoffice.${config.numbus.services.domain} 'self';
|
||||
script-src https://onlyoffice.${config.numbus.services.domain} 'self' 'unsafe-inline';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
connect-src 'self';
|
||||
img-src 'self' data:;
|
||||
font-src 'self' data:;
|
||||
frame-src https://onlyoffice.${config.numbus.services.domain} 'self';
|
||||
frame-ancestors https://onlyoffice.${config.numbus.services.domain} 'self';
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
'';
|
||||
|
||||
systemd.services."${name}-quirk" = {
|
||||
description = "Podman container quirk : ${name}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@@ -203,38 +251,62 @@ helper.mkPodmanService {
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
startLimitBurst = 5;
|
||||
startLimitIntervalSec = 600;
|
||||
path = [ pkgs.coreutils pkgs.sudo pkgs.podman ];
|
||||
path = [ pkgs.coreutils pkgs.sudo pkgs.podman pkgs.systemd pkgs.gnugrep ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /var/lib/numbus-server/${name}
|
||||
if [[ -e /var/lib/numbus-server/${name}/quirk.true ]]; then
|
||||
exit 0
|
||||
fi
|
||||
OCC="sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ"
|
||||
|
||||
[[ ! -e /var/lib/numbus-server/${name}/.env ]] && systemctl start ${name}-secrets.service
|
||||
until [[ -e /var/lib/numbus-server/${name}/.env ]]; do
|
||||
echo "Waiting for secrets generation..."
|
||||
sleep 5
|
||||
done
|
||||
source /var/lib/numbus-server/${name}/.env
|
||||
sleep 300
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ background:cron
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ db:add-missing-indices
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ maintenance:repair --include-expensive
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ files:scan --all
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ files:repair-tree
|
||||
for app in calendar contacts mail note onlyoffice cookbook whiteboard; do
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:install $app
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:enable $app
|
||||
|
||||
until $OCC status | grep -iq "installed: true" >/dev/null 2>&1; do
|
||||
echo "Waiting for Nextcloud to be up and running..."
|
||||
sleep 60
|
||||
done
|
||||
for app in activity app_api federatedfilesharing federation webhook_listeners photos recommendations sharebymail teams support richdocumentscode; do
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:disable $app
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ app:remove $app
|
||||
|
||||
$OCC db:add-missing-indices
|
||||
$OCC maintenance:repair --include-expensive
|
||||
|
||||
INSTALL_APPS_LIST=( "calendar" "contacts" "mail" "notes" "onlyoffice" "cookbook" "whiteboard" )
|
||||
DISABLE_APPS_LIST=( "activity" "federation" "webhook_listeners" "photos" "recommendations" "sharebymail" "teams" "support" "richdocumentscode" )
|
||||
|
||||
for app in ''${INSTALL_APPS_LIST[@]}; do
|
||||
if ! $OCC --no-warnings app:list | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:install "$app"
|
||||
fi
|
||||
if $OCC --no-warnings app:list --disabled | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:enable "$app"
|
||||
fi
|
||||
done
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice DocumentServerInternalUrl --value="https://onlyoffice.${config.numbus.services.domain}/"
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice DocumentServerUrl --value="https://onlyoffice.${config.numbus.services.domain}/"
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_PASSWORD"
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:app:set whiteboard collabBackendUrl --value="https://whiteboard.${config.numbus.services.domain}"
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ config:app:set whiteboard jwt_secret_key --value="$WHITEBOARD_PASSWORD"
|
||||
touch /var/lib/numbus-server/${name}/quirk.true
|
||||
for app in ''${DISABLE_APPS_LIST[@]}; do
|
||||
if $OCC --no-warnings app:list --enabled | grep -iq "$app:"; then
|
||||
$OCC --no-warnings app:disable "$app"
|
||||
fi
|
||||
done
|
||||
$OCC --no-warnings config:system:set onlyoffice DocumentServerInternalUrl --value="https://onlyoffice.${config.numbus.services.domain}/"
|
||||
$OCC --no-warnings config:system:set onlyoffice DocumentServerUrl --value="https://onlyoffice.${config.numbus.services.domain}/"
|
||||
$OCC --no-warnings config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_PASSWORD"
|
||||
$OCC --no-warnings config:app:set whiteboard collabBackendUrl --value="https://whiteboard.${config.numbus.services.domain}"
|
||||
$OCC --no-warnings config:app:set whiteboard jwt_secret_key --value="$WHITEBOARD_PASSWORD"
|
||||
|
||||
if [[ ! -f /var/lib/numbus-server/${name}/croned.true ]]; then
|
||||
$OCC background:cron
|
||||
sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php
|
||||
touch /var/lib/numbus-server/${name}/croned.true
|
||||
fi
|
||||
|
||||
if [[ ! -f /var/lib/numbus-server/${name}/scanned.true ]]; then
|
||||
$OCC files:scan --all
|
||||
$OCC files:repair-tree
|
||||
touch /var/lib/numbus-server/${name}/scanned.true
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -242,10 +314,11 @@ helper.mkPodmanService {
|
||||
description = "Podman container crontab : ${name}";
|
||||
after = [ "${name}.service" "${name}-quirk.service" ];
|
||||
onFailure = [ "service-failure-notify@%n.service" ];
|
||||
path = [ pkgs.coreutils pkgs.sudo pkgs.podman ];
|
||||
path = [ pkgs.sudo pkgs.podman ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php";
|
||||
ExecCondition = ''${pkgs.sudo}/bin/sudo -u numbus-admin podman exec --user www-data nextcloud-server php occ status'';
|
||||
ExecStart = "${pkgs.sudo}/bin/sudo -u numbus-admin podman exec --user www-data nextcloud-server php -f /var/www/html/cron.php";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@ helper.mkPodmanService {
|
||||
DB_PASSWORD = "xkcdpass -n 10 -d -";
|
||||
SMTP_PASSWORD = "cat ${config.numbus.mail.smtpPasswordPath}";
|
||||
};
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"100032:users ${cfg.configDir}/gpg"
|
||||
"100032:users ${cfg.configDir}/jwt"
|
||||
"100999:users ${cfg.configDir}/database"
|
||||
"100032:100 ${cfg.configDir}"
|
||||
"100032:100 ${cfg.configDir}/gpg"
|
||||
"100032:100 ${cfg.configDir}/jwt"
|
||||
"100999:100 ${cfg.configDir}/database"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
@@ -68,7 +70,7 @@ helper.mkPodmanService {
|
||||
"0",
|
||||
"passbolt-database:3306",
|
||||
"--",
|
||||
"/docker-entrypoint.sh",
|
||||
"/docker-entrypoint.sh"
|
||||
]
|
||||
depends_on:
|
||||
- passbolt-database
|
||||
|
||||
@@ -18,14 +18,15 @@ helper.mkPodmanService {
|
||||
pod = "false";
|
||||
defaultPort = "4443";
|
||||
scheme = "https";
|
||||
dependencies = [ "network.target" "multi-user.target" ];
|
||||
dataDir = false;
|
||||
dependencies = [ "network.target" ];
|
||||
dataDirEnabled = false;
|
||||
startDelay = 10;
|
||||
generatedSecrets = {
|
||||
PIHOLE_PASSWORD = "xkcdpass -n 10 -d -";
|
||||
};
|
||||
middlewares = [ "secureHeaders" ];
|
||||
dirPermissions = [
|
||||
"numbus-admin:users ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}"
|
||||
];
|
||||
|
||||
# Compose file good
|
||||
@@ -50,12 +51,15 @@ helper.mkPodmanService {
|
||||
FTLCONF_webserver_domain: ${cfg.subdomain}.${config.numbus.services.domain}
|
||||
FTLCONF_dns_upstreams: 9.9.9.9;149.112.112.112
|
||||
FTLCONF_dns_hosts: |
|
||||
${lib.concatStringsSep "" (lib.mapAttrsToList (name: service:
|
||||
if builtins.isAttrs service && service ? enable && service.enable && service ? subdomain then
|
||||
" ${config.numbus.networking.ipAddress} ${service.subdomain}.${config.numbus.services.domain}\n"
|
||||
else
|
||||
""
|
||||
) config.numbus.services)}
|
||||
${lib.concatStringsSep "" (lib.mapAttrsToList (name: service:
|
||||
if builtins.isAttrs service && service ? enable && service.enable && service ? subdomain then
|
||||
" ${config.numbus.networking.ipAddress} ${service.subdomain}.${config.numbus.services.domain}\n" +
|
||||
(if name == "nextcloud" then
|
||||
" ${config.numbus.networking.ipAddress} onlyoffice.${config.numbus.services.domain}\n" +
|
||||
" ${config.numbus.networking.ipAddress} whiteboard.${config.numbus.services.domain}\n"
|
||||
else "")
|
||||
else ""
|
||||
) config.numbus.services)}
|
||||
FTLCONF_dns_listeningMode: "BIND"
|
||||
FTLCONF_dns_domain_name: "${config.numbus.services.domain}"
|
||||
FTLCONF_dns_domain_local: "true"
|
||||
|
||||
@@ -4,7 +4,7 @@ with lib;
|
||||
|
||||
let
|
||||
# Version tagging
|
||||
traefikVersion = "v3.6.8";
|
||||
traefikVersion = "v3.7.4";
|
||||
# Helper
|
||||
helper = import ./lib.nix { inherit config pkgs lib; };
|
||||
cfg = config.numbus.services.traefik;
|
||||
@@ -16,16 +16,18 @@ helper.mkPodmanService {
|
||||
inherit name;
|
||||
description = "Traefik reverse proxy, one to rule them all";
|
||||
pod = "false";
|
||||
reverseProxied = false;
|
||||
dataDir = false;
|
||||
dependencies = [ "network.target" "multi-user.target" ];
|
||||
dataDirEnabled = false;
|
||||
dependencies = [ "network.target" ];
|
||||
startDelay = 10;
|
||||
generatedSecrets = {
|
||||
CLOUDFLARE_DNS_API_TOKEN = "cat ${config.sops.secrets."cloudflareDnsApiToken".path}";
|
||||
};
|
||||
dirPermissions = [
|
||||
"100999:users ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}"
|
||||
"100999:100 ${cfg.configDir}/rules"
|
||||
"100999:100 ${cfg.configDir}/certs"
|
||||
];
|
||||
reverseProxied = false;
|
||||
|
||||
# Compose file good
|
||||
composeText = ''
|
||||
@@ -149,7 +151,7 @@ helper.mkPodmanService {
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
cp -ravu /etc/traefik/* ${cfg.configDir}
|
||||
cp -Lurv /etc/traefik/* ${cfg.configDir}
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -162,6 +164,5 @@ helper.mkPodmanService {
|
||||
example = "ERROR";
|
||||
description = "The level of detail Traefik should print in the logs.";
|
||||
};
|
||||
# traefikDynamicConfigDir defined at global.nix
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.numbus.services.virtualization;
|
||||
in
|
||||
|
||||
{
|
||||
options.numbus.services.virtualization = {
|
||||
enable = mkEnableOption "QEMU/KVM virtualization software";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation.libvirtd.enable = true;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user