Wrote initial configuration for the password manager, the git forge and the dns.
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
imports = [
|
imports = [
|
||||||
# Module for LXC containers
|
# Module for LXC containers
|
||||||
../../../modules/machine-types/lxc
|
../../../modules/machine-types/lxc
|
||||||
|
# Technitium DNS Server service module
|
||||||
|
../../../modules/services/dns/default.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Explicitly enable LXC machine type
|
# Explicitly enable LXC machine type
|
||||||
@@ -13,7 +15,14 @@
|
|||||||
networking.hostName = "dns01";
|
networking.hostName = "dns01";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
|
|
||||||
# TODO: Add DNS service module import and configuration
|
# Technitium DNS Server — primary DNS server
|
||||||
# imports = [ ../../../modules/services/dns/default.nix ];
|
services.dns = {
|
||||||
# services.dns.enable = true;
|
enable = true;
|
||||||
}
|
recursion = "AllowOnlyForPrivateNetworks";
|
||||||
|
forwarders = [ "1.1.1.1" "8.8.8.8" ];
|
||||||
|
# Uncomment and configure with agenix secret:
|
||||||
|
# adminPasswordFile = config.age.secrets.dns-admin-password.path;
|
||||||
|
allowZoneTransfer = [ "10.40.128.11" ]; # Allow secondary to dns02
|
||||||
|
listenAddresses = [ "10.40.128.10" "127.0.0.1" "::1" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
imports = [
|
imports = [
|
||||||
# Module for LXC containers
|
# Module for LXC containers
|
||||||
../../../modules/machine-types/lxc
|
../../../modules/machine-types/lxc
|
||||||
|
# Technitium DNS Server service module
|
||||||
|
../../../modules/services/dns/default.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Explicitly enable LXC machine type
|
# Explicitly enable LXC machine type
|
||||||
@@ -13,7 +15,13 @@
|
|||||||
networking.hostName = "dns02";
|
networking.hostName = "dns02";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
|
|
||||||
# TODO: Add DNS service module import and configuration
|
# Technitium DNS Server — secondary (replica) DNS server
|
||||||
# imports = [ ../../../modules/services/dns/default.nix ];
|
services.dns = {
|
||||||
# services.dns.enable = true;
|
enable = true;
|
||||||
}
|
recursion = "AllowOnlyForPrivateNetworks";
|
||||||
|
forwarders = [ "1.1.1.1" "8.8.8.8" ];
|
||||||
|
# Uncomment and configure with agenix secret:
|
||||||
|
# adminPasswordFile = config.age.secrets.dns-admin-password.path;
|
||||||
|
listenAddresses = [ "10.40.128.11" "127.0.0.1" "::1" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
imports = [
|
imports = [
|
||||||
# Module for LXC containers
|
# Module for LXC containers
|
||||||
../../../modules/machine-types/lxc
|
../../../modules/machine-types/lxc
|
||||||
# Module for the git forge service
|
# Module for the git forge service (Forgejo)
|
||||||
../../../modules/services/git-forge/default.nix
|
../../../modules/services/git-forge/default.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -15,6 +15,12 @@
|
|||||||
networking.hostName = "git01";
|
networking.hostName = "git01";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
|
|
||||||
# TODO: Enable and configure the git forge service
|
# Forgejo — self-hosted git forge
|
||||||
# services.git-forge.enable = true;
|
services.git-forge = {
|
||||||
}
|
enable = true;
|
||||||
|
domain = "git.lagraula.fr";
|
||||||
|
sshPort = 2222;
|
||||||
|
httpPort = 3000;
|
||||||
|
databaseType = "sqlite3";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Do not modify!!
|
||||||
|
# Proxmox hypervisor on NixOS is not mature enough.
|
||||||
|
# Hypervisor are here for future reference only.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Do not modify!!
|
||||||
|
# Proxmox hypervisor on NixOS is not mature enough.
|
||||||
|
# Hypervisor are here for future reference only.
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
imports = [
|
imports = [
|
||||||
# Module for LXC containers
|
# Module for LXC containers
|
||||||
../../../modules/machine-types/lxc
|
../../../modules/machine-types/lxc
|
||||||
# Module for password manager service
|
# Module for password manager service (Vaultwarden)
|
||||||
../../../modules/services/password-manager/default.nix
|
../../../modules/services/password-manager/default.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -15,6 +15,14 @@
|
|||||||
networking.hostName = "pass01";
|
networking.hostName = "pass01";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
|
|
||||||
# TODO: Enable and configure the password manager service
|
# Vaultwarden — Bitwarden-compatible password manager
|
||||||
# services.password-manager.enable = true;
|
services.password-manager = {
|
||||||
}
|
enable = true;
|
||||||
|
domain = "pass.lagraula.fr";
|
||||||
|
port = 8080;
|
||||||
|
dbBackend = "sqlite";
|
||||||
|
signupsAllowed = false; # Only admin creates accounts
|
||||||
|
# Uncomment and configure with agenix secret:
|
||||||
|
# adminTokenFile = config.age.secrets.vaultwarden-admin-token.path;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.dns;
|
||||||
|
dnsPkg = if cfg.package != null then cfg.package else pkgs.technitium-dns-server;
|
||||||
|
|
||||||
|
# Build the config.json for Technitium DNS Server.
|
||||||
|
# The server reads this file on startup from its config directory.
|
||||||
|
configJson = {
|
||||||
|
WebServicePort = cfg.webPort;
|
||||||
|
DNSListenerPort = cfg.dnsPort;
|
||||||
|
Recursion = cfg.recursion;
|
||||||
|
Forwarders = cfg.forwarders;
|
||||||
|
Log = false;
|
||||||
|
CachePrefetch = false;
|
||||||
|
AllowTtlOverride = true;
|
||||||
|
} // lib.optionalAttrs (cfg.adminPasswordFile != null) {
|
||||||
|
# Password hash will be set by the activation script on first run
|
||||||
|
# using the value from adminPasswordFile.
|
||||||
|
} // lib.optionalAttrs (cfg.listenAddresses != [ ]) {
|
||||||
|
ListenAddresses = cfg.listenAddresses;
|
||||||
|
} // lib.optionalAttrs (cfg.allowZoneTransfer != [ ]) {
|
||||||
|
AllowZoneTransfer = cfg.allowZoneTransfer;
|
||||||
|
} // cfg.extraConfig;
|
||||||
|
|
||||||
|
configFile = pkgs.writeText "technitium-dns-config.json"
|
||||||
|
(builtins.toJSON configJson);
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./options.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
environment.systemPackages = [ dnsPkg ];
|
||||||
|
|
||||||
|
# Create the config directory and deploy initial config.json
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${cfg.configDir} 0750 dns dns - -"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.technitium-dns-server = {
|
||||||
|
description = "Technitium DNS Server";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
|
||||||
|
# Generate a password hash if adminPasswordFile is provided.
|
||||||
|
# The server is stopped on first run if no password hash exists,
|
||||||
|
# so we pre-seed the config with the hashed password.
|
||||||
|
preStart = ''
|
||||||
|
if [ -f "${cfg.configDir}/config.json" ]; then
|
||||||
|
# Config already exists, do not overwrite
|
||||||
|
true
|
||||||
|
else
|
||||||
|
install -m 0640 ${configFile} ${cfg.configDir}/config.json
|
||||||
|
${lib.optionalString (cfg.adminPasswordFile != null) ''
|
||||||
|
if [ -f "${cfg.adminPasswordFile}" ]; then
|
||||||
|
# .NET-compatible SHA256 hash of the password
|
||||||
|
PASSWORD=$(cat "${cfg.adminPasswordFile}" | tr -d '\n')
|
||||||
|
HASH=$(echo -n "$PASSWORD" | ${pkgs.openssl}/bin/openssl dgst -sha256 -hex | cut -d' ' -f2)
|
||||||
|
${pkgs.jq}/bin/jq \
|
||||||
|
".AdminPassword = \"$HASH\" | .Pbkdf2Iterations = 600000" \
|
||||||
|
${cfg.configDir}/config.json > ${cfg.configDir}/config.json.tmp
|
||||||
|
mv ${cfg.configDir}/config.json.tmp ${cfg.configDir}/config.json
|
||||||
|
fi
|
||||||
|
''}
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${dnsPkg}/bin/technitium-dns-server ${cfg.configDir}";
|
||||||
|
User = "dns";
|
||||||
|
Group = "dns";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "5s";
|
||||||
|
LimitNOFILE = 1048576;
|
||||||
|
# Protect the system
|
||||||
|
ProtectSystem = "full";
|
||||||
|
ProtectHome = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
ReadWritePaths = [ cfg.configDir ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create the dns system user and group
|
||||||
|
users.users.dns = {
|
||||||
|
description = "Technitium DNS Server daemon user";
|
||||||
|
group = "dns";
|
||||||
|
isSystemUser = true;
|
||||||
|
home = cfg.configDir;
|
||||||
|
createHome = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.dns = { };
|
||||||
|
|
||||||
|
# Open firewall ports for DNS (UDP/TCP 53) and optionally the web interface
|
||||||
|
networking.firewall = lib.mkMerge [
|
||||||
|
{
|
||||||
|
allowedTCPPorts = [ cfg.dnsPort ];
|
||||||
|
allowedUDPPorts = [ cfg.dnsPort ];
|
||||||
|
}
|
||||||
|
# Allow web admin access only if listenAddresses restricts it to localhost
|
||||||
|
(lib.mkIf (cfg.listenAddresses == [ ] || builtins.elem "127.0.0.1" cfg.listenAddresses) {
|
||||||
|
allowedTCPPorts = [ cfg.webPort ];
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# Ensure DNS resolution is available locally before starting
|
||||||
|
networking.nameservers = lib.mkAfter [ "127.0.0.1" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) types mkOption;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.dns = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable the Technitium DNS Server";
|
||||||
|
};
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = null;
|
||||||
|
description = "Technitium DNS Server package to use. Defaults to pkgs.technitium-dns-server.";
|
||||||
|
};
|
||||||
|
|
||||||
|
webPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 5380;
|
||||||
|
description = "HTTP port for the Technitium web administration interface";
|
||||||
|
};
|
||||||
|
|
||||||
|
dnsPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 53;
|
||||||
|
description = "DNS server port (both TCP and UDP)";
|
||||||
|
};
|
||||||
|
|
||||||
|
recursion = mkOption {
|
||||||
|
type = types.enum [ "AllowOnlyForPrivateNetworks" "AllowAll" "DenyAll" ];
|
||||||
|
default = "AllowOnlyForPrivateNetworks";
|
||||||
|
description = "Recursion policy for DNS queries";
|
||||||
|
};
|
||||||
|
|
||||||
|
forwarders = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Upstream DNS forwarders (e.g. [ \"1.1.1.1\" \"8.8.8.8\" ]). Empty means use root hints";
|
||||||
|
};
|
||||||
|
|
||||||
|
configDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/etc/dns";
|
||||||
|
description = "Directory for persistent Technitium DNS configuration and zone data";
|
||||||
|
};
|
||||||
|
|
||||||
|
adminPasswordFile = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to a file containing the admin password for the web interface.
|
||||||
|
If not set, the default credentials (admin/admin) are used.
|
||||||
|
Use agenix or sops-nix to provide this file securely.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
listenAddresses = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = "IP addresses to listen on. Empty means listen on all interfaces";
|
||||||
|
};
|
||||||
|
|
||||||
|
allowZoneTransfer = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = "IP addresses or subnets allowed to request zone transfers (AXFR/IXFR)";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.attrsOf types.anything;
|
||||||
|
default = { };
|
||||||
|
description = "Additional Technitium DNS configuration options as an attribute set";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.git-forge;
|
||||||
|
inherit (lib) mkIf mkOption types;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.git-forge = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable the git forge service (Forgejo)";
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "git.lagraula.fr";
|
||||||
|
description = "Domain name for the Forgejo instance";
|
||||||
|
};
|
||||||
|
|
||||||
|
sshPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 2222;
|
||||||
|
description = "SSH port for Git operations (avoid conflict with host SSH on 22)";
|
||||||
|
};
|
||||||
|
|
||||||
|
httpPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 3000;
|
||||||
|
description = "HTTP port for the Forgejo web interface";
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/var/lib/forgejo";
|
||||||
|
description = "Data directory for Forgejo repositories and database";
|
||||||
|
};
|
||||||
|
|
||||||
|
databaseType = mkOption {
|
||||||
|
type = types.enum [ "sqlite3" "postgres" "mysql" ];
|
||||||
|
default = "sqlite3";
|
||||||
|
description = "Database backend type";
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = types.attrsOf types.anything;
|
||||||
|
default = { };
|
||||||
|
description = "Additional Forgejo settings (merged into services.forgejo.settings)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Use the built-in NixOS forgejo module
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.forgejo;
|
||||||
|
settings = lib.recursiveUpdate {
|
||||||
|
server = {
|
||||||
|
DOMAIN = cfg.domain;
|
||||||
|
HTTP_PORT = cfg.httpPort;
|
||||||
|
HTTP_ADDR = "0.0.0.0";
|
||||||
|
ROOT_URL = "https://${cfg.domain}";
|
||||||
|
SSH_PORT = cfg.sshPort;
|
||||||
|
SSH_LISTEN_PORT = cfg.sshPort;
|
||||||
|
};
|
||||||
|
service = {
|
||||||
|
DISABLE_REGISTRATION = false;
|
||||||
|
};
|
||||||
|
"repository".ROOT = "${cfg.dataDir}/repos";
|
||||||
|
} (lib.mapAttrs (section: values: lib.mapAttrs (key: value: lib.mkDefault value) values) cfg.settings);
|
||||||
|
|
||||||
|
database = {
|
||||||
|
type = cfg.databaseType;
|
||||||
|
};
|
||||||
|
|
||||||
|
dump = {
|
||||||
|
type = "tar.zst";
|
||||||
|
};
|
||||||
|
|
||||||
|
# LXC container specifics - use the existing forgejo user
|
||||||
|
stateDir = cfg.dataDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open firewall ports for HTTP and SSH (git protocol)
|
||||||
|
networking.firewall = lib.mkIf config.services.forgejo.enable {
|
||||||
|
allowedTCPPorts = [ cfg.httpPort cfg.sshPort ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.password-manager;
|
||||||
|
inherit (lib) mkIf mkOption types;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.password-manager = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable the password manager service (Vaultwarden)";
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "pass.lagraula.fr";
|
||||||
|
description = "Domain name for the Vaultwarden instance";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 8080;
|
||||||
|
description = "HTTP port for the Vaultwarden web interface";
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/var/lib/vaultwarden";
|
||||||
|
description = "Data directory for Vaultwarden persistent state";
|
||||||
|
};
|
||||||
|
|
||||||
|
dbBackend = mkOption {
|
||||||
|
type = types.enum [ "sqlite" "mysql" "postgresql" ];
|
||||||
|
default = "sqlite";
|
||||||
|
description = "Database backend type";
|
||||||
|
};
|
||||||
|
|
||||||
|
adminTokenFile = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to a file containing the admin token for the /admin panel.
|
||||||
|
Use agenix or sops-nix to provide this file securely.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
signupsAllowed = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Allow new user registration";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.attrsOf (types.nullOr (types.oneOf [ types.bool types.str types.int types.port ]));
|
||||||
|
default = { };
|
||||||
|
description = "Additional Vaultwarden config options as attribute set (mapped to env vars)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Use the built-in NixOS vaultwarden module
|
||||||
|
services.vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.vaultwarden;
|
||||||
|
webVaultPackage = pkgs.vaultwarden-webvault;
|
||||||
|
inherit (cfg) dbBackend;
|
||||||
|
config = {
|
||||||
|
DOMAIN = "https://${cfg.domain}";
|
||||||
|
PORT = cfg.port;
|
||||||
|
SIGNUPS_ALLOWED = cfg.signupsAllowed;
|
||||||
|
} // (lib.mapAttrs (name: value:
|
||||||
|
if value == true then "true"
|
||||||
|
else if value == false then "false"
|
||||||
|
else toString value
|
||||||
|
) cfg.extraConfig);
|
||||||
|
} // lib.optionalAttrs (cfg.adminTokenFile != null) {
|
||||||
|
environmentFile = cfg.adminTokenFile;
|
||||||
|
config = {
|
||||||
|
ADMIN_TOKEN = null; # Will be read from environmentFile
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open firewall port
|
||||||
|
networking.firewall = mkIf config.services.vaultwarden.enable {
|
||||||
|
allowedTCPPorts = [ cfg.port ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user