restore UISP server + caddy frontend, fix SSH host key regeneration, add tofu proxmox provider

This commit is contained in:
Graham McIntire 2026-06-21 19:06:33 -05:00
parent 216bd8e668
commit d6cf15165a
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
11 changed files with 264 additions and 5 deletions

View file

@ -1,5 +1,6 @@
---
ansible_host: 204.110.191.224
ansible_user: debian
ansible_python_interpreter: /usr/bin/python3
ansible_ssh_common_args: '-o StrictHostKeyChecking=accept-new'

View file

@ -40,6 +40,7 @@ aprs.w5isp.com
[caddy_servers]
skippy.w5isp.com
netbox.vntx.net
uisp.vntx.net
[netbox_servers]
netbox.vntx.net
@ -65,5 +66,5 @@ us.manero.org ansible_host=manero-us
ca.manero.org ansible_host=manero-ca
[nixos_resolvers]
nixos-resolver ansible_host=nixos-resolver
nixos-resolver1 ansible_host=nixos-resolver1

View file

@ -117,6 +117,7 @@
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
storage: "{{ proxmox_storage }}"
timeout: 90
full: true
@ -129,6 +130,7 @@
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
cores: "{{ vm_cores }}"
memory: "{{ vm_memory }}"
update: true
@ -139,6 +141,7 @@
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
disk: scsi0
size: "{{ vm_disk_size }}G"
state: resized
@ -151,6 +154,7 @@
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
ipconfig:
ipconfig0: "ip={{ vm_ip }}/26,gw={{ vm_gateway }}"
nameservers:
@ -168,6 +172,7 @@
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
state: started
- name: Wait for VM to be accessible via SSH
@ -466,6 +471,122 @@
roles:
- aprsc
- name: Provision UISP VM on Proxmox
hosts: localhost
gather_facts: false
tags:
- uisp
- provision
- never
vars:
# Proxmox connection settings
proxmox_node: "{{ lookup('env', 'PROXMOX_NODE') | default('vm2-380', true) }}"
proxmox_api_host: 10.0.0.2
proxmox_api_user: "{{ lookup('env', 'PROXMOX_API_USER') | default('root@pam', true) }}"
proxmox_api_password: "{{ lookup('env', 'PROXMOX_API_PASSWORD') }}"
proxmox_storage: local-lvm
proxmox_template_name: debian-cloud-init
proxmox_template_vmid: 9000
# UISP VM configuration
vm_name: uisp.vntx.net
vm_vmid: 224
vm_ip: 204.110.191.224
vm_gateway: 204.110.191.254
vm_cores: 20
vm_memory: 16384
vm_disk_size: 64
vm_vlan: 9
ansible_ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFghGMnDdkfNC6JPEhMxrKhYDmNcXjHXp/y/mf3uLtzb"
tasks:
- name: Clone cloud-init template for UISP server
community.proxmox.proxmox_kvm:
node: "{{ proxmox_node }}"
vmid: "{{ proxmox_template_vmid }}"
clone: "{{ proxmox_template_name }}"
newid: "{{ vm_vmid }}"
name: "{{ vm_name }}"
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
storage: "{{ proxmox_storage }}"
timeout: 90
full: true
- name: Configure VM resources
community.proxmox.proxmox_kvm:
node: "{{ proxmox_node }}"
vmid: "{{ vm_vmid }}"
name: "{{ vm_name }}"
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
cores: "{{ vm_cores }}"
memory: "{{ vm_memory }}"
net:
net0: "virtio,bridge=vmbr0,tag={{ vm_vlan }}"
update: true
- name: Resize disk
community.proxmox.proxmox_disk:
vmid: "{{ vm_vmid }}"
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
disk: scsi0
size: "{{ vm_disk_size }}G"
state: resized
- name: Configure cloud-init network
community.proxmox.proxmox_kvm:
node: "{{ proxmox_node }}"
vmid: "{{ vm_vmid }}"
name: "{{ vm_name }}"
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
ipconfig:
ipconfig0: "ip={{ vm_ip }}/26,gw={{ vm_gateway }}"
nameservers:
- 1.1.1.1
- 8.8.8.8
ciuser: debian
cipassword: "sxcbctolxALGnj2R8GStXrfW8GVd3s/ju91fNon7T1U="
searchdomains: vntx.net
sshkeys: "{{ ansible_ssh_key }}"
update: true
- name: Start VM
community.proxmox.proxmox_kvm:
node: "{{ proxmox_node }}"
vmid: "{{ vm_vmid }}"
name: "{{ vm_name }}"
api_user: "{{ proxmox_api_user }}"
api_password: "{{ proxmox_api_password }}"
api_host: "{{ proxmox_api_host }}"
validate_certs: false
state: started
- name: Wait for VM to be accessible via SSH
ansible.builtin.wait_for:
host: "{{ vm_ip }}"
port: 22
delay: 30
timeout: 300
state: started
- name: Add VM to in-memory inventory
ansible.builtin.add_host:
name: "{{ vm_name }}"
ansible_host: "{{ vm_ip }}"
ansible_user: debian
groups: uisp_servers
- name: Configure UISP servers
hosts: uisp_servers
become: true
@ -473,7 +594,10 @@
tags:
- uisp
roles:
- uisp
- role: base
tags: base
- role: uisp
tags: uisp
- name: Configure Dokku servers
hosts: dokku_servers

