Initialize project structure with basic configuration files and main function

This commit is contained in:
Root User 2025-12-03 22:31:03 +01:00
commit e5ccdbfb75
Signed by: root
GPG key ID: 087F0A95E5766D72
10 changed files with 656 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

8
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

14
.idea/discord.xml generated Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
<option name="applicationTheme" value="default" />
<option name="iconsTheme" value="default" />
<option name="button1Title" value="" />
<option name="button1Url" value="" />
<option name="button2Title" value="" />
<option name="button2Url" value="" />
<option name="customApplicationId" value="" />
</component>
</project>

7
Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "the-prg-server-structure"
version = "0.1.0"

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "the-prg-server-structure"
version = "0.1.0"
edition = "2024"
[dependencies]

View file

@ -0,0 +1 @@
#

View file

@ -0,0 +1,388 @@
{
config,
pkgs,
lib,
...
}: {
imports = [./hardware-configuration.nix];
### Lix Package Manager ###
nixpkgs.overlays = [
(final: prev: {
inherit
(prev.lixPackageSets.stable)
nixpkgs-review
nix-eval-jobs
nix-fast-build
colmena
;
})
];
nix.package = pkgs.lixPackageSets.stable.lix;
### Network Configuration ###
networking.hostName = "prg-lan-gateway";
networking.domain = "prg.dtu.dk";
networking.useDHCP = false;
networking.useNetworkd = true;
# Set MAC addresses to match DTU documentation
systemd.network.links."10-wan" = {
matchConfig. OriginalName = "eth*";
matchConfig.Type = "ether";
linkConfig = {
Name = "ens18";
MACAddress = "2a:99:d6:03:dd:92"; # Hardcoded MAC, ensuring that DTU's sysadmin sees it is still the same
WakeOnLan = "off";
};
};
# Discuss removing/changing them?
systemd.network.links."20-lan1" = {
matchConfig.OriginalName = "eth*";
matchConfig.Type = "ether";
linkConfig = {
Name = "ens19";
MACAddress = "0e:27:6a:11:a0:77";
};
};
systemd.network.links."30-lan2" = {
matchConfig.OriginalName = "eth*";
matchConfig.Type = "ether";
linkConfig = {
Name = "ens20";
MACAddress = "42:d7:85:15:e1:ff";
};
};
# WAN Interface (ens18)
systemd.network.networks."10-wan" = {
matchConfig.Name = "ens18";
address = ["130.225.91.242/27"];
gateway = ["130.225.91.225"];
networkConfig = {
IPv6AcceptRA = false;
DHCP = "no";
};
linkConfig = {
RequiredForOnline = "routable";
MTUBytes = "1500";
};
};
# LAN Interface 1 (ens19) - Dual IP
systemd.network.networks."20-lan1" = {
matchConfig.Name = "ens19";
address = [
"10.123.123.1/24"
"192.168.0.1/24"
];
networkConfig = {
IPv6AcceptRA = false;
DHCP = "no";
ConfigureWithoutCarrier = true;
};
};
# LAN Interface 2 (ens20)
systemd.network.networks."30-lan2" = {
matchConfig.Name = "ens20";
address = ["10.255.255.1/24"];
networkConfig = {
IPv6AcceptRA = false;
DHCP = "no";
ConfigureWithoutCarrier = true;
};
};
# DNS Configuration
services.resolved = {
enable = true;
dnssec = "false";
domains = ["prg.dtu.dk"];
fallbackDns = ["1.1.1.1" "8.8.8.8" "130.225.89.2"];
extraConfig = ''
DNSStubListener=no
'';
};
# Kernel parameters for gateway/security
boot.kernel.sysctl = {
# IP forwarding (gateway)
"net.ipv4.ip_forward" = 1;
# Reverse Path Filtering
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1;
# SYN flood
"net.ipv4.tcp_syncookies" = 1;
"net.ipv4.tcp_syn_retries" = 5;
# ICMP redirects / sending redirects
"net.ipv4.conf.all.accept_redirects" = 0;
"net.ipv4.conf.default.accept_redirects" = 0;
"net.ipv4.conf.all.send_redirects" = 0;
"net.ipv4.conf.default.send_redirects" = 0;
"net.ipv4.conf.all.secure_redirects" = 0;
# Source route / routing protections
"net.ipv4.conf.all.accept_source_route" = 0;
"net.ipv4.conf.default.accept_source_route" = 0;
# Log suspicious packets
"net.ipv4.conf.all.log_martians" = 1;
"net.ipv4.conf.default.log_martians" = 1;
# ICMP hygiene
"net.ipv4.icmp_echo_ignore_broadcasts" = 1;
"net.ipv4.icmp_ignore_bogus_error_responses" = 1;
# Performance
"net.ipv4.tcp_window_scaling" = 1;
# Disable IPv6 if desired
"net.ipv6.conf.all.disable_ipv6" = 1;
"net.ipv6.conf.default.disable_ipv6" = 1;
# Additional hardening knobs
"kernel.kptr_restrict" = 1; # hide kernel pointers in /proc
"kernel.dmesg_restrict" = 1; # restrict dmesg
"kernel.yama.ptrace_scope" = 1; # restrict ptrace
"fs.protected_hardlinks" = 1;
"fs.protected_symlinks" = 1;
};
# NAT Configuration
networking.nat = {
enable = true;
externalInterface = "ens18";
internalInterfaces = ["ens19" "ens20"];
forwardPorts = []; # Empty - no port forwarding
};
# Firewall Configuration
networking.firewall = {
enable = true;
# Trusted LAN interfaces (all ports open)
trustedInterfaces = ["ens19" "ens20"];
# Interface-specific rules (keep permitted ports on LAN)
interfaces = {
ens19.allowedTCPPorts = [22 53];
ens19.allowedUDPPorts = [53 67 123];
ens20.allowedTCPPorts = [22 53];
ens20.allowedUDPPorts = [53 67 123];
};
# Tightened iptables rules using conntrack, drop INVALID, rate-limit ICMP and logging.
extraCommands = ''
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Drop invalid packets early
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Established/related
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Rate-limit ICMP (allow limited pings)
iptables -A INPUT -p icmp -m conntrack --ctstate NEW -m limit --limit 1/second --limit-burst 5 -j ACCEPT
# Block new connections from WAN interface
iptables -A INPUT -i ens18 -m conntrack --ctstate NEW -j DROP
# Log dropped packets (rate-limited)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-dropped: " --log-level 7
'';
extraStopCommands = ''
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
'';
};
# Hosts file
networking.extraHosts = ''
130.225.91.242 prg-lan-gateway.prg.dtu.dk prg-lan-gateway
'';
# Time synchronization
time.timeZone = "Europe/Copenhagen";
services.chrony = {
enable = true;
servers = ["time.cloudflare.com"];
extraConfig = ''
makestep 1.0 3
rtcsync
'';
};
# Locale settings
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "da_DK.UTF-8";
LC_IDENTIFICATION = "da_DK.UTF-8";
LC_MEASUREMENT = "da_DK.UTF-8";
LC_MONETARY = "da_DK.UTF-8";
LC_NAME = "da_DK.UTF-8";
LC_NUMERIC = "da_DK. UTF-8";
LC_PAPER = "da_DK.UTF-8";
LC_TELEPHONE = "da_DK.UTF-8";
LC_TIME = "en_DK.UTF-8";
};
# Console keymap
# Change it back to Danish?
console.keyMap = "us";
# User configuration -
users.users.admin = {
isNormalUser = true;
description = "Gateway Administrator";
extraGroups = ["wheel" "networkmanager" "systemd-journal"];
openssh.authorizedKeys.keys = [
# Christine's Hardware Key - Copy and change to the desired hardware keys
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3pjIXlpg7H9h1RrmdxbIRnDIdQvf/EZKI9PG2/rY7D openpgp:0x8BCD4992"
];
};
# Passwordless sudo for wheel group
security.sudo.wheelNeedsPassword = false;
# Hardware U2F support - Passwordless sudo with hardware key
security.pam.u2f = {
enable = true;
settings = {
authfile = "/etc/u2f_keys";
cue = true;
pinverification = 0; # No PIN verification
userpresence = 1; # Require user presence (touch)
};
};
# SSH Agent authentication
security.pam.enableSSHAgentAuth = true;
# System packages
environment.systemPackages = with pkgs; [
# Network tools
wget
curl
dig
tcpdump
ethtool
iptables
nftables
iproute2
bridge-utils
netcat-gnu
traceroute
mtr
# Monitoring
btop
htop
iotop
bandwhich
# Editors
micro
vim
helix
# System info
fastfetch
lshw
pciutils
usbutils
];
# OpenSSH
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
X11Forwarding = false;
# Additional hardening
MaxAuthTries = 3;
LoginGraceTime = "20s";
};
extraConfig = ''
AllowUsers admin
'';
openFirewall = false; # Manually configured in firewall section
};
# Tailscale VPN - We need to discuss about this long term
services.tailscale = {
enable = true;
useRoutingFeatures = "server";
};
# Automatic upgrades
system.autoUpgrade = {
enable = true; # Set to true for automatic updates
dates = "daily";
allowReboot = false;
};
# Nix garbage collection
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# Nix settings
nix.settings = {
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
trusted-users = ["root" "@wheel"];
};
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Boot configuration TO BE CHANGED ACCORDING TO INSTALL VERSION
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
timeout = 3;
};
# Kernel optimization
boot.kernelParams = [
"quiet"
"splash"
];
# Enable zram swap
zramSwap = {
enable = true;
memoryPercent = 50;
};
# Protect /tmp as a tmpfs with nosuid/nodev/noexec
fileSystems."/tmp" = {
device = "tmpfs";
fsType = "tmpfs";
options = ["mode=1777" "nosuid" "nodev" "noexec"];
};
# System state version
system.stateVersion = "XX.XX";
}

