atlas svo

This commit is contained in:
v 2026-09-14 03:04:38 +03:00
commit a54778f061
22 changed files with 2422 additions and 0 deletions

18
.gitignore vendored Normal file
View file

@ -0,0 +1,18 @@
*.kdbx
*.key
*.priv
*.env
.terraform/
*.tfstate*
*.tfstate.backup
*.tfvars
.terraform.lock.hcl
crash.log
*.retry
talos/clusterconfig/
talos/kubeconfig
# Repomix
repomix-output.xml
talos/secrets.yaml
talos/clusterconfig/

13
ansible/ansible.cfg Normal file
View file

@ -0,0 +1,13 @@
[defaults]
inventory = inventory.yml
remote_user = vyos
host_key_checking = False
retry_files_enabled = False
interpreter_python = auto_silent
deprecation_warnings = False
[privilege_escalation]
become = False
[network_cli]
ssh_type = paramiko

View file

@ -0,0 +1,63 @@
---
- name: Update APT cache and install base utilities
ansible.builtin.apt:
name:
- curl
- wget
- ca-certificates
- jq
state: present
update_cache: true
- name: Provision Zot Registry
when: inventory_hostname == 'registry0' or ansible_host == '10.0.10.15'
block:
- name: Download Zot binary
ansible.builtin.get_url:
url: https://github.com/project-zot/zot/releases/download/v2.1.1/zot-linux-amd64
dest: /usr/local/bin/zot
mode: '0755'
- name: Create Zot configuration directory
ansible.builtin.file:
path: /etc/zot
state: directory
mode: '0755'
- name: Generate Zot configuration
ansible.builtin.copy:
dest: /etc/zot/config.json
content: |
{
"distSpecVersion": "1.1.0-dev",
"storage": {
"rootDirectory": "/mnt/registry",
"gc": true
},
"http": {
"address": "0.0.0.0",
"port": "5000"
}
}
- name: Create Zot systemd service
ansible.builtin.copy:
dest: /etc/systemd/system/zot.service
content: |
[Unit]
Description=Zot OCI Registry
After=network.target
[Service]
ExecStart=/usr/local/bin/zot serve /etc/zot/config.json
Restart=always
[Install]
WantedBy=multi-user.target
- name: Enable and start Zot service
ansible.builtin.systemd:
name: zot
enabled: true
state: started
daemon_reload: true

21
ansible/inventory.yml Normal file
View file

@ -0,0 +1,21 @@
all:
children:
routers:
hosts:
vyos:
ansible_host: 192.168.1.2
ansible_user: vyos
tier0_lxc:
hosts:
dns0:
ansible_host: 10.0.10.11
vault0:
ansible_host: 10.0.10.12
git0:
ansible_host: 10.0.10.13
storage0:
ansible_host: 10.0.10.14
registry0:
ansible_host: 10.0.10.15
vars:
ansible_user: root

View file

@ -0,0 +1,59 @@
---
- name: Configure Proxmox Host Day-0 Integration
hosts: pve0
gather_facts: false
tasks:
- name: Ensure host directories exist with unprivileged LXC permissions
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "100000"
group: "100000"
mode: "0755"
loop:
- /terra/media
- /terra/torrents
- /terra/vault
- /terra/registry
- name: Check existing mount points for LXC 104
ansible.builtin.command: grep -q "^{{ item.id }}: {{ item.src }},mp={{ item.dest }}" /etc/pve/lxc/104.conf
register: check_104
changed_when: false
failed_when: false
loop:
- { id: 'mp0', src: '/terra/media', dest: '/mnt/media' }
- { id: 'mp1', src: '/terra/torrents', dest: '/mnt/torrents' }
- { id: 'mp2', src: '/terra/vault', dest: '/mnt/backups' }
- name: Apply mount points for LXC 104
ansible.builtin.command: pct set 104 -{{ item.item.id }} {{ item.item.src }},mp={{ item.item.dest }}
when: item.rc != 0
register: apply_104
loop: "{{ check_104.results }}"
loop_control:
label: "{{ item.item.id }}"
- name: Reboot LXC 104 to apply pending mount points
ansible.builtin.command: pct reboot 104
when: apply_104.changed
- name: Check existing mount points for LXC 105
ansible.builtin.command: grep -q "^{{ item.id }}: {{ item.src }},mp={{ item.dest }}" /etc/pve/lxc/105.conf
register: check_105
changed_when: false
failed_when: false
loop:
- { id: 'mp0', src: '/terra/registry', dest: '/mnt/registry' }
- name: Apply mount points for LXC 105
ansible.builtin.command: pct set 105 -{{ item.item.id }} {{ item.item.src }},mp={{ item.item.dest }}
when: item.rc != 0
register: apply_105
loop: "{{ check_105.results }}"
loop_control:
label: "{{ item.item.id }}"
- name: Reboot LXC 105 to apply pending mount points
ansible.builtin.command: pct reboot 105
when: apply_105.changed

View file

@ -0,0 +1,24 @@
---
- name: Configure VyOS Network Day-0
hosts: vyos_router
connection: network_cli
gather_facts: false
vars:
ansible_network_os: vyos.vyos.vyos
tasks:
- name: Apply base network configuration
vyos.vyos.vyos_config:
lines:
- set interfaces ethernet eth0 address '192.168.1.2/24'
- set interfaces ethernet eth0 description 'WAN_TRUNK'
- set interfaces ethernet eth1 address '10.0.10.1/24'
- set interfaces ethernet eth1 description 'TIER0'
- set interfaces ethernet eth2 address '10.0.20.1/24'
- set interfaces ethernet eth2 description 'K8S'
- set interfaces ethernet eth3 address '10.0.30.1/24'
- set interfaces ethernet eth3 description 'LAN_CLIENTS'
- set protocols static route 0.0.0.0/0 next-hop 192.168.1.1
- set nat source rule 100 outbound-interface name 'eth0'
- set nat source rule 100 source address '10.0.0.0/16'
- set nat source rule 100 translation address 'masquerade'
save: true

View file