View file

@ -27,6 +27,7 @@
- name: Regenerate SSH host keys
ansible.builtin.command:
cmd: ssh-keygen -A
args:
creates: /etc/ssh/ssh_host_ed25519_key
when: ansible_facts['os_family'] == "Debian"

View file

@ -0,0 +1,15 @@
uisp.vntx.net {
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
}
reverse_proxy https://localhost:8443 {
transport http {
tls_insecure_skip_verify
}
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}

View file

@ -105,7 +105,7 @@
- name: Download UISP installer script
ansible.builtin.get_url:
url: https://getuisp.com/install.sh
url: https://uisp.ui.com/install
dest: "{{ uisp_app_dir }}/update.sh"
owner: "{{ uisp_user }}"
group: root
@ -119,9 +119,11 @@
failed_when: false
- name: Run UISP installer (first install only — skips existing)
ansible.builtin.command: "{{ uisp_app_dir }}/update.sh"
ansible.builtin.command: "{{ uisp_app_dir }}/update.sh --update"
become: true
become_user: "{{ uisp_user }}"
environment:
PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
when:
- not uisp_postgres_container.exists | default(false)
register: uisp_install
@ -131,7 +133,7 @@
ansible.builtin.copy:
dest: /etc/cron.d/unms-update
content: |
* * * * * {{ uisp_user }} {{ uisp_app_dir }}/update.sh --cron > /dev/null 2>&1 || true
* * * * * {{ uisp_user }} {{ uisp_app_dir }}/update.sh --update > /dev/null 2>&1 || true
owner: root
group: root
mode: '0644'

View file

