Compare commits

...

4 commits

13 changed files with 309 additions and 379 deletions

1
hosts/dev/channel Normal file
View file

@ -0,0 +1 @@
https://channels.nixos.org/nixos-25.11

107
hosts/dev/configuration.nix Normal file
View file

@ -0,0 +1,107 @@
{ config, lib, pkgs, ... }:
let
projectsDir = "projects"; # Relative to /home/dominik
repositories = [
{ url = "gitea@git.cloonar.com:Cloonar/wohnservice-wien-typo3.git"; path = "cloonar/wohnservice-wien"; }
# Add repos here: { url = "git@..."; path = "relative/path"; }
];
cloneScript = pkgs.writeShellScript "clone-repos" ''
set -eu
export PATH="${pkgs.openssh}/bin:$PATH"
export GIT_SSH_COMMAND="${pkgs.openssh}/bin/ssh"
HOME_DIR="/home/dominik"
PROJECTS_DIR="$HOME_DIR/${projectsDir}"
mkdir -p "$PROJECTS_DIR"
chown dominik:users "$PROJECTS_DIR"
${lib.concatMapStrings (repo: ''
if [ ! -d "$PROJECTS_DIR/${repo.path}" ]; then
${pkgs.sudo}/bin/sudo -u dominik -E ${pkgs.git}/bin/git clone ${repo.url} "$PROJECTS_DIR/${repo.path}" || true
fi
'') repositories}
'';
in
{
imports = [
./modules/dev-tools.nix
];
networking.hostName = "dev";
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 80 443 ];
};
system.stateVersion = "22.05";
time.timeZone = "Europe/Vienna";
# User configuration
users.users.dominik = {
isNormalUser = true;
uid = 1000;
home = "/home/dominik";
extraGroups = [ "wheel" "docker" ];
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
];
};
users.groups.users = {};
services.openssh.enable = true;
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
# Auto-attach to tmux on SSH login
environment.interactiveShellInit = ''
if [[ -n "$SSH_CONNECTION" ]] && [[ -z "$TMUX" ]]; then
tmux attach-session -t main 2>/dev/null || tmux new-session -s main
fi
'';
# Passwordless sudo for dominik
security.sudo.extraRules = [{
users = [ "dominik" ];
commands = [{
command = "ALL";
options = [ "NOPASSWD" ];
}];
}];
# Clone repos as dominik user on boot
systemd.services.clone-repos = {
description = "Clone configured git repositories";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = cloneScript;
RemainAfterExit = true;
};
};
# Create ddev global config to bind on all interfaces (allows access from other devices)
systemd.services.ddev-config = {
description = "Create ddev global config";
after = [ "local-fs.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "dominik";
Group = "users";
};
script = ''
mkdir -p /home/dominik/.ddev
if [ ! -f /home/dominik/.ddev/global_config.yaml ]; then
cat > /home/dominik/.ddev/global_config.yaml << 'EOF'
router_bind_all_interfaces: true
EOF
fi
'';
};
}

View file

@ -0,0 +1,53 @@
{ pkgs, ... }:
{
nixpkgs.overlays = [
(import ../utils/overlays/packages.nix)
];
environment.systemPackages = with pkgs; [
# Development tools
ddev
docker-compose
git
git-lfs
mkcert
screen
# PHP
php
# Node.js
nodejs_22
# AI coding
claude-code
# Utilities
jq
unzip
vim
wget
curl
htop
];
# Persistent SSH sessions with tmux
programs.tmux = {
enable = true;
clock24 = true;
historyLimit = 50000;
terminal = "screen-256color";
extraConfig = ''
# Enable mouse support
set -g mouse on
# Start windows and panes at 1, not 0
set -g base-index 1
setw -g pane-base-index 1
'';
};
# Docker for ddev
virtualisation.docker.enable = true;
users.users.dominik.extraGroups = [ "docker" ];
}

1
hosts/dev/utils Symbolic link
View file

@ -0,0 +1 @@
../../utils

View file

@ -34,6 +34,7 @@
./modules/microvm.nix
./modules/gitea-vm.nix
./modules/forgejo-runner.nix
./modules/dev-microvm.nix
# ./modules/vscode-server.nix # Add VS Code Server microvm
./modules/ai-mailer.nix
@ -94,6 +95,7 @@
"mongodb"
"ai-mailer"
"filebot"
"claude-code"
];
# Intel N100 Graphics Support for hardware transcoding

1
hosts/fw/dev Symbolic link
View file

@ -0,0 +1 @@
../dev