@ -0,0 +1,135 @@
---
- name: Deploy Zot OCI Registry
hosts: registry0
gather_facts: false
tasks:
- name: Create zot group
ansible.builtin.group:
name: zot
state: present
- name: Create zot user
ansible.builtin.user:
name: zot
group: zot
system: true
create_home: false
shell: /usr/sbin/nologin
state: present
- name: Ensure Zot configuration directory exists
ansible.builtin.file:
path: /etc/zot
state: directory
owner: zot
group: zot
mode: "0755"
- name: Ensure Zot storage directory exists with correct ownership
ansible.builtin.file:
path: /mnt/registry
state: directory
owner: zot
group: zot
mode: "0755"
- name: Download Zot binary
ansible.builtin.get_url:
url: https://github.com/project-zot/zot/releases/download/v2.1.1/zot-linux-amd64
dest: /usr/local/bin/zot
owner: root
group: root
mode: "0755"
notify: Restart Zot
- name: Generate Zot configuration
ansible.builtin.copy:
dest: /etc/zot/config.json
owner: zot
group: zot
mode: "0644"
content: |
{
"distSpecVersion": "1.1.0-dev",
"storage": {
"rootDirectory": "/mnt/registry",
"gc": true
},
"http": {
"address": "0.0.0.0",
"port": "5000"
},
"extensions": {
"sync": {
"enable": true,
"registries": [
{
"urls": ["https://registry-1.docker.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{
"prefix": "**",
"destination": "/docker.io"
}
]
},
{
"urls": ["https://ghcr.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{
"prefix": "**",
"destination": "/ghcr.io"
}
]
},
{
"urls": ["https://registry.k8s.io"],
"onDemand": true,
"tlsVerify": true,
"content": [
{
"prefix": "**",
"destination": "/k8s.io"
}
]
}
]
}
}
}
notify: Restart Zot
- name: Create Zot systemd service
ansible.builtin.copy:
dest: /etc/systemd/system/zot.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Zot OCI Registry
After=network.target
[Service]
User=zot
Group=zot
ExecStart=/usr/local/bin/zot serve /etc/zot/config.json
Restart=always
[Install]
WantedBy=multi-user.target
notify: Restart Zot
- name: Enable and start Zot service
ansible.builtin.systemd:
name: zot
enabled: true
state: started
daemon_reload: true
handlers:
- name: Restart Zot
ansible.builtin.systemd:
name: zot
state: restarted

View file

@ -0,0 +1,72 @@
---
- name: Deploy Technitium DNS on Debian 12
hosts: dns0
gather_facts: false
tasks:
- name: Update APT cache and install dependencies
ansible.builtin.apt:
name:
- curl
- tar
state: present
update_cache: true
- name: Download dotnet-install script
ansible.builtin.get_url:
url: https://dot.net/v1/dotnet-install.sh
dest: /tmp/dotnet-install.sh
mode: "0755"
- name: Install .NET 8 Runtime
ansible.builtin.command:
cmd: /tmp/dotnet-install.sh --runtime aspnetcore --channel 8.0 --install-dir /usr/share/dotnet
creates: /usr/share/dotnet/dotnet
- name: Create dotnet symlink
ansible.builtin.file:
src: /usr/share/dotnet/dotnet
dest: /usr/bin/dotnet
state: link
- name: Ensure Technitium DNS directory exists
ansible.builtin.file:
path: /opt/technitium/dns
state: directory
mode: "0755"
- name: Download and extract Technitium DNS
ansible.builtin.unarchive:
src: https://download.technitium.com/dns/DnsServerPortable.tar.gz
dest: /opt/technitium/dns
remote_src: true
notify: Restart Technitium
- name: Create systemd service
ansible.builtin.copy:
dest: /etc/systemd/system/technitium-dns.service
mode: "0644"
content: |
[Unit]
Description=Technitium DNS Server
After=network.target
[Service]
ExecStart=/usr/bin/dotnet /opt/technitium/dns/DnsServerApp.dll
WorkingDirectory=/opt/technitium/dns
Restart=always
SyslogIdentifier=technitium-dns
[Install]
WantedBy=multi-user.target
notify: Restart Technitium
- name: Enable and start Technitium DNS service
ansible.builtin.systemd:
name: technitium-dns
enabled: true
state: started
daemon_reload: true
handlers:
- name: Restart Technitium
ansible.builtin.systemd:
name: technitium-dns
state: restarted

View file