View file

@ -0,0 +1,105 @@
# Headless server configuration with Lix
{
config,
pkgs,
lib,
...
}: {
imports = [
./hardware-configuration.nix
];
## Use Lix, instead of Nix NixOS default ##
nixpkgs.overlays = [
(final: prev: {
inherit
(prev.lixPackageSets.stable)
nixpkgs-review
nix-eval-jobs
nix-fast-build
colmena
;
})
];
nix.package = pkgs.lixPackageSets.stable.lix;
### TO BE CHANGED ACCORDING TO INSTALL ###
# Networking
networking.hostName = "server";
networking.networkmanager.enable = true;
# Time zone
time.timeZone = "Europe/Copenhagen";
# Locale
i18n.defaultLocale = "en_GB.UTF-8";
# Also install Danish and Norwegian locales
i18n.extraLocales = ["da_DK.UTF-8" "nb_NO.UTF-8"];
# User account with hardware key support
users.users.admin = {
isNormalUser = true;
extraGroups = ["wheel" "networkmanager"];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3pjIXlpg7H9h1RrmdxbIRnDIdQvf/EZKI9PG2/rY7D openpgp:0x8BCD4992"
];
};
# Hardware Key Passwordless Sudo
security.pam.u2f.enable = true;
security.pam.u2f.settings = {
authfile = "/etc/u2f_keys";
authpending_file = "";
pinverification = 0;
userpresence = 1;
};
# SSH Passwordless Sudo
security.pam.enableSSHAgentAuth = true;
security.pam.sshAgentAuth = {
enable = true;
authorizedKeysFiles = ["/etc/ssh/authorized_keys.d/admin"];
};
# Essential packages
environment.systemPackages = with pkgs; [
wget
curl
git
btop
htop
micro
vim
helix
fastfetch
];
# OpenSSH
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
# Tailscale - Think about how we manage this long term
services.tailscale.enable = true;
# Garbage collection
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# Firewall
networking.firewall.allowedTCPPorts = [22];
nixpkgs.config.allowUnfree = true;
### TO BE CHANGED ACCORDING TO INSTALL VERSION ###
system.stateVersion = "XX.XX";
}