View file

@ -0,0 +1,73 @@
{ lib, pkgs, config, ... }:
let
hostname = "dev";
in
{
# Create persist directories on the host
# UID 1000 = dominik user inside the microvm
systemd.tmpfiles.rules = [
"d /var/lib/microvm-persist 0755 root root -"
"d /var/lib/microvm-persist/dev 0755 root root -"
"d /var/lib/microvm-persist/dev/home 0755 root root -"
"d /var/lib/microvm-persist/dev/home/dominik 0700 1000 100 -"
];
microvm.vms.dev = {
# Use host's pkgs which already has overlays applied
inherit pkgs;
config = {
imports = [
../dev/configuration.nix
./network-prefix.nix
];
networkPrefix = config.networkPrefix;
microvm = {
mem = 4096;
vcpu = 2;
shares = [
{
source = "/nix/store";
mountPoint = "/nix/.ro-store";
tag = "ro-store";
proto = "virtiofs";
}
{
source = "/var/lib/microvm-persist/dev";
mountPoint = "/persist";
tag = "persist";
proto = "virtiofs";
}
{
source = "/var/lib/microvm-persist/dev/home";
mountPoint = "/home";
tag = "home";
proto = "virtiofs";
}
];
volumes = [{
image = "rootfs.img";
mountPoint = "/";
size = 51200;
}];
interfaces = [{
type = "tap";
id = "vm-${hostname}";
mac = "02:00:00:00:02:01";
}];
};
systemd.network.networks."10-lan" = {
matchConfig.PermanentMACAddress = "02:00:00:00:02:01";
address = [ "${config.networkPrefix}.97.15/24" ];
gateway = [ "${config.networkPrefix}.97.1" ];
dns = [ "${config.networkPrefix}.97.1" ];
};
};
};
}

View file

@ -97,6 +97,8 @@
"/invidious.cloonar.com/${config.networkPrefix}.97.5"
"/fivefilters.cloonar.com/${config.networkPrefix}.97.5"
"/n8n.cloonar.com/${config.networkPrefix}.97.5"
"/dev.cloonar.com/${config.networkPrefix}.97.15"
"/.ddev.site/${config.networkPrefix}.97.15" # Wildcard for ddev projects
"/home-assistant.cloonar.com/${config.networkPrefix}.97.20"
"/mopidy.cloonar.com/${config.networkPrefix}.97.21"
"/snapcast.cloonar.com/${config.networkPrefix}.97.21"

View file