@ -1,6 +1,40 @@
# This file is maintained automatically by "tofu init".
# Manual edits may be lost in future updates.
provider "registry.opentofu.org/bpg/proxmox" {
version = "0.110.0"
constraints = "~> 0.73"
hashes = [
"h1:CmD2DUi0wm0QrmOo0+y9AWo0IHVnbBusJyXZUfJygog=",
"h1:GyRZ1NI0nZD0MRsL2fwzkM4js4wZMPrSS54culEoVL8=",
"h1:Lt4c3HAwfiLkZR6d4VGs39DbFJUPmAYuUsZWlrtGc7E=",
"h1:NTgKnVpERB79Njen2hi8qs4lqo/jAh65ossyHZ8vLsc=",
"h1:ONmlUxolb7Wsvw+uXJHat9qqoO2k4oB1pSX3jHdtc8c=",
"h1:Por3tFR3Xlup/nvDNI/NCc7bCgRJotcYOgBYOCbWtos=",
"h1:Vt35/l/0+/HBaFrZGKt3dlhstxaUJz77yZFHPHdjnjg=",
"h1:WWArX57beGP4K7BA+H8WRrxZTMNixQI2ad++K8P1JCo=",
"h1:biwuaVoTqlXMFxtjSJ7Pz3WgYXRRp/KsloLvK3SB2+c=",
"h1:eCQKW6guUjlUU06MKgGFgIuJRBlSmZJvsQEe8BpNAtg=",
"h1:qqL9hKHlFnfwxJJ0gi10gwkUCAnMdfiv3qt2fx+DKag=",
"h1:wz47cguCgZsPR+S7BC3F2FPu3NhMJ6vp/K0mCE7bswE=",
"h1:yWBV4ZnuKV4TwR32cqKj6+dkNf5cIbB06fxKOopM6ZI=",
"zh:208b983701f3dc1d1028d6bd6830453c5b778226899de97207317b140e56083e",
"zh:21d22ee1082745e309be59f690ca8fc63374b59d396c314905fba5ed13f7159c",
"zh:28523eee5fc04df414f67175bfe14260946d86be5a6fd1e1b124be18639b7545",
"zh:2b863781982476ed24d05cec19c23c8dc3894714c3e2f6571f489c297e3ed12a",
"zh:3bbeb3cbb705245d2084769c0612099ea267bc45d0f61d5d21604a1e8d341eae",
"zh:94706cacd457a15120ce7345cab3a7274714f12dc80150d468e80abe0bac867d",
"zh:9976da036955ad9b3cbb0c2a710d799d7b91a2d192f14050716b90c6493a35be",
"zh:ac30d314e03cebe281c5da1f7963c8ded3d470fb4ef5a0b9086c08d574f35b91",
"zh:c2f27ffbd83614d2507a948c56f0f5b4b1ecdc5654d65f68f2929ab4dbdf5d7b",
"zh:d9126e674744127976aa365b3ce2f8073f206dea945fc028a89d293bcbd94dab",
"zh:ecf37aca9a909ac1b9e9bd2e3cd3330dc8f5e666fde5dc436e520c19bf5eee55",
"zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
"zh:f3e30cce3165227f3417ab4497af873bae2a459be1adbb6196595ee1ca8ad6ae",
"zh:f4b2edd80b4c34917942401f9e4e7fb1cc5b803e7a12dc1dba7bbf834a5c7eb0",
]
}
provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "5.19.1"
constraints = "~> 5.0"

View file

@ -8,6 +8,10 @@ terraform {
source = "cloudflare/cloudflare"
version = "~> 5.0"
}
proxmox = {
source = "bpg/proxmox"
version = "~> 0.73"
}
}
}
@ -18,3 +22,10 @@ provider "porkbun" {
provider "cloudflare" {
# Credentials via CLOUDFLARE_API_TOKEN env var
}
provider "proxmox" {
endpoint = "https://10.0.0.2:8006"
username = "root@pam"
password = var.proxmox_password
insecure = true
}

65
tofu/proxmox.tf Normal file
View file

@ -0,0 +1,65 @@
# NixOS resolver VM Unbound DNS resolver on Proxmox
# Template (VMID 9010) must exist first; built via: ansible-playbook playbook.yml --tags template
locals {
nixos_ssh_keys = trimspace(<<-EOT
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHLyVSEEAEbGZZqwPwEup0XrlTpu3x3iF9ExvvQPA4xN
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOzrDMNn3nINGdIogzRxY05fkn05LSYi98BGW1Bz5yXD
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIER/8suIKcrT3a/NZHjvOpRosPC5uX4kcznIJHt/98qj
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEEKtgXwoW8HZGqC+KJok9iNpI/lK4glvoryL4Ng/AL+
EOT
)
}
resource "proxmox_virtual_environment_vm" "nixos_resolver" {
node_name = "vm2-380"
name = "nixos-resolver1"
vm_id = 110
clone {
vm_id = 9010
full = true
}
cpu {
cores = 2
}
memory {
dedicated = 4096
}
disk {
datastore_id = "local-lvm"
interface = "scsi0"
size = 64
}
network_device {
bridge = "vmbr0"
}
initialization {
datastore_id = "local-lvm"
ip_config {
ipv4 {
address = "10.0.0.30/24"
gateway = "10.0.0.254"
}
}
dns {
servers = ["9.9.9.9"]
}
user_account {
username = "root"
keys = [local.nixos_ssh_keys]
}
}
agent {
enabled = true
}
}

5
tofu/variables.tf Normal file
View file

@ -0,0 +1,5 @@
variable "proxmox_password" {
description = "Proxmox API password (set via TF_VAR_proxmox_password env var)"
type = string
sensitive = true
}