View file

@ -0,0 +1,123 @@
# Old Server Notes
---
# Gateway WAN Configuration - Essential Info
## Network Details
```
WAN IP: 130.225.91.242/27
Netmask: 255.255.255.224
Gateway: 130.225.91.225
Gateway MAC: f0:7f:06:98:4a:64
Network: 130.225.91.224/27
Broadcast: 130.225.91.255
Interface: ens18
MTU: 1500
Domain: prg.dtu.dk
Hostname: prg-lan-gateway
FQDN: prg-lan-gateway.prg.dtu.dk
```
## Upstream Path
```
Gateway (130.225.91.225) → Cisco e11_0-1.bg106.internet.i3.cisco.net.local
Next Hop (192.38.93.34) → DTU edge router et2_12.90.sb-1g303-1
```
## Interface Configuration
```
Interface: ens18
Type: Static IPv4
Address: 130.225.91.242/27
Gateway: 130.225.91.225
No VLANs, No PPPoE, No MAC cloning
```
## Proxmox VM Configuration
```
VM ID: 100
Node: ve0
Memory: 2GB
CPU: 2 cores (1 socket)
Disk: 10GB (local-lvm)
NIC Model: VirtIO
Network Devices:
net0 (ens18): virtio=2A:99:D6:03:DD:92,bridge=vmbr1 ← WAN
net1 (ens19): virtio=0E:27:6A:11:A0:77,bridge=vmbr0 ← LAN
net2 (ens20): virtio=42:D7:85:15:E1:FF,bridge=vmbr2 ← LAN
```
## DNS Servers
```
Primary: 1.1.1.1 (Cloudflare)
Secondary: 8.8.8.8 (Google)
Tertiary: 130.225.89.2 (DTU)
Domain: prg.dtu.dk
Search: prg.dtu.dk
```
## NTP Servers
```
time.cloudflare.com
```
## Firewall Rules
### NAT (Outbound)
```
Chain: POSTROUTING
Action: Masquerade all traffic on interface ens18
```
### Filter (Inbound)
```
Accept: Loopback (lo)
Accept: Established/Related connections
Drop: All other traffic from ens18 (WAN)
Default: Accept (for other interfaces)
```
### Port Forwarding
```
None configured
```
## System Requirements
```
IP Forwarding: Enabled (net.ipv4.ip_forward=1)
Reverse Path Filtering: Enabled (net.ipv4.conf.all.rp_filter=1)
SYN Cookies: Enabled (net.ipv4.tcp_syncookies=1)
Accept ICMP Redirects: Disabled (net.ipv4.conf.all.accept_redirects=0)
Send ICMP Redirects: Disabled (net.ipv4.conf.all.send_redirects=0)
Accept Source Route: Disabled (net.ipv4.conf.all.accept_source_route=0)
Log Martian Packets: Enabled (net.ipv4.conf.all.log_martians=1)
Ignore Broadcast Pings: Enabled (net.ipv4.icmp_echo_ignore_broadcasts=1)
Ignore Bogus ICMP Errors: Enabled (net.ipv4.icmp_ignore_bogus_error_responses=1)
```
## Hosts File
```
127.0.0.1 localhost
130.225.91.242 prg-lan-gateway.prg.dtu.dk prg-lan-gateway
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
```
## LAN Interfaces
```
ens19: 10.123.123.1/24, 192.168.0.1/24 (dual IP)
ens20: 10.255.255.1/24
```
## Critical Notes
```
Platform: Proxmox VM (node ve0, VM ID 100)
WAN MAC: 2A:99:D6:03:DD:92 (must preserve for rebuild maybe, due to DTU being very thorough maybe)
WAN Bridge: vmbr1 (not vmbr0)
IPv6: Not configured
```

3
src/main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
println!("Hello, this will be changed later!");
}