@ -1,349 +0,0 @@
{ config, pkgs, ... }:
let
cids = import ../modules/staticids.nix;
domain = "ns.cloonar.com";
adblockLocalZones = pkgs.stdenv.mkDerivation {
name = "unbound-zones-adblock";
src = (pkgs.fetchFromGitHub {
owner = "StevenBlack";
repo = "hosts";
rev = "3.0.0";
sha256 = "01g6pc9s1ah2w1cbf6bvi424762hkbpbgja9585a0w99cq0n6bxv";
} + "/hosts");
phases = [ "installPhase" ];
installPhase = ''
${pkgs.gawk}/bin/awk '{sub(/\r$/,"")} {sub(/^127\.0\.0\.1/,"0.0.0.0")} BEGIN { OFS = "" } NF == 2 && $1 == "0.0.0.0" { print "local-zone: \"", $2, "\" static"}' $src | tr '[:upper:]' '[:lower:]' | sort -u > $out
'';
};
cfg = {
remote-control.control-enable = true;
server = {
# include = [
# "\"${adblockLocalZones}\""
# ];
interface = [ "0.0.0.0" "::0" ];
interface-automatic = "yes";
access-control = [
"127.0.0.0/8 allow"
"${config.networkPrefix}.96.0/24 allow"
"${config.networkPrefix}.97.0/24 allow"
"${config.networkPrefix}.98.0/24 allow"
"${config.networkPrefix}.99.0/24 allow"
"${config.networkPrefix}.101.0/24 allow"
"0.0.0.0/0 allow"
];
tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt";
local-zone = "\"cloonar.com\" transparent";
local-data = [
"\"localhost A 127.0.0.1\""
"\"localhost.cloonar.com A 127.0.0.1\""
"\"localhost AAAA ::1\""
"\"localhost.cloonar.com AAAA ::1\""
"\"fw.cloonar.com A ${config.networkPrefix}.97.1\""
"\"fw A ${config.networkPrefix}.97.1\""
"\"www.7-zip.org A 49.12.202.237\""
"\"pc.cloonar.com IN A ${config.networkPrefix}.96.5\""
"\"omada.cloonar.com IN A ${config.networkPrefix}.97.2\""
"\"switch.cloonar.com IN A ${config.networkPrefix}.97.10\""
"\"mopidy.cloonar.com IN A ${config.networkPrefix}.97.21\""
"\"deconz.cloonar.com IN A ${config.networkPrefix}.97.22\""
"\"wazuh-manager.cloonar.com IN A ${config.networkPrefix}.97.31\""
"\"wazuh-indexer.cloonar.com IN A ${config.networkPrefix}.97.32\""
"\"wazuh.cloonar.com IN A ${config.networkPrefix}.97.33\""
"\"brn30055c566237.cloonar.com IN A ${config.networkPrefix}.96.100\""
"\"snapcast.cloonar.com IN A ${config.networkPrefix}.97.21\""
"\"home-assistant.cloonar.com IN A ${config.networkPrefix}.97.20\""
"\"web-02.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"matrix.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"element.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"support.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"tinder.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"git.cloonar.com IN A ${config.networkPrefix}.97.50\""
"\"sync.cloonar.com IN A ${config.networkPrefix}.97.51\""
"\"feeds.cloonar.com IN A 188.34.191.144\""
# "\"paraclub.cloonar.dev IN A 49.12.244.139\""
# "\"api.paraclub.cloonar.dev IN A 49.12.244.139\""
# "\"module.paraclub.cloonar.dev IN A 49.12.244.139\""
# "\"tandem.paraclub.cloonar.dev IN A 49.12.244.139\""
"\"stage.wsw.at IN A 10.254.235.22\""
"\"prod.wsw.at IN A 10.254.217.23\""
"\"piwik.wohnservice-wien.at IN A 10.254.240.109\""
"\"wohnservice-wien.at IN A 10.254.240.109\""
"\"mieterhilfe.at IN A 10.254.240.109\""
"\"wohnpartner-wien.at IN A 10.254.240.109\""
"\"new.wohnberatung-wien.at IN A 10.254.240.109\""
"\"new.wohnpartner-wien.at IN A 10.254.240.109\""
"\"wohnberatung-wien.at IN A 10.254.240.109\""
"\"wienbautvor.at IN A 10.254.240.109\""
"\"wienwohntbesser.at IN A 10.254.240.109\""
"\"b.wohnservice-wien.at IN A 10.254.240.109\""
"\"b.mieterhilfe.at IN A 10.254.240.109\""
"\"b.wohnpartner-wien.at IN A 10.254.240.109\""
"\"b.wohnberatung-wien.at IN A 10.254.240.109\""
"\"b.wienbautvor.at IN A 10.254.240.109\""
"\"b.wienwohntbesser.at IN A 10.254.240.109\""
"\"a.wohnservice-wien.at IN A 10.254.240.109\""
"\"a.wohnpartner-wien.at IN A 10.254.240.109\""
"\"a.stage.wohnservice-wien.at IN A 10.254.240.110\""
"\"a.stage.mieterhilfe.at IN A 10.254.240.110\""
"\"a.stage.wohnpartner-wien.at IN A 10.254.240.110\""
"\"a.stage.wohnberatung-wien.at IN A 10.254.240.110\""
"\"a.stage.wienbautvor.at IN A 10.254.240.110\""
"\"a.stage.wienwohntbesser.at IN A 10.254.240.110\""
"\"b.stage.wohnservice-wien.at IN A 10.254.240.110\""
"\"b.stage.mieterhilfe.at IN A 10.254.240.110\""
"\"b.stage.wohnpartner-wien.at IN A 10.254.240.110\""
"\"b.stage.new.wohnberatung-wien.at IN A 10.254.240.110\""
"\"b.stage.new.wohnpartner-wien.at IN A 10.254.240.110\""
"\"b.stage.wohnberatung-wien.at IN A 10.254.240.110\""
"\"b.stage.wienbautvor.at IN A 10.254.240.110\""
"\"b.stage.wienwohntbesser.at IN A 10.254.240.110\""
"\"upgrade-staging.wohnservice-wien.at IN A 10.254.240.110\""
"\"upgrade-staging.mieterhilfe.at IN A 10.254.240.110\""
"\"upgrade-staging.wohnpartner-wien.at IN A 10.254.240.110\""
"\"upgrade-staging.wohnberatung-wien.at IN A 10.254.240.110\""
"\"upgrade-staging.wienbautvor.at IN A 10.254.240.110\""
"\"upgrade-staging.wienwohntbesser.at IN A 10.254.240.110\""
"\"conf.wrwks.at IN A 10.254.240.105\""
"\"web.hilgenberg-gmbh.de IN A 91.107.197.169\""
"\"web.lenaschilling.at IN A 159.69.3.18\""
# gaming
"\"foundry-vtt.cloonar.com IN A ${config.networkPrefix}.97.5\""
"\"deconz.cloonar.multimedia IN A ${config.networkPrefix}.97.22\""
"\"metz.cloonar.multimedia IN A ${config.networkPrefix}.99.10\""
# "\"ps5.cloonar.multimedia IN A ${config.networkPrefix}.99.12\""
"\"xbox.cloonar.multimedia IN A ${config.networkPrefix}.99.13\""
# "\"switch.cloonar.multimedia IN A ${config.networkPrefix}.99.14\""
#living room
"\"shellyuni-livingroom-1.cloonar.smart IN A ${config.networkPrefix}.100.8\""
"\"shellyswitch25-livingroom-1.cloonar.smart IN A ${config.networkPrefix}.100.9\""
"\"shellyplug-s-living-1.cloonar.smart IN A ${config.networkPrefix}.100.10\""
"\"shellyplug-s-living-2.cloonar.smart IN A ${config.networkPrefix}.100.11\""
# kitchen
"\"shellyplug-s-kitchen-1.cloonar.smart IN A ${config.networkPrefix}.100.17\""
"\"shellyrgbw2-kitchen-1.cloonar.smart IN A ${config.networkPrefix}.100.18\""
#bedroom
"\"shelly1-bedroom-1.cloonar.smart IN A ${config.networkPrefix}.100.33\""
"\"shellybutton1-bedroom-1.cloonar.smart IN A ${config.networkPrefix}.100.34\""
"\"shellybutton1-bedroom-2.cloonar.smart IN A ${config.networkPrefix}.100.35\"" # todo
"\"shellyrgbw2-bedroom-1.cloonar.smart IN A ${config.networkPrefix}.100.36\""
"\"shellyrgbw2-bedroom-2.cloonar.smart IN A ${config.networkPrefix}.100.37\""
"\"shellyrgbw2-bedroom-3.cloonar.smart IN A ${config.networkPrefix}.100.38\""
# bath
"\"shellyswitch25-bath-1.cloonar.smart IN A ${config.networkPrefix}.100.49\""
"\"shelly1pm-bath-1.cloonar.smart IN A ${config.networkPrefix}.100.52\""
"\"shellyht-bath-1.cloonar.smart IN A ${config.networkPrefix}.100.53\"" # todo
# hallway
"\"shelly1-hallway-1.cloonar.smart IN A ${config.networkPrefix}.100.65\""
"\"shellyem3.cloonar.smart IN A ${config.networkPrefix}.100.70\""
"\"shellypro-1.cloonar.smart IN A ${config.networkPrefix}.100.71\""
"\"shellypro-2.cloonar.smart IN A ${config.networkPrefix}.100.72\""
# toilet
"\"shelly1-toilet-1.cloonar.smart IN A ${config.networkPrefix}.100.81\""
"\"shellybulbduo-toilet-1.cloonar.smart IN A ${config.networkPrefix}.100.82\""
# storage
"\"shelly1-storage-1.cloonar.smart IN A ${config.networkPrefix}.100.97\""
"\"shellyplug-storage-1.cloonar.smart IN A ${config.networkPrefix}.100.98\""
"\"brn30055c566237.cloonar.multimedia IN A ${config.networkPrefix}.99.100\""
"\"ddl-warez.to IN A 172.67.184.30\""
"\"cdnjs.cloudflare.com IN A 104.17.24.14\""
];
local-data-ptr = [
"\"127.0.0.1 localhost\""
"\"::1 localhost\""
"\"${config.networkPrefix}.97.1 fw.cloonar.com\""
"\"${config.networkPrefix}.97.20 home-assistant.cloonar.com\""
"\"${config.networkPrefix}.97.21 snapcast.cloonar.com\""
"\"${config.networkPrefix}.97.22 deconz.cloonar.com\""
"\"${config.networkPrefix}.97.50 git.cloonar.com\""
"\"10.254.235.22 stage.wsw.at\""
"\"10.254.217.23 prod.wsw.at\""
"\"10.254.240.109 wohnservice-wien.at\""
"\"10.254.240.110 a.stage.wohnservice-wien.at\""
"\"172.67.184.30 ddl-warez.to\""
"\"104.17.24.14 cdnjs.cloudflare.com\""
];
# ssl-upstream = "yes";
};
forward-zone = [
{
name = "local.ghetto.at.";
forward-tls-upstream = "no";
forward-addr = [
"10.43.97.1"
];
}
{
name = "ghetto.at.local.";
forward-tls-upstream = "no";
forward-addr = [
"10.43.97.1"
];
}
{
name = "epicenter.works.";
forward-tls-upstream = "no";
forward-addr = [
"10.50.60.1"
];
}
{
name = "akvorrat.at.";
forward-tls-upstream = "no";
forward-addr = [
"10.50.60.1"
];
}
{
name = "epicenter.intra.";
forward-tls-upstream = "no";
forward-addr = [
"10.14.1.1"
];
}
{
name = "intra.epicenter.works.";
forward-tls-upstream = "no";
forward-addr = [
"10.14.1.1"
];
}
{
name = ".";
forward-tls-upstream = "yes";
forward-first = "no";
forward-addr = [
"9.9.9.9@853#dns9.quad9.net"
"149.112.112.11@853#dns11.quad9.net"
];
}
];
};
in {
users.users.unbound = {
group = "unbound";
isSystemUser = true;
uid = cids.uids.unbound;
};
users.groups.unbound = {
gid = cids.gids.unbound;
};
security.acme.certs."${domain}" = {
group = "unbound";
};
security.acme.certs."fw.cloonar.com" = {
group = "unbound";
};
services.resolved.enable = false;
services.unbound = {
enable = true;
settings = cfg;
};
systemd.services.unbound-sync = {
enable = true;
path = with pkgs; [ unbound inotify-tools ];
script = ''
#!/usr/bin/env bash
set -euo pipefail
# readFile and readFileUnique as before…
function readFile() {
if [[ "''\$2" == "A" ]] ; then
cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context
do
echo "''\${address},''\${hostname}"
done
else
cat "''\$1" | tail -n +2 | while IFS=, read -r address duid valid_lifetime expire subnet_id pref_lifetime lease_type iaid prefix_len fqdn_fwd fqdn_rev hostname hwaddr state user_context hwtype hwaddr_source
do
echo "''\${address},''\${hostname}"
done
fi
}
function readFileUnique() {
readFile "''\$1" ''\$2 | uniq | while IFS=, read -r address hostname
do
if echo "''\${1}" | grep -Eq '.*\.(cloonar.com|cloonar.multimedia|cloonar.smart)'; then
echo ''\${hostname} ''\$2 ''\${address}
unbound-control local_data ''\${hostname} ''\$2 ''\${address} > /dev/null 2>&1
if [[ "''\$2" == "A" ]] ; then
echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3
do
unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} > /dev/null 2>&1
unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} > /dev/null 2>&1
done
fi
else
if [[ "''\$2" == "A" ]] ; then
echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3
do
if [[ "''\${hostname}" != "" ]]; then
domain=cloonar.com
if [[ "''\${ip2}" == 99 ]]; then
domain=cloonar.multimedia
fi
if [[ "''\${ip2}" == 100 ]]; then
domain=cloonar.smart
fi
if [[ "''\${hostname}" != *. ]]; then
unbound-control local_data ''\${hostname}.''\${domain} ''\$2 ''\${address} > /dev/null 2>&1
else
unbound-control local_data ''\${hostname}''\${domain} ''\$2 ''\${address} > /dev/null 2>&1
fi
fi
unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} > /dev/null 2>&1
unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} > /dev/null 2>&1
done
fi
fi
done
}
function syncLeases() {
# 1) nuke all of our old lease records from unbound
unbound-control list_local_data \
| grep -E 'cloonar\.(com|multimedia|smart)|ip4\.arpa|in-addr\.arpa' \
| while read -r name type data; do
unbound-control local_data_remove "$name" "$type" "$data" \
> /dev/null 2>&1
done
# 2) re-push every current lease
readFileUnique "/var/lib/kea/dhcp4.leases" A
# if you need IPv6:
# readFileUnique "/var/lib/kea/dhcp6.leases" AAAA
}
while true; do
syncLeases
sleep 10
done
'';
wants = [ "network-online.target" "unbound.service" ];
after = [ "network-online.target" "unbound.service" ];
partOf = [ "unbound.service" ];
wantedBy = [ "multi-user.target" ];
};
networking.firewall.allowedUDPPorts = [ 53 5353 ];
}