@ -0,0 +1,112 @@
---
- name: Deploy OpenBao Vault
hosts: vault0
gather_facts: false
tasks:
- name: Update APT cache and install dependencies
ansible.builtin.apt:
name:
- curl
- gpg
- apt-transport-https
- unzip
state: present
update_cache: true
- name: Create bao group
ansible.builtin.group:
name: bao
state: present
- name: Create bao user
ansible.builtin.user:
name: bao
group: bao
system: true
create_home: false
shell: /usr/sbin/nologin
state: present
- name: Ensure bao configuration directory exists
ansible.builtin.file:
path: /etc/bao
state: directory
owner: bao
group: bao
mode: "0755"
- name: Ensure bao data directory exists
ansible.builtin.file:
path: /var/lib/bao/data
state: directory
owner: bao
group: bao
mode: "0750"
- name: Download and extract OpenBao binary
ansible.builtin.unarchive:
src: https://github.com/openbao/openbao/releases/download/v2.0.1/bao_2.0.1_linux_amd64.zip
dest: /usr/local/bin
remote_src: true
creates: /usr/local/bin/bao
owner: root
group: root
mode: "0755"
notify: Restart OpenBao
- name: Generate OpenBao configuration
ansible.builtin.copy:
dest: /etc/bao/vault.hcl
owner: bao
group: bao
mode: "0644"
content: |
disable_mlock = true
ui = true
storage "file" {
path = "/var/lib/bao/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}
notify: Restart OpenBao
- name: Create OpenBao systemd service
ansible.builtin.copy:
dest: /etc/systemd/system/openbao.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=OpenBao Secrets Management
After=network.target
[Service]
User=bao
Group=bao
ExecStart=/usr/local/bin/bao server -config=/etc/bao/vault.hcl
Restart=on-failure
[Install]
WantedBy=multi-user.target
notify: Restart OpenBao
- name: Enable and start OpenBao service
ansible.builtin.systemd:
name: openbao
enabled: true
state: started
daemon_reload: true
- name: Wait for OpenBao port 8200 to become available
ansible.builtin.wait_for:
port: 8200
host: 127.0.0.1
state: started
timeout: 30
handlers:
- name: Restart OpenBao
ansible.builtin.systemd:
name: openbao
state: restarted

View file

@ -0,0 +1,115 @@
---
- name: Deploy Forgejo GitOps Server
hosts: git0
gather_facts: false
tasks:
- name: Update APT cache and install dependencies
ansible.builtin.apt:
name:
- git
- curl
state: present
update_cache: true
- name: Create git group
ansible.builtin.group:
name: git
state: present
- name: Create git user
ansible.builtin.user:
name: git
group: git
system: true
home: /var/lib/forgejo
shell: /bin/bash
state: present
- name: Ensure Forgejo directories exist
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: git
group: git
mode: "0750"
loop:
- /etc/forgejo
- /var/lib/forgejo
- /var/lib/forgejo/data
- /var/lib/forgejo/custom
- /var/lib/forgejo/log
- name: Download Forgejo binary
ansible.builtin.get_url:
url: https://codeberg.org/forgejo/forgejo/releases/download/v7.0.4/forgejo-7.0.4-linux-amd64
dest: /usr/local/bin/forgejo
owner: root
group: root
mode: "0755"
notify: Restart Forgejo
- name: Generate Forgejo configuration
ansible.builtin.copy:
dest: /etc/forgejo/app.ini
owner: git
group: git
mode: "0640"
force: false
content: |
APP_NAME = Sovereign C2 GitOps
RUN_USER = git
WORK_PATH = /var/lib/forgejo
[database]
DB_TYPE = sqlite3
PATH = /var/lib/forgejo/data/forgejo.db
[server]
HTTP_PORT = 3000
SSH_PORT = 2222
DISABLE_SSH = false
START_SSH_SERVER = true
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true
notify: Restart Forgejo
- name: Create Forgejo systemd service
ansible.builtin.copy:
dest: /etc/systemd/system/forgejo.service
owner: root
group: root
mode: "0644"
content: |
[Unit]
Description=Forgejo Git Service
After=network.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/forgejo
ExecStart=/usr/local/bin/forgejo web -c /etc/forgejo/app.ini
Restart=always
Environment=USER=git HOME=/var/lib/forgejo GITEA_WORK_DIR=/var/lib/forgejo
[Install]
WantedBy=multi-user.target
notify: Restart Forgejo
- name: Enable and start Forgejo service
ansible.builtin.systemd:
name: forgejo
enabled: true
state: started
daemon_reload: true
- name: Wait for Forgejo port 3000 to become available
ansible.builtin.wait_for:
port: 3000
host: 127.0.0.1
state: started
timeout: 30
handlers:
- name: Restart Forgejo
ansible.builtin.systemd:
name: forgejo
state: restarted

View file

@ -0,0 +1,110 @@
---
- name: Deploy NAS Storage with NFS-Ganesha
hosts: storage0
gather_facts: false
tasks:
- name: Update APT cache and install NFS-Ganesha
ansible.builtin.apt:
name:
- nfs-ganesha
- nfs-ganesha-vfs
state: present
update_cache: true
- name: Ensure export directories exist
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop:
- /mnt/media
- /mnt/torrents
- /mnt/backups
- /mnt/models
- name: Generate NFS-Ganesha configuration
ansible.builtin.copy:
dest: /etc/ganesha/ganesha.conf
mode: "0644"
content: |
EXPORT {
Export_Id = 1;
Path = /mnt/media;
Pseudo = /media;
Access_Type = None;
Squash = All_Squash;
Anonymous_uid = 0;
Anonymous_gid = 0;
SecType = sys;
FSAL {
Name = VFS;
}
CLIENT {
Clients = 10.0.10.0/24, 10.0.20.0/24;
Access_Type = RW;
}
}
EXPORT {
Export_Id = 2;
Path = /mnt/torrents;
Pseudo = /torrents;
Access_Type = None;
Squash = All_Squash;
Anonymous_uid = 0;
Anonymous_gid = 0;
SecType = sys;
FSAL {
Name = VFS;
}
CLIENT {
Clients = 10.0.10.0/24, 10.0.20.0/24;
Access_Type = RW;
}
}
EXPORT {
Export_Id = 3;
Path = /mnt/backups;
Pseudo = /backups;
Access_Type = None;
Squash = All_Squash;
Anonymous_uid = 0;
Anonymous_gid = 0;
SecType = sys;
FSAL {
Name = VFS;
}
CLIENT {
Clients = 10.0.10.0/24, 10.0.20.0/24;
Access_Type = RW;
}
}
EXPORT {
Export_Id = 4;
Path = /mnt/models;
Pseudo = /models;
Access_Type = None;
Squash = All_Squash;
Anonymous_uid = 0;
Anonymous_gid = 0;
SecType = sys;
FSAL {
Name = VFS;
}
CLIENT {
Clients = 10.0.10.0/24, 10.0.20.0/24;
Access_Type = RW;
}
}
notify: Restart NFS-Ganesha
- name: Enable and start NFS-Ganesha service
ansible.builtin.systemd:
name: nfs-ganesha
enabled: true
state: started
handlers:
- name: Restart NFS-Ganesha
ansible.builtin.systemd:
name: nfs-ganesha
state: restarted

23
deploy.sh Executable file
View file

@ -0,0 +1,23 @@
#!/bin/bash
set -e
ssh-add -l > /dev/null 2>&1 || ssh-add ~/.ssh/id_ed25519
if [ -z "$DEV_KP_PASS" ]; then
read -s -p "Enter KeePassXC Master Password: " KP_PASS
echo ""
else
KP_PASS="$DEV_KP_PASS"
fi
export TF_VAR_pve_username="root@pam"
export TF_VAR_pve_password=$(echo "$KP_PASS" | keepassxc-cli show -q -a Password ~/Projects/atlas-secrets.kdbx "ProxmoxRoot")
export TF_VAR_state_passphrase=$(echo "$KP_PASS" | keepassxc-cli show -q -a Password ~/Projects/atlas-secrets.kdbx "TofuState")
cd ~/Projects/atlas/tofu
tofu apply -auto-approve
unset TF_VAR_pve_username
unset TF_VAR_pve_password
unset TF_VAR_state_passphrase
unset KP_PASS

650
docs/hardware_snapshot.json Normal file
View file

@ -0,0 +1,650 @@
{
"cpu": {
"lscpu": [
{
"field": "Architecture:",
"data": "x86_64"
},
{
"field": "CPU op-mode(s):",
"data": "32-bit, 64-bit"
},
{
"field": "Address sizes:",
"data": "43 bits physical, 48 bits virtual"
},
{
"field": "Byte Order:",
"data": "Little Endian"
},
{
"field": "CPU(s):",
"data": "8"
},
{
"field": "On-line CPU(s) list:",
"data": "0-7"
},
{
"field": "Vendor ID:",
"data": "AuthenticAMD"
},
{
"field": "Model name:",
"data": "AMD Ryzen 5 3350GE with Radeon Vega Graphics"
},
{
"field": "CPU family:",
"data": "23"
},
{
"field": "Model:",
"data": "24"
},
{
"field": "Thread(s) per core:",
"data": "2"
},
{
"field": "Core(s) per socket:",
"data": "4"
},
{
"field": "Socket(s):",
"data": "1"
},
{
"field": "Stepping:",
"data": "1"
},
{
"field": "Frequency boost:",
"data": "enabled"
},
{
"field": "CPU(s) scaling MHz:",
"data": "94%"
},
{
"field": "CPU max MHz:",
"data": "3300.0000"
},
{
"field": "CPU min MHz:",
"data": "1400.0000"
},
{
"field": "BogoMIPS:",
"data": "6600.28"
},
{
"field": "Flags:",
"data": "fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb hw_pstate ssbd ibpb vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif overflow_recov succor smca sev sev_es"
},
{
"field": "Virtualization:",
"data": "AMD-V"
},
{
"field": "L1d cache:",
"data": "128 KiB (4 instances)"
},
{
"field": "L1i cache:",
"data": "256 KiB (4 instances)"
},
{
"field": "L2 cache:",
"data": "2 MiB (4 instances)"
},
{
"field": "L3 cache:",
"data": "4 MiB (1 instance)"
},
{
"field": "NUMA node(s):",
"data": "1"
},
{
"field": "NUMA node0 CPU(s):",
"data": "0-7"
},
{
"field": "Vulnerability Gather data sampling:",
"data": "Not affected"
},
{
"field": "Vulnerability Ghostwrite:",
"data": "Not affected"
},
{
"field": "Vulnerability Indirect target selection:",
"data": "Not affected"
},
{
"field": "Vulnerability Itlb multihit:",
"data": "Not affected"
},
{
"field": "Vulnerability L1tf:",
"data": "Not affected"
},
{
"field": "Vulnerability Mds:",
"data": "Not affected"
},
{
"field": "Vulnerability Meltdown:",
"data": "Not affected"
},
{
"field": "Vulnerability Mmio stale data:",
"data": "Not affected"
},
{
"field": "Vulnerability Old microcode:",
"data": "Not affected"
},
{
"field": "Vulnerability Reg file data sampling:",
"data": "Not affected"
},
{
"field": "Vulnerability Retbleed:",
"data": "Mitigation; untrained return thunk; SMT vulnerable"
},
{
"field": "Vulnerability Spec rstack overflow:",
"data": "Mitigation; Safe RET"
},
{
"field": "Vulnerability Spec store bypass:",
"data": "Mitigation; Speculative Store Bypass disabled via prctl"
},
{
"field": "Vulnerability Spectre v1:",
"data": "Mitigation; usercopy/swapgs barriers and __user pointer sanitization"
},
{
"field": "Vulnerability Spectre v2:",
"data": "Mitigation; Retpolines; IBPB conditional; STIBP disabled; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected"
},
{
"field": "Vulnerability Srbds:",
"data": "Not affected"
},
{
"field": "Vulnerability Tsa:",
"data": "Not affected"
},
{
"field": "Vulnerability Tsx async abort:",
"data": "Not affected"
},
{
"field": "Vulnerability Vmscape:",
"data": "Mitigation; IBPB before exit to userspace"
}
]
},
"ram_bytes": 39863885824,
"disks": {
"blockdevices": [
{
"name": "loop0",
"size": "8G",
"fstype": "ext4",
"uuid": "1cda1590-5d27-4cab-858f-2666c19f45bd",
"model": null,
"serial": null,
"path": "/dev/loop0",
"rota": false,
"type": "loop"
},
{
"name": "loop1",
"size": "8G",
"fstype": "ext4",
"uuid": "b2e798db-809f-48d5-a97a-58a16d19de8c",
"model": null,
"serial": null,
"path": "/dev/loop1",
"rota": false,
"type": "loop"
},
{
"name": "loop2",
"size": "4G",
"fstype": "ext4",
"uuid": "a0dad42d-f88a-4983-88f9-6e8f9b8e5c74",
"model": null,
"serial": null,
"path": "/dev/loop2",
"rota": false,
"type": "loop"
},
{
"name": "loop3",
"size": "4G",
"fstype": "ext4",
"uuid": "5e9edd0b-1e43-4f26-96aa-aec3bd3b6d98",
"model": null,
"serial": null,
"path": "/dev/loop3",
"rota": false,
"type": "loop"
},
{
"name": "loop4",
"size": "2G",
"fstype": "ext4",
"uuid": "37dd032b-8381-4eec-b69f-a9748bc33777",
"model": null,
"serial": null,
"path": "/dev/loop4",
"rota": false,
"type": "loop"
},
{
"name": "sda",
"size": "1.8T",
"fstype": null,
"uuid": null,
"model": "TOSHIBA HDWA120",
"serial": "27MWR2SAS",
"path": "/dev/sda",
"rota": true,
"type": "disk",
"children": [
{
"name": "sda1",
"size": "1.8T",
"fstype": "zfs_member",
"uuid": "7540128891022881476",
"model": null,
"serial": null,
"path": "/dev/sda1",
"rota": true,
"type": "part"
},
{
"name": "sda9",
"size": "8M",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/sda9",
"rota": true,
"type": "part"
}
]
},
{
"name": "sdb",
"size": "953.9G",
"fstype": null,
"uuid": null,
"model": "DEXP SSD C100 1Tb",
"serial": "HGB446242911",
"path": "/dev/sdb",
"rota": false,
"type": "disk",
"children": [
{
"name": "sdb1",
"size": "953.9G",
"fstype": "zfs_member",
"uuid": "1766286880976563783",
"model": null,
"serial": null,
"path": "/dev/sdb1",
"rota": false,
"type": "part"
},
{
"name": "sdb9",
"size": "8M",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/sdb9",
"rota": false,
"type": "part"
}
]
},
{
"name": "sdc",
"size": "476.9G",
"fstype": null,
"uuid": null,
"model": "Patriot P210 512GB",
"serial": "P210EDCB22092102722",
"path": "/dev/sdc",
"rota": false,
"type": "disk",
"children": [
{
"name": "sdc1",
"size": "976M",
"fstype": "vfat",
"uuid": "9DAA-752C",
"model": null,
"serial": null,
"path": "/dev/sdc1",
"rota": false,
"type": "part"
},
{
"name": "sdc2",
"size": "977M",
"fstype": "linux_raid_member",
"uuid": "e895a645-731a-c3f0-4f42-5bf822ece61e",
"model": null,
"serial": null,
"path": "/dev/sdc2",
"rota": false,
"type": "part",
"children": [
{
"name": "md0",
"size": "976M",
"fstype": "ext4",
"uuid": "4326ce97-013c-48e0-9b89-08722f8b13d3",
"model": null,
"serial": null,
"path": "/dev/md0",
"rota": false,
"type": "raid1"
}
]
},
{
"name": "sdc3",
"size": "445.3G",
"fstype": "linux_raid_member",
"uuid": "b383b1c8-144c-322c-58ab-66a03745768a",
"model": null,
"serial": null,
"path": "/dev/sdc3",
"rota": false,
"type": "part",
"children": [
{
"name": "md1",
"size": "445.1G",
"fstype": "crypto_LUKS",
"uuid": "d5ac7445-7491-4299-9cc5-22c316245793",
"model": null,
"serial": null,
"path": "/dev/md1",
"rota": false,
"type": "raid1",
"children": [
{
"name": "md1_crypt",
"size": "445.1G",
"fstype": "ext4",
"uuid": "aa4d959e-ebdb-4bd7-b8e9-5631a250da60",
"model": null,
"serial": null,
"path": "/dev/mapper/md1_crypt",
"rota": false,
"type": "crypt"
}
]
}
]
}
]
},
{
"name": "sdd",
"size": "953.9G",
"fstype": null,
"uuid": null,
"model": "DEXP SSD C100 1Tb",
"serial": "HGB443029148",
"path": "/dev/sdd",
"rota": false,
"type": "disk",
"children": [
{
"name": "sdd1",
"size": "953.9G",
"fstype": "zfs_member",
"uuid": "1766286880976563783",
"model": null,
"serial": null,
"path": "/dev/sdd1",
"rota": false,
"type": "part"
},
{
"name": "sdd9",
"size": "8M",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/sdd9",
"rota": false,
"type": "part"
}
]
},
{
"name": "sde",
"size": "447.1G",
"fstype": null,
"uuid": null,
"model": "HS-SSD-C100 480G",
"serial": "30103741962",
"path": "/dev/sde",
"rota": false,
"type": "disk",
"children": [
{
"name": "sde1",
"size": "976M",
"fstype": "vfat",
"uuid": "9DAB-4792",
"model": null,
"serial": null,
"path": "/dev/sde1",
"rota": false,
"type": "part"
},
{
"name": "sde2",
"size": "977M",
"fstype": "linux_raid_member",
"uuid": "e895a645-731a-c3f0-4f42-5bf822ece61e",
"model": null,
"serial": null,
"path": "/dev/sde2",
"rota": false,
"type": "part",
"children": [
{
"name": "md0",
"size": "976M",
"fstype": "ext4",
"uuid": "4326ce97-013c-48e0-9b89-08722f8b13d3",
"model": null,
"serial": null,
"path": "/dev/md0",
"rota": false,
"type": "raid1"
}
]
},
{
"name": "sde3",
"size": "445.2G",
"fstype": "linux_raid_member",
"uuid": "b383b1c8-144c-322c-58ab-66a03745768a",
"model": null,
"serial": null,
"path": "/dev/sde3",
"rota": false,
"type": "part",
"children": [
{
"name": "md1",
"size": "445.1G",
"fstype": "crypto_LUKS",
"uuid": "d5ac7445-7491-4299-9cc5-22c316245793",
"model": null,
"serial": null,
"path": "/dev/md1",
"rota": false,
"type": "raid1",
"children": [
{
"name": "md1_crypt",
"size": "445.1G",
"fstype": "ext4",
"uuid": "aa4d959e-ebdb-4bd7-b8e9-5631a250da60",
"model": null,
"serial": null,
"path": "/dev/mapper/md1_crypt",
"rota": false,
"type": "crypt"
}
]
}
]
}
]
},
{
"name": "sdf",
"size": "953.9G",
"fstype": null,
"uuid": null,
"model": "DEXP SSD C100 1024Gb",
"serial": "MBM343145343",
"path": "/dev/sdf",
"rota": false,
"type": "disk",
"children": [
{
"name": "sdf1",
"size": "953.9G",
"fstype": "zfs_member",
"uuid": "1766286880976563783",
"model": null,
"serial": null,
"path": "/dev/sdf1",
"rota": false,
"type": "part"
},
{
"name": "sdf9",
"size": "8M",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/sdf9",
"rota": false,
"type": "part"
}
]
},
{
"name": "zd0",
"size": "4M",
"fstype": "iso9660",
"uuid": "2026-08-26-12-40-52-00",
"model": null,
"serial": null,
"path": "/dev/zd0",
"rota": false,
"type": "disk"
},
{
"name": "zd16",
"size": "100G",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/zd16",
"rota": false,
"type": "disk"
},
{
"name": "zd32",
"size": "100G",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/zd32",
"rota": false,
"type": "disk"
},
{
"name": "zd48",
"size": "10G",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/zd48",
"rota": false,
"type": "disk",
"children": [
{
"name": "zd48p1",
"size": "1M",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/zd48p1",
"rota": false,
"type": "part"
},
{
"name": "zd48p2",
"size": "256M",
"fstype": "vfat",
"uuid": "C283-D401",
"model": null,
"serial": null,
"path": "/dev/zd48p2",
"rota": false,
"type": "part"
},
{
"name": "zd48p3",
"size": "9G",
"fstype": "ext4",
"uuid": "c33ec994-5719-497b-a670-f3941f9a2792",
"model": null,
"serial": null,
"path": "/dev/zd48p3",
"rota": false,
"type": "part"
}
]
},
{
"name": "zd64",
"size": "20G",
"fstype": null,
"uuid": null,
"model": null,
"serial": null,
"path": "/dev/zd64",
"rota": false,
"type": "disk"
}
]
}
}

51
docs/invariants.md Normal file
View file

@ -0,0 +1,51 @@
# Каноническая спецификация инвариантов Sovereign C2
**Статус документа:** Строгий стандарт
**Назначение:** Определение фундаментальных правил, которые не могут быть нарушены ни при каких изменениях программного или аппаратного обеспечения. Любое техническое решение (выбор ОС, файловой системы, сетевого стека) должно доказывать соответствие данным инвариантам.
**Формат кода:** `[ДОМЕН]-[НОМЕР]`. Код постоянен, эволюция требований отслеживается историей Git.
---
## Категория A: Хранение и данные (DATA)
* **DATA-01 (Изоляция и профилирование ввода-вывода):** Хранилище строго разделяется по паттернам доступа. Физические носители и параметры файловых систем обязаны математически соответствовать профилю нагрузки: мелкоблочный случайный ввод-вывод с критическими требованиями к задержкам физически изолирован от емкостных последовательных нагрузок, а геометрия хранилища выровнена по размеру транзакции потребителя для исключения эффекта усиления записи.
* **DATA-02 (Абсолютная криптография покоя):** Все без исключения энергонезависимые носители информации криптографически защищены. Извлечение физического накопителя из вычислительного комплекса не должно раскрывать структуру, метаданные или содержимое данных.
* **DATA-03 (Иммутабельность точек восстановления):** Резервные копии формируются как атомарные, криптографически запечатанные слепки состояния, не зависящие от работоспособности исходной файловой системы и доступные для валидации в изолированной среде.
---
## Категория B: Сеть и изоляция (NET)
* **NET-01 (Мультиплексирование физической среды):** Логические домены безопасности (внешний периметр, маршрутизация, управление, внутренние вычисления) полностью изолированы друг от друга на уровне канального протокола, независимо от количества доступных физических сетевых интерфейсов.
* **NET-02 (L2 Fast-Path и скрытая плоскость данных):** Вычислительные узлы скрыты от внешних широковещательных доменов. При этом обмен данными между доверенными локальными клиентами и внутренними прикладными сервисами замыкается напрямую в общем L2-сегменте на скорости коммутатора, полностью минуя межсетевой экран и исключая нагрузку на процессор маршрутизатора.
* **NET-03 (Запрет прямой эксфильтрации):** Ни один прикладной сервис не имеет права на самостоятельное установление исходящих соединений во внешние сети. Доставка любых внешних бинарных компонентов, зависимостей и образов ПО разрешена исключительно через контролируемые локальные кэширующие шлюзы.
* **NET-04 (Обфускация транзитного трафика):** Любой исходящий трафик за пределы доверенного периметра должен быть инкапсулирован и криптографически замаскирован для предотвращения глубокого анализа пакетов (DPI), цензуры или активного зондирования промежуточными операторами связи.
* **NET-05 (Топология наложенного управления):** Административный доступ к инфраструктуре осуществляется строго через криптографически аутентифицированную одноранговую наложенную сеть (Overlay Network), исключающую зависимость от таблиц маршрутизации физических пограничных маршрутизаторов.
---
## Категория C: Физическая безопасность и доступ (SEC)
* **SEC-01 (Устойчивость к физическому захвату):** Физический захват включенного или выключенного оборудования третьими лицами на месте установки не должен приводить к автоматической компрометации критических данных или ключей управления.
* **SEC-02 (Стойкость при досмотре клиентов):** Компрометация или принудительный досмотр мобильных и клиентских устройств за пределами доверенного периметра не должны раскрывать факт наличия, архитектуру или содержимое приватных сервисов.
* **SEC-03 (Энергозависимость секретов):** Любые криптографические ключи, пароли и токены доступа существуют исключительно в энергозависимой памяти (RAM). Запись секретов в открытом виде на постоянные носители строго запрещена на всех этапах жизненного цикла инфраструктуры.
* **SEC-04 (Автономность холодной загрузки):** Базовый слой инфраструктуры обязан корректно инициализироваться в условиях полного отсутствия доступа к глобальной сети, опираясь исключительно на доверенную локальную среду и энергозависимую инъекцию мастер-ключей авторизованным оператором.
* **SEC-05 (Автономность клиентских терминалов):** Отказ, обесточивание или недоступность основного вычислительного комплекса не должны блокировать доступ пользователя к локально закэшированным критическим учетным данным и ключам на клиентских терминалах (ноутбук, смартфон).
---
## Категория D: Вычисления и отказоустойчивость (COMP)
* **COMP-01 (Детерминизм планировщика):** Компоненты управления (Control Plane) и маршрутизации получают строгие гарантии процессорного времени. Пользовательские и прикладные нагрузки утилизируют только остаточные вычислительные такты и не могут вызвать голодание системных процессов.
* **COMP-02 (Строгое бюджетирование памяти):** Оперативная память распределяется квотами с обязательным аппаратным резервом. Каждому домену (маршрутизация, кэш файловой системы, управление, вычисления) установлен жесткий лимит для предотвращения каскадных отказов по исчерпанию памяти (OOM-шторм).
* **COMP-03 (Гарантии восстановления из пепла):** При полной физической гибели основного оборудования допустима потеря данных не более чем за 7 дней (RPO ≤ 7 дней). Восстановление рабочего состояния на новом оборудовании должно выполняться оффлайн, используя исключительно холодные резервные копии и мастер-ключ.
* **COMP-04 (N-Node Elasticity):** Архитектура индифферентна к количеству и вычислительной мощности узлов. Система обязана полноценно функционировать на одном маломощном устройстве, сохраняя способность прозрачно подключать разнородные вычислительные узлы без изменения сетевой модели и логики работы сервисов.
---
## Категория E: Управление и источник правды (SSOT)
* **SSOT-01 (Идемпотентная декларативность):** Весь жизненный цикл инфраструктуры (от создания дисков до конфигурации приложений) описан в виде исполняемого кода. Процесс применения конфигурации обязан быть конвергентным и идемпотентным (безопасным для повторного запуска).
* **SSOT-02 (Локализация источника правды):** Механизмы непрерывной доставки и хранилища конфигураций (Source of Truth) размещаются внутри управляемого периметра. Инфраструктура развертывает и обновляет саму себя без привлечения внешних публичных репозиториев или облачных CI/CD конвейеров.
* **SSOT-03 (Иммутабельность вычислительных узлов):** Любые ручные изменения состояния внутри операционных систем вычислительных узлов запрещены. Обновление или исправление конфигурации достигается исключительно пересозданием вычислительного ресурса на основе эталонного образа.
* **SSOT-04 (Автономная телеметрия):** Непрерывный аудит, мониторинг и сбор телеметрии замкнуты строго внутри доверенного периметра. Любая эксфильтрация метрик, логов или событий безопасности во внешние облачные платформы категорически запрещена.

382
docs/topology.yaml Normal file
View file

@ -0,0 +1,382 @@
hardware:
cpu:
architecture: "x86_64"
model: "AMD Ryzen 5 3350GE with Radeon Vega Graphics"
threads: 8
cores: 4
ram:
total_bytes: 39863885824
budgeting_gb:
reserved_apu: 0.064
arc_cache_limit: 4.0
vyos_podman: 1.0
lxc_tier0: 2.5
talos_master: 2.5
talos_workers: 20.0
oom_headroom: 9.936
storage:
pools:
astra:
type: "zfs_raidz1"
media: "ssd"
devices:
- "/dev/disk/by-id/ata-DEXP_SSD_C100_1Tb_HGB446242911"
- "/dev/disk/by-id/ata-DEXP_SSD_C100_1Tb_HGB443029148"
- "/dev/disk/by-id/ata-DEXP_SSD_C100_1024Gb_MBM343145343"
terra:
type: "zfs_single"
media: "hdd"
devices:
- "/dev/disk/by-id/ata-TOSHIBA_HDWA120_27MWR2SAS"
local:
type: "mdadm_luks_ext4"
media: "ssd"
devices:
- "/dev/disk/by-id/ata-Patriot_P210_512GB_P210EDCB22092102722"
- "/dev/disk/by-id/ata-HS-SSD-C100_480G_30103741962"
network:
vlans:
vlan_10:
id: 10
name: "TIER0"
cidr: "10.0.10.0/24"
gateway: "10.0.10.1"
policy: "strict_internal"
vlan_20:
id: 20
name: "K8S"
cidr: "10.0.20.0/24"
gateway: "10.0.20.1"
policy: "k8s_overlay"
vlan_30:
id: 30
name: "LAN_CLIENTS"
cidr: "10.0.30.0/24"
gateway: "10.0.30.1"
policy: "l2_fast_path_vip"
vlan_40:
id: 40
name: "IOT"
cidr: "10.0.40.0/24"
gateway: "10.0.40.1"
policy: "isolated_no_internet"
vlan_99:
id: 99
name: "WAN_TRUNK"
cidr: "192.168.1.0/24"
gateway: "192.168.1.1"
policy: "external_egress"
tier0_ips:
vyos: "10.0.10.1"
dns0: "10.0.10.11"
vault0: "10.0.10.12"
git0: "10.0.10.13"
storage0: "10.0.10.14"
registry0: "10.0.10.15"
infrastructure_nodes:
- id: 100
name: "vyos-router"
type: "vm"
role: "edge_router"
vcpu: 2
ram_mb: 1024
disk_gb: 10
pool: "astra"
- id: 101
name: "dns0"
type: "lxc"
role: "dns_server"
vcpu: 1
ram_mb: 512
disk_gb: 2
pool: "local"
- id: 102
name: "vault0"
type: "lxc"
role: "secrets_manager"
vcpu: 1
ram_mb: 512
disk_gb: 4
pool: "local"
- id: 103
name: "git0"
type: "lxc"
role: "gitops_repo"
vcpu: 2
ram_mb: 1024
disk_gb: 8
pool: "local"
- id: 104
name: "storage0"
type: "lxc"
role: "nas_storage"
vcpu: 2
ram_mb: 1024
disk_gb: 4
pool: "local"
mounts:
- path: "/mnt/media"
volume: "/terra/media"
- path: "/mnt/torrents"
volume: "/terra/torrents"
- path: "/mnt/backups"
volume: "/terra/vault"
- id: 105
name: "registry0"
type: "lxc"
role: "oci_registry"
vcpu: 2
ram_mb: 1024
disk_gb: 8
pool: "local"
mounts:
- path: "/mnt/registry"
pool: "terra"
volume: "/terra/registry"
- id: 201
name: "talos-master-1"
type: "vm"
role: "k8s_control_plane"
vcpu: 2
ram_mb: 2560
disk_gb: 20
pool: "astra"
- id: 202
name: "talos-worker-1"
type: "vm"
role: "k8s_worker"
vcpu: 4
ram_mb: 10240
disk_gb: 100
pool: "astra"
- id: 203
name: "talos-worker-2"
type: "vm"
role: "k8s_worker"
vcpu: 4
ram_mb: 10240
disk_gb: 100
pool: "astra"
workloads:
- name: "cilium_cni"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "traefik_v3"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "csi_drivers"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "IO-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "fluxcd"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "Idle"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "kyverno"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "tetragon"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "vector_agent"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "IO-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "crowdsec"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "CPU-Bound"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "SQLite"
- name: "postgresql"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "SSD"
storage_fs: "ZVOL"
db_dependency: "None"
- name: "redis_cache"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "RAM-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "authentik_sso"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "Postgres, Redis"
- name: "vaultwarden"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "Idle"
storage_medium: "SSD"
storage_fs: "ZVOL"
db_dependency: "SQLite"
- name: "immich_system"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "CPU-Bound"
storage_medium: "SSD"
storage_fs: "ZVOL"
media_storage_medium: "SSD"
media_storage_fs: "PVC"
db_dependency: "Postgres, Redis"
- name: "paperless_ngx"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "CPU-Bound"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "Postgres, Redis"
- name: "netbox_dcim"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "Idle"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "Postgres, Redis"
- name: "opencloud"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "Postgres, Redis"
- name: "homebox"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "Idle"
storage_medium: "SSD"
storage_fs: "ZVOL"
db_dependency: "SQLite"
- name: "spoolman"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "Idle"
storage_medium: "SSD"
storage_fs: "ZVOL"
db_dependency: "SQLite"
- name: "victoriametrics"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "None"
- name: "grafana_loki"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "HDD"
storage_fs: "Dataset"
db_dependency: "None"
- name: "grafana_ui"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "Idle"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "SQLite"
- name: "pixie"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "RAM-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "qbittorrent"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "HDD"
storage_fs: "Dataset"
db_dependency: "None"
- name: "jellyfin"
runtime: "bare-metal"
state_type: "Stateful"
compute_profile: "IO-Bound"
storage_medium: "HDD"
storage_fs: "Dataset"
db_dependency: "None"
- name: "kiwix_reader"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "IO-Bound"
storage_medium: "HDD"
storage_fs: "Dataset"
db_dependency: "None"
- name: "sure_finance"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "Idle"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "Postgres"
- name: "searxng"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "act_runner_ci"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "karakeep"
runtime: "k8s"
state_type: "Micro-Stateful"
compute_profile: "Idle"
storage_medium: "SSD"
storage_fs: "PVC"
db_dependency: "SQLite"
- name: "transmute"
runtime: "k8s"
state_type: "Stateless"
compute_profile: "CPU-Bound"
storage_medium: "RAM"
storage_fs: "tmpfs"
db_dependency: "None"
- name: "printstash"
runtime: "k8s"
state_type: "Stateful"
compute_profile: "Idle"
storage_medium: "HDD"
storage_fs: "Dataset"
db_dependency: "Postgres"

29
repomix.config.json Normal file
View file

@ -0,0 +1,29 @@
{
"output": {
"filePath": "repomix-output.xml",
"style": "xml",
"removeComments": false,
"removeEmptyLines": true,
"showLineNumbers": false,
"copyToClipboard": true
},
"include": [
"**/*"
],
"ignore": {
"useGitignore": true,
"useDefaultPatterns": true,
"customPatterns": [
"**/.terraform/**",
"**/.terraform.lock.hcl",
"**/*.tfstate*",
"**/terraform.tfvars",
"vpn/*.priv",
"**/*.priv",
"**/*.key"
]
},
"security": {
"enableSecurityCheck": true
}
}

21
talos/generate_config.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash
set -euo pipefail
mkdir -p talos/clusterconfig
if [ ! -f "talos/secrets.yaml" ]; then
talosctl gen secrets -o talos/secrets.yaml
fi
chmod 0600 talos/secrets.yaml
talosctl gen config atlas https://10.0.20.10:6443 \
--with-secrets talos/secrets.yaml \
--config-patch @talos/patches/common.yaml \
--config-patch-worker @talos/patches/worker.yaml \
--output-dir talos/clusterconfig \
--with-docs=false \
--with-examples=false \
--force
chmod 0600 talos/clusterconfig/*

27
talos/patches/common.yaml Normal file
View file

@ -0,0 +1,27 @@
machine:
network:
nameservers:
- 10.0.10.11
- 10.0.20.1
registries:
config:
10.0.10.15:5000:
tls:
insecureSkipVerify: true
mirrors:
docker.io:
overridePath: true
endpoints:
- http://10.0.10.15:5000/v2/docker.io
ghcr.io:
overridePath: true
endpoints:
- http://10.0.10.15:5000/v2/ghcr.io
registry.k8s.io:
overridePath: true
endpoints:
- http://10.0.10.15:5000/v2/k8s.io
cluster:
network:
cni:
name: none

View file

@ -0,0 +1,7 @@
machine:
network:
interfaces:
- interface: eth0
dhcp: true
- interface: eth1
dhcp: false

422
tofu/compute.tf Normal file
View file

@ -0,0 +1,422 @@
variable "talos_iso_file_id" {
type = string
description = "Proxmox file ID for the Talos Linux ISO"
default = "local:iso/talos-amd64.iso"
}
# ==============================================================================
# ROUTING & EDGE (VyOS)
# ==============================================================================
resource "proxmox_virtual_environment_vm" "vyos_router" {
vm_id = 100
name = "vyos-router"
node_name = "pve0"
started = true
cpu {
cores = 2
type = "host"
}
memory {
dedicated = 1024
}
disk {
datastore_id = "astra"
file_id = "local:iso/vyos-1.5-cloudinit.img"
interface = "virtio0"
size = 10
}
# Явный контракт загрузки: стартуем с подготовленного диска
boot_order = ["virtio0"]
# VLAN 99: WAN_TRUNK
network_device {
bridge = "vmbr0"
vlan_id = 99
model = "virtio"
}
# VLAN 10: TIER0 (MGMT)
network_device {
bridge = "vmbr0"
vlan_id = 10
model = "virtio"
}
# VLAN 20: K8S
network_device {
bridge = "vmbr0"
vlan_id = 20
model = "virtio"
}
# VLAN 30: LAN_CLIENTS
network_device {
bridge = "vmbr0"
vlan_id = 30
model = "virtio"
}
operating_system {
type = "l26"
}
agent {
enabled = true
}
}
# ==============================================================================
# TIER-0 LXC CONTAINERS (AIR-GAP FOUNDATION)
# ==============================================================================
resource "proxmox_virtual_environment_container" "dns0" {
vm_id = 101
node_name = "pve0"
unprivileged = true
started = true
cpu { cores = 1 }
memory { dedicated = 512 }
disk {
datastore_id = "local"
size = 2
}
network_interface {
name = "eth0"
bridge = "vmbr0"
vlan_id = 10
}
initialization {
hostname = "dns0"
ip_config {
ipv4 {
address = "10.0.10.11/24"
gateway = "10.0.10.1"
}
}
user_account { keys = [var.ssh_public_key] }
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_amd64.tar.zst"
type = "debian"
}
}
resource "proxmox_virtual_environment_container" "vault0" {
vm_id = 102
node_name = "pve0"
unprivileged = true
started = true
cpu { cores = 1 }
memory { dedicated = 512 }
disk {
datastore_id = "local"
size = 4
}
network_interface {
name = "eth0"
bridge = "vmbr0"
vlan_id = 10
}
initialization {
hostname = "vault0"
ip_config {
ipv4 {
address = "10.0.10.12/24"
gateway = "10.0.10.1"
}
}
user_account { keys = [var.ssh_public_key] }
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_amd64.tar.zst"
type = "debian"
}
}
resource "proxmox_virtual_environment_container" "git0" {
vm_id = 103
node_name = "pve0"
unprivileged = true
started = true
cpu { cores = 2 }
memory { dedicated = 1024 }
disk {
datastore_id = "local"
size = 8
}
network_interface {
name = "eth0"
bridge = "vmbr0"
vlan_id = 10
}
initialization {
hostname = "git0"
ip_config {
ipv4 {
address = "10.0.10.13/24"
gateway = "10.0.10.1"
}
}
user_account { keys = [var.ssh_public_key] }
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_amd64.tar.zst"
type = "debian"
}
}
# АРХИТЕКТУРНОЕ РЕШЕНИЕ: Прямые Host Bind Mounts (volume = "/terra/...") вызывают
# ошибку 403 Forbidden при работе Tofu через Proxmox API Token для unprivileged LXC.
# Создаем чистый контейнер. Проброс путей пула terra делегирован в Слой 2 (Ansible) через pct set.
resource "proxmox_virtual_environment_container" "storage0" {
vm_id = 104
node_name = "pve0"
unprivileged = true
started = true
cpu { cores = 2 }
memory { dedicated = 1024 }
disk {
datastore_id = "local"
size = 4
}
network_interface {
name = "eth0"
bridge = "vmbr0"
vlan_id = 10
}
initialization {
hostname = "storage0"
ip_config {
ipv4 {
address = "10.0.10.14/24"
gateway = "10.0.10.1"
}
}
user_account { keys = [var.ssh_public_key] }
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_amd64.tar.zst"
type = "debian"
}
}
# АРХИТЕКТУРНОЕ РЕШЕНИЕ: Аналогично storage0, монтирование динамического датасета
# /terra/registry делегировано в Слой 2 (Ansible).
resource "proxmox_virtual_environment_container" "registry0" {
vm_id = 105
node_name = "pve0"
unprivileged = true
started = true
cpu { cores = 2 }
memory { dedicated = 1024 }
disk {
datastore_id = "local"
size = 8
}
network_interface {
name = "eth0"
bridge = "vmbr0"
vlan_id = 10
}
initialization {
hostname = "registry0"
ip_config {
ipv4 {
address = "10.0.10.15/24"
gateway = "10.0.10.1"
}
}
user_account { keys = [var.ssh_public_key] }
}
operating_system {
template_file_id = "local:vztmpl/debian-12-standard_amd64.tar.zst"
type = "debian"
}
}
# ==============================================================================
# TALOS KUBERNETES CLUSTER
# ==============================================================================
resource "proxmox_virtual_environment_vm" "talos_master_1" {
vm_id = 201
name = "talos-master-1"
node_name = "pve0"
started = true
cpu {
cores = 2
type = "host"
units = 2048
}
memory {
dedicated = 2560
}
disk {
datastore_id = "astra"
file_format = "raw"
interface = "virtio0"
size = 20
}
# Boot Contract: Явное указание интерфейса ide2 для совпадения с boot_order
cdrom {
file_id = var.talos_iso_file_id
interface = "ide2"
}
boot_order = ["virtio0", "ide2"]
network_device {
bridge = "vmbr0"
vlan_id = 20
model = "virtio"
}
operating_system {
type = "l26"
}
# Lifecycle Safety: Отключаем ожидание QEMU агента, так как его нет в ISO установщика
agent {
enabled = false
}
}
resource "proxmox_virtual_environment_vm" "talos_worker_1" {
vm_id = 202
name = "talos-worker-1"
node_name = "pve0"
started = true
cpu {
cores = 4
type = "host"
units = 1024
}
memory {
dedicated = 10240
}
disk {
datastore_id = "astra"
file_format = "raw"
interface = "virtio0"
size = 100
}
cdrom {
file_id = var.talos_iso_file_id
interface = "ide2"
}
boot_order = ["virtio0", "ide2"]
# eth0: K8S Overlay
network_device {
bridge = "vmbr0"
vlan_id = 20
model = "virtio"
}
# eth1: LAN_CLIENTS (L2 Fast-Path)
network_device {
bridge = "vmbr0"
vlan_id = 30
model = "virtio"
}
operating_system {
type = "l26"
}
agent {
enabled = false
}
}
resource "proxmox_virtual_environment_vm" "talos_worker_2" {
vm_id = 203
name = "talos-worker-2"
node_name = "pve0"
started = true
cpu {
cores = 4
type = "host"
units = 1024
}
memory {
dedicated = 10240
}
disk {
datastore_id = "astra"
file_format = "raw"
interface = "virtio0"
size = 100
}
cdrom {
file_id = var.talos_iso_file_id
interface = "ide2"
}
boot_order = ["virtio0", "ide2"]
# eth0: K8S Overlay
network_device {
bridge = "vmbr0"
vlan_id = 20
model = "virtio"
}
# eth1: LAN_CLIENTS (L2 Fast-Path)
network_device {
bridge = "vmbr0"
vlan_id = 30
model = "virtio"
}
operating_system {
type = "l26"
}
agent {
enabled = false
}
}

42
tofu/providers.tf Normal file
View file

@ -0,0 +1,42 @@
terraform {
required_version = ">= 1.8.0"
encryption {
key_provider "pbkdf2" "state_key" {
passphrase = var.state_passphrase
}
method "aes_gcm" "state_method" {
keys = key_provider.pbkdf2.state_key
}
state {
method = method.aes_gcm.state_method
enforced = true
}
plan {
method = method.aes_gcm.state_method
enforced = true
}
}
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.73.0"
}
}
}
provider "proxmox" {
endpoint = var.pve_endpoint
insecure = true
username = var.pve_username
password = var.pve_password
ssh {
agent = true
username = "root"
}
}

26
tofu/variables.tf Normal file
View file

@ -0,0 +1,26 @@
variable "pve_endpoint" {
type = string
description = "URL API Proxmox"
}
variable "pve_username" {
type = string
sensitive = true
description = "API Токен гипервизора"
}
variable "state_passphrase" {
type = string
sensitive = true
description = "Ключ шифрования состояния AES-GCM"
}
variable "ssh_public_key" {
type = string
description = "Публичный SSH-ключ для доступа к ВМ и LXC"
}
variable "pve_password" {
type = string
sensitive = true
}