This commit is contained in:
Graham McIntire 2025-09-12 09:58:37 -05:00
parent b65a8cb61e
commit 4d376c353f
No known key found for this signature in database
5 changed files with 544 additions and 0 deletions

View file

@ -0,0 +1,216 @@
---
- name: Create PostgreSQL 17 LXC Container with Debian 13 on lab02
hosts: lab02
become: true
vars:
ct_id: 300
ct_name: postgres
ct_template: "local:vztmpl/debian-13-standard_13.1-1_amd64.tar.zst"
ct_memory: 8192 # 8GB RAM
ct_disk_size: 512 # 512GB storage as requested
ct_cores: 4
ct_ip: "10.0.19.5/22"
ct_gateway: "10.0.19.254"
ct_storage: "ceph" # Use Ceph RBD storage
aprs_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits length=16') }}"
tasks:
- name: Check if container already exists
command: pct status {{ ct_id }}
register: ct_exists
failed_when: false
changed_when: false
- name: Stop and destroy existing container if it exists
shell: |
pct stop {{ ct_id }} || true
pct destroy {{ ct_id }} --purge || true
when: ct_exists.rc == 0
- name: List available templates
command: pveam list local
register: template_list
changed_when: false
- name: Show available templates
debug:
msg: "Available templates: {{ template_list.stdout_lines | select('match', '.*debian.*') | list }}"
- name: Create PostgreSQL LXC container
command: |
pct create {{ ct_id }} {{ ct_template }} \
--hostname {{ ct_name }} \
--memory {{ ct_memory }} \
--cores {{ ct_cores }} \
--net0 name=eth0,bridge=vmbr0,ip={{ ct_ip }},gw={{ ct_gateway }} \
--storage {{ ct_storage }} \
--rootfs {{ ct_storage }}:{{ ct_disk_size }} \
--unprivileged 1 \
--features nesting=1 \
--onboot 1 \
--startup order=10
- name: Start container
command: pct start {{ ct_id }}
- name: Wait for container to boot
pause:
seconds: 30
- name: Update container packages
shell: pct exec {{ ct_id }} -- apt update && pct exec {{ ct_id }} -- apt upgrade -y
- name: Install PostgreSQL 17 repository
shell: |
pct exec {{ ct_id }} -- bash -c "
apt-get install -y wget ca-certificates
sh -c 'echo \"deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main\" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
apt-get update
"
- name: Install PostgreSQL 17 and PostGIS
shell: |
pct exec {{ ct_id }} -- bash -c "
export DEBIAN_FRONTEND=noninteractive
apt-get install -y postgresql-17 postgresql-contrib-17 postgresql-17-postgis-3 postgis
"
- name: Start and enable PostgreSQL
shell: |
pct exec {{ ct_id }} -- bash -c "
systemctl enable postgresql
systemctl start postgresql
"
- name: Configure PostgreSQL for network access
shell: |
pct exec {{ ct_id }} -- bash -c "
# Configure postgresql.conf
sed -i \"s/#listen_addresses = 'localhost'/listen_addresses = '*'/g\" /etc/postgresql/17/main/postgresql.conf
# Configure pg_hba.conf
echo '# TYPE DATABASE USER ADDRESS METHOD' > /etc/postgresql/17/main/pg_hba.conf
echo 'local all postgres peer' >> /etc/postgresql/17/main/pg_hba.conf
echo 'local all all peer' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all 127.0.0.1/32 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all ::1/128 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all 10.0.19.0/24 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all 10.0.16.0/22 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all 10.42.0.0/16 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
echo 'host all all 10.43.0.0/16 scram-sha-256' >> /etc/postgresql/17/main/pg_hba.conf
# Restart PostgreSQL
systemctl restart postgresql
"
- name: Create APRS user and database
shell: |
pct exec {{ ct_id }} -- su - postgres -c "psql << 'EOF'
-- Create APRS user and database
CREATE USER aprs WITH PASSWORD '{{ aprs_password }}';
CREATE DATABASE aprs OWNER aprs;
\c aprs
CREATE EXTENSION IF NOT EXISTS postgis;
GRANT ALL PRIVILEGES ON DATABASE aprs TO aprs;
GRANT ALL ON SCHEMA public TO aprs;
ALTER DATABASE aprs SET search_path TO public, postgis;
EOF"
- name: Test APRS database connection
shell: |
pct exec {{ ct_id }} -- su - postgres -c "psql -d aprs -c 'SELECT version(); SELECT PostGIS_full_version();'"
register: db_test
- name: Save APRS password to file
copy:
content: "{{ aprs_password }}"
dest: "./aprs_db_password.txt"
mode: '0600'
delegate_to: localhost
- name: Display connection info
debug:
msg: |
PostgreSQL 17 with PostGIS installed successfully on Debian 13!
Container details:
- Container ID: {{ ct_id }}
- Host: lab02
- IP: 10.0.19.5
- Storage: {{ ct_disk_size }}GB on {{ ct_storage }}
Database details:
- PostgreSQL version: 17
- PostGIS: Installed
- Database: aprs
- User: aprs
- Password: {{ aprs_password }}
- Password saved to: ./aprs_db_password.txt
Connection string:
postgresql://aprs:{{ aprs_password }}@10.0.19.5:5432/aprs
Test output:
{{ db_test.stdout }}
- name: Create K8s secret for APRS database
hosts: home-k3s-control-1
become: true
vars:
aprs_password: "{{ hostvars['lab02']['aprs_password'] }}"
tasks:
- name: Create aprs namespace if it doesn't exist
command: |
/usr/local/bin/k3s kubectl create namespace aprs --dry-run=client -o yaml | /usr/local/bin/k3s kubectl apply -f -
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Delete existing database secret if it exists
command: |
/usr/local/bin/k3s kubectl delete secret aprs-db-secret -n aprs --ignore-not-found=true
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Create database secret
command: |
/usr/local/bin/k3s kubectl create secret generic aprs-db-secret \
--from-literal=DATABASE_URL="ecto://aprs:{{ aprs_password }}@10.0.19.5:5432/aprs" \
--from-literal=DB_HOST="10.0.19.5" \
--from-literal=DB_PORT="5432" \
--from-literal=DB_NAME="aprs" \
--from-literal=DB_USER="aprs" \
--from-literal=DB_PASSWORD="{{ aprs_password }}" \
-n aprs
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Verify secret was created
command: |
/usr/local/bin/k3s kubectl get secret aprs-db-secret -n aprs -o yaml
register: secret_verify
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Display secret creation result
debug:
msg: |
Kubernetes secret created successfully!
Secret name: aprs-db-secret
Namespace: aprs
To use in your deployment, add:
envFrom:
- secretRef:
name: aprs-db-secret
Or individual env vars:
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: aprs-db-secret
key: DATABASE_URL