View file

@ -40,6 +40,7 @@ in {
# ./modules/steam.nix
./modules/fingerprint.nix
./modules/set-nix-channel.nix
./modules/networking.nix
./hardware-configuration.nix
];
@ -249,36 +250,6 @@ in {
};
};
networking.wireguard.interfaces = {
wg0 = {
ips = [ "10.42.98.201/32" ];
# publicKey: YdlRGsjh4hS3OMJI+t6SZ2eGXKbs0wZBXWudHW4NyS8=
privateKeyFile = config.sops.secrets.wg-cloonar-key.path;
peers = [
{
publicKey = "TKQVDmBnf9av46kQxLQSBDhAeaK8r1zh8zpU64zuc1Q=";
allowedIPs = [
"10.42.96.0/20"
# wohnservice-wien
"10.254.240.0/24"
"10.254.235.0/24"
# epicenter.works
"10.14.0.0/16"
"10.25.0.0/16"
"188.34.191.144/32" # web-arm
"91.107.201.241" # mail
];
endpoint = "vpn.cloonar.com:51820"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577
persistentKeepalive = 25;
}
];
postSetup = ''
printf "nameserver 10.42.97.1\nsearch cloonar.com" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0 -x
'';
};
};
# pgp
services.pcscd.enable = true;
programs.gnupg.agent = {

View file

@ -0,0 +1,63 @@
{ config, lib, pkgs, ... }:
{
# Enable systemd-resolved with split DNS for ddev.site
services.resolved = {
enable = true;
dnssec = "false";
extraConfig = ''
DNS=127.0.0.1:5353
Domains=~ddev.site
'';
};
# Integrate NetworkManager with systemd-resolved
networking.networkmanager.dns = "systemd-resolved";
# Local dnsmasq for .ddev.site resolution only (port 5353)
services.dnsmasq = {
enable = true;
settings = {
port = 5353;
listen-address = "127.0.0.1";
bind-interfaces = true;
no-resolv = true;
address = "/.ddev.site/127.0.0.1";
};
};
# WireGuard VPN configuration
networking.wireguard.interfaces = {
wg0 = {
ips = [ "10.42.98.201/32" ];
# publicKey: YdlRGsjh4hS3OMJI+t6SZ2eGXKbs0wZBXWudHW4NyS8=
privateKeyFile = config.sops.secrets.wg-cloonar-key.path;
peers = [
{
publicKey = "TKQVDmBnf9av46kQxLQSBDhAeaK8r1zh8zpU64zuc1Q=";
allowedIPs = [
"10.42.96.0/20"
# wohnservice-wien
"10.254.240.0/24"
"10.254.235.0/24"
# epicenter.works
"10.14.0.0/16"
"10.25.0.0/16"
"188.34.191.144/32" # web-arm
"91.107.201.241" # mail
];
endpoint = "vpn.cloonar.com:51820"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577
persistentKeepalive = 25;
}
];
# Use resolvectl for systemd-resolved integration
# Note: No postDown needed - systemd-resolved automatically handles interface removal
postSetup = ''
${pkgs.systemd}/bin/resolvectl dns wg0 10.42.97.1
${pkgs.systemd}/bin/resolvectl domain wg0 cloonar.com
'';
};
};
}

View file

@ -1,3 +1,6 @@
/home/dominik/projects/infrastructure/actions
/home/dominik/projects/infrastructure/forgejo-mcp
/home/dominik/projects/cloonar/chatgpt.vim
/home/dominik/projects/cloonar/ai.nvim
/home/dominik/projects/cloonar/gitea.nvim

View file

@ -620,6 +620,8 @@ in
git clone gitea@git.cloonar.com:ScanA11y/sa-core.git ${persistHome}/projects/scana11y/sa-core 2>/dev/null
git clone gitea@git.cloonar.com:Cloonar/ai-image-alt.git ${persistHome}/projects/cloonar/ai-image-alt 2>/dev/null
git clone gitea@git.cloonar.com:Cloonar/bookmap.git ${persistHome}/projects/cloonar/bookmap 2>/dev/null
git clone gitea@git.cloonar.com:infrastructure/actions.git ${persistHome}/projects/infrastructure/actions 2>/dev/null
git clone ssh://git@codeberg.org/razormind/forgejo-mcp.git ${persistHome}/projects/infrastructure/forgejo-mcp 2>/dev/null
git clone gitea@git.cloonar.com:dominik.polakovics/typo3-basic.git ${persistHome}/cloonar/typo3-basic 2>/dev/null