atlas svo
This commit is contained in:
commit
a54778f061
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal 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
13
ansible/ansible.cfg
Normal 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
|
||||
63
ansible/ansible/roles/lxc_tier0/tasks/main.yml
Normal file
63
ansible/ansible/roles/lxc_tier0/tasks/main.yml
Normal 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
21
ansible/inventory.yml
Normal 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
|
||||
59
ansible/playbooks/01_pve_host_day0.yml
Normal file
59
ansible/playbooks/01_pve_host_day0.yml
Normal 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
|
||||
24
ansible/playbooks/02_vyos_network_day0.yml
Normal file
24
ansible/playbooks/02_vyos_network_day0.yml
Normal 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
|
||||
135
ansible/playbooks/03_zot_registry.yml
Normal file
135
ansible/playbooks/03_zot_registry.yml
Normal 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
|
||||
72
ansible/playbooks/04_technitium_dns.yml
Normal file
72
ansible/playbooks/04_technitium_dns.yml
Normal 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
|
||||
112
ansible/playbooks/05_openbao_vault.yml
Normal file
112
ansible/playbooks/05_openbao_vault.yml
Normal 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
|
||||
115
ansible/playbooks/06_forgejo_git.yml
Normal file
115
ansible/playbooks/06_forgejo_git.yml
Normal 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
|
||||
110
ansible/playbooks/07_nas_storage.yml
Normal file
110
ansible/playbooks/07_nas_storage.yml
Normal 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
23
deploy.sh
Executable 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
650
docs/hardware_snapshot.json
Normal 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
51
docs/invariants.md
Normal 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
382
docs/topology.yaml
Normal 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
29
repomix.config.json
Normal 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
21
talos/generate_config.sh
Executable 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
27
talos/patches/common.yaml
Normal 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
|
||||
7
talos/patches/worker.yaml
Normal file
7
talos/patches/worker.yaml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
machine:
|
||||
network:
|
||||
interfaces:
|
||||
- interface: eth0
|
||||
dhcp: true
|
||||
- interface: eth1
|
||||
dhcp: false
|
||||
422
tofu/compute.tf
Normal file
422
tofu/compute.tf
Normal 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
42
tofu/providers.tf
Normal 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
26
tofu/variables.tf
Normal 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
|
||||
}
|
||||
Loading…
Reference in a new issue