View file

@ -0,0 +1,143 @@
---
- name: Fix K3s worker nodes
hosts: k3s_workers
become: true
tasks:
- name: Stop k3s-agent service
systemd:
name: k3s-agent
state: stopped
enabled: no
ignore_errors: yes
- name: Remove k3s node password
file:
path: /etc/rancher/node/password
state: absent
- name: Remove k3s data directory
file:
path: /var/lib/rancher/k3s
state: absent
- name: Remove k3s config
file:
path: /etc/rancher/k3s
state: absent
- name: Ensure k3s binary exists
stat:
path: /usr/local/bin/k3s
register: k3s_binary
- name: Download k3s binary if missing
get_url:
url: https://github.com/k3s-io/k3s/releases/download/{{ k3s_version | default('v1.28.5+k3s1') }}/k3s
dest: /usr/local/bin/k3s
mode: '0755'
when: not k3s_binary.stat.exists
- name: Create k3s config directory
file:
path: /etc/rancher/k3s
state: directory
mode: '0755'
- name: Get token from control node
delegate_to: home-k3s-control-1
slurp:
src: /var/lib/rancher/k3s/server/node-token
register: node_token
run_once: true
- name: Create k3s agent config
copy:
content: |
server: https://{{ hostvars['home-k3s-control-1']['ansible_host'] }}:6443
token: {{ node_token.content | b64decode | trim }}
with-node-id: true
dest: /etc/rancher/k3s/config.yaml
- name: Ensure k3s-agent service exists
copy:
content: |
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service'
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s agent
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/k3s-agent.service
- name: Start k3s-agent service
systemd:
name: k3s-agent
daemon_reload: yes
enabled: yes
state: started
- name: Remove stale nodes from cluster
hosts: home-k3s-control-1
become: true
tasks:
- name: Get list of nodes
command: /usr/local/bin/k3s kubectl get nodes -o json
register: nodes_json
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Parse node list
set_fact:
nodes: "{{ nodes_json.stdout | from_json }}"
- name: Remove NotReady worker nodes
command: /usr/local/bin/k3s kubectl delete node {{ item.metadata.name }}
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
loop: "{{ nodes['items'] }}"
when:
- item.metadata.name is match("home-k3s-worker-.*")
- item.status.conditions | selectattr('type', 'equalto', 'Ready') | selectattr('status', 'equalto', 'Unknown') | list | length > 0
- name: Verify worker nodes
hosts: home-k3s-control-1
become: true
tasks:
- name: Wait for worker nodes to join
shell: /usr/local/bin/k3s kubectl get nodes | grep -E "home-k3s-worker-[0-9]+.*Ready" | wc -l
register: ready_workers
until: ready_workers.stdout | int >= 3
retries: 30
delay: 10
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Display cluster status
command: /usr/local/bin/k3s kubectl get nodes
register: final_status
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Show cluster status
debug:
var: final_status.stdout_lines

View file

@ -0,0 +1,23 @@
Forgejo Database Credentials
============================
PostgreSQL Container: 300 on lab02
Host: 10.0.19.5
Port: 5432
Database: forgejo
Username: forgejo
Password: 6Cj1BR1zgutXn0LzDCvanw
Connection String:
postgresql://forgejo:6Cj1BR1zgutXn0LzDCvanw@10.0.19.5:5432/forgejo
For Forgejo app.ini configuration:
[database]
DB_TYPE = postgres
HOST = 10.0.19.5:5432
NAME = forgejo
USER = forgejo
PASSWD = 6Cj1BR1zgutXn0LzDCvanw
SSL_MODE = disable
Note: The password has also been saved to /tmp/forgejo_db_password.txt

View file

@ -0,0 +1,161 @@
---
- name: Recreate K3s Worker-2 VM on Proxmox
hosts: lab02
gather_facts: no
vars:
template_vmid: 9000
network_gateway: "10.0.19.254"
ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHLyVSEEAEbGZZqwPwEup0XrlTpu3x3iF9ExvvQPA4xN graham@mcintire.me"
worker2:
vmid: 1201
name: "home-k3s-worker-2"
ip: "10.0.19.111/24"
cores: 4
memory: 8192
disk: "64G"
target_node: "lab03"
tasks:
- name: Clone template to create worker-2
command: |
qm clone {{ template_vmid }} {{ worker2.vmid }} \
--name {{ worker2.name }} \
--full true \
--target {{ worker2.target_node }}
register: clone_result
- name: Configure worker-2 VM
delegate_to: lab03
command: |
qm set {{ worker2.vmid }} \
--cores {{ worker2.cores }} \
--memory {{ worker2.memory }} \
--ipconfig0 ip={{ worker2.ip }},gw={{ network_gateway }} \
--sshkeys /root/.ssh/authorized_keys \
--onboot 1
- name: Resize disk if needed
delegate_to: lab03
command: |
qm resize {{ worker2.vmid }} scsi0 {{ worker2.disk }}
ignore_errors: yes
- name: Start worker-2 VM
delegate_to: lab03
command: qm start {{ worker2.vmid }}
- name: Wait for VM to boot
pause:
seconds: 90
- name: Test SSH connectivity
delegate_to: localhost
wait_for:
host: 10.0.19.111
port: 22
timeout: 300
- name: Configure K3s on worker-2
hosts: home-k3s-worker-2
become: true
tasks:
- name: Wait for SSH to be ready
wait_for_connection:
delay: 30
timeout: 300
- name: Gather facts
setup:
- name: Install curl
package:
name: curl
state: present
- name: Download k3s binary
get_url:
url: https://github.com/k3s-io/k3s/releases/download/v1.28.5+k3s1/k3s
dest: /usr/local/bin/k3s
mode: '0755'
- name: Create k3s config directory
file:
path: /etc/rancher/k3s
state: directory
mode: '0755'
- name: Get token from control node
delegate_to: home-k3s-control-1
slurp:
src: /var/lib/rancher/k3s/server/node-token
register: node_token
- name: Create k3s agent config
copy:
content: |
server: https://10.0.19.100:6443
token: {{ node_token.content | b64decode | trim }}
with-node-id: true
dest: /etc/rancher/k3s/config.yaml
- name: Create k3s-agent systemd service
copy:
content: |
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/default/%N
EnvironmentFile=-/etc/sysconfig/%N
KillMode=process
Delegate=yes
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s
ExecStartPre=/bin/sh -xc '! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service'
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s agent
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/k3s-agent.service
- name: Start k3s-agent service
systemd:
name: k3s-agent
daemon_reload: yes
enabled: yes
state: started
- name: Verify worker-2 joined cluster
hosts: home-k3s-control-1
become: true
tasks:
- name: Wait for worker-2 to join
shell: /usr/local/bin/k3s kubectl get nodes | grep -E "home-k3s-worker-2.*Ready"
register: worker2_status
until: worker2_status.rc == 0
retries: 30
delay: 10
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Display cluster status
command: /usr/local/bin/k3s kubectl get nodes
register: final_status
environment:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
- name: Show cluster status
debug:
var: final_status.stdout_lines

View file

@ -0,0 +1 @@
k3s_token: "K1006c65c6d4e2ab336de2a35dc7c5e026895fa439ce083fe5b0155678c72dd8a4e::server:c60eed71d179e902fbce39ad6866fb07"