This commit is contained in:
Graham McIntire 2025-10-05 13:12:28 -05:00
parent 8e4a9830bc
commit 7ac6cae23d
No known key found for this signature in database
26 changed files with 481 additions and 100 deletions

View file

@ -129,6 +129,11 @@ tofu plan
### K3s Cluster at 204.110.191.2 ### K3s Cluster at 204.110.191.2
- **Purpose**: Home lab Kubernetes cluster - **Purpose**: Home lab Kubernetes cluster
- **Node1 IPs**:
- Public: 204.110.191.2
- Tailscale: 100.102.235.20
- Internal: 10.0.101.21
- **API Access**: Currently only available on 10.0.101.21:6443 (not on Tailscale)
- **Context**: Use `kubectl config use-context homelab` to access - **Context**: Use `kubectl config use-context homelab` to access
- **Storage**: Longhorn for persistent volumes - **Storage**: Longhorn for persistent volumes
- **Applications**: - **Applications**:
@ -166,5 +171,8 @@ tofu plan
- Do not ever reply with "you're right". Just fix the issue - Do not ever reply with "you're right". Just fix the issue
- Never say you're right, just accept it and move on - Never say you're right, just accept it and move on
### Notes for Claude
- As you learn new things, keep claude.md updated
## Clusters ## Clusters
- k3s cluster at 204.110.191.2 - k3s cluster at 204.110.191.2

View file

@ -42,4 +42,12 @@ base:
ssh_service: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}" ssh_service: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}"
# NTP service name (varies by distribution) # NTP service name (varies by distribution)
ntp_service: "{{ 'ntp' if ansible_os_family == 'Debian' else 'ntpd' }}" ntp_service: "{{ 'ntp' if ansible_os_family == 'Debian' else 'ntpd' }}"
# Network configuration - skip for all hosts
network:
skip: true
nameservers:
- 9.9.9.9
- 149.112.112.112
domain: local

View file

@ -0,0 +1,10 @@
---
# K3s servers group configuration
# Additional packages for K3s servers
k3s_packages:
- open-iscsi # iSCSI support (required for Longhorn volumes)
- dmsetup # Device mapper tools
- nfs-common # NFSv4 client (for RWX volumes)
- jq # JSON processing
- cryptsetup # Encryption support (optional but recommended)

View file

@ -1,7 +1,6 @@
[vntx_servers] [vntx_servers]
#logs.vntx.net #logs.vntx.net
#unimus.vntx.net #unimus.vntx.net
monitor.vntx.net
radius.vntx.net radius.vntx.net
vpn.vntx.net vpn.vntx.net
librenms.vntx.net librenms.vntx.net
@ -10,6 +9,9 @@ ns1.vntx.net
ns2.vntx.net ns2.vntx.net
#ntp.vntx.net #ntp.vntx.net
[monitoring_servers]
monitor.vntx.net
[app_servers] [app_servers]
apps.w5isp.com apps.w5isp.com
@ -17,10 +19,10 @@ apps.w5isp.com
skippy.w5isp.com skippy.w5isp.com
sync.w5isp.com ansible_host=204.110.191.216 sync.w5isp.com ansible_host=204.110.191.216
[proxmox] [k3s_servers]
lab02.w5isp.com node1 # ansible_host=10.0.101.211
lab03.w5isp.com node2 # ansible_host=10.0.101.212
lab04.w5isp.com node3 # ansible_host=10.0.101.213
[tailscale_home] [tailscale_home]
sync.w5isp.com sync.w5isp.com

View file

@ -0,0 +1,47 @@
---
- name: Install k3s on node3 and join cluster
hosts: node3
become: true
vars:
k3s_version: "v1.28.4+k3s1"
k3s_server_url: "https://10.0.101.211:6443" # node1 IP
tasks:
- name: Check if k3s is already installed
stat:
path: /usr/local/bin/k3s
register: k3s_binary
- name: Get k3s token from master (node1)
delegate_to: node1
slurp:
src: /var/lib/rancher/k3s/server/node-token
register: k3s_token
when: not k3s_binary.stat.exists
- name: Install k3s as agent
shell: |
curl -sfL https://get.k3s.io | \
INSTALL_K3S_VERSION="{{ k3s_version }}" \
K3S_URL="{{ k3s_server_url }}" \
K3S_TOKEN="{{ k3s_token.content | b64decode | trim }}" \
sh -
when: not k3s_binary.stat.exists
- name: Wait for node to be ready
delegate_to: node1
shell: kubectl get node {{ inventory_hostname }} -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'
register: node_status
until: node_status.stdout == "True"
retries: 30
delay: 10
when: not k3s_binary.stat.exists
- name: Verify node joined cluster
delegate_to: node1
command: kubectl get nodes
register: cluster_nodes
changed_when: false
- name: Display cluster status
debug:
var: cluster_nodes.stdout_lines

53
ansible/k3s-install.sh Executable file
View file

@ -0,0 +1,53 @@
#!/bin/bash
# Script to install k3s on node3 and join it to the existing cluster
# Configuration
K3S_VERSION="v1.28.4+k3s1"
K3S_SERVER_URL="https://node1:6443"
echo "Installing k3s on node3..."
# First, get the token from node1
echo "Getting k3s token from node1..."
TOKEN=$(ssh graham@node1 "sudo cat /var/lib/rancher/k3s/server/node-token")
if [ -z "$TOKEN" ]; then
echo "Error: Could not get k3s token from node1"
echo "Please make sure:"
echo "1. k3s is installed on node1"
echo "2. node1 is accessible via SSH"
exit 1
fi
echo "Token retrieved successfully"
# Install k3s on node3
echo "Installing k3s on node3..."
ssh graham@node3 "curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_VERSION='${K3S_VERSION}' K3S_URL='${K3S_SERVER_URL}' K3S_TOKEN='${TOKEN}' sh -"
if [ $? -eq 0 ]; then
echo "k3s installed successfully on node3"
# Check if node3 can reach node1
echo "Checking connectivity from node3 to node1..."
ssh graham@node3 "ping -c 1 node1 && curl -k https://node1:6443 --connect-timeout 5 || echo 'Cannot reach node1:6443'"
# Start k3s-agent manually
echo "Starting k3s-agent service..."
ssh graham@node3 "sudo systemctl start k3s-agent"
# Check service status
echo "Checking k3s-agent status..."
ssh graham@node3 "sudo systemctl status k3s-agent --no-pager || sudo journalctl -u k3s-agent -n 50 --no-pager"
# Wait a bit for the node to register
echo "Waiting for node to register with cluster..."
sleep 10
# Check if node joined the cluster
echo "Checking cluster status..."
ssh graham@node1 "sudo kubectl get nodes"
else
echo "Error: Failed to install k3s on node3"
exit 1
fi

View file

@ -0,0 +1,23 @@
---
- name: Install k3s on node3
hosts: node3
become: true
gather_facts: no
vars:
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/ansible
tasks:
- name: Install k3s using direct command
raw: |
if ! command -v k3s &> /dev/null; then
# Get token from node1
TOKEN=$(ssh -o StrictHostKeyChecking=no -i ~/.ssh/ansible ansible@10.0.101.211 "sudo cat /var/lib/rancher/k3s/server/node-token" 2>/dev/null)
if [ -n "$TOKEN" ]; then
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION='v1.28.4+k3s1' K3S_URL='https://10.0.101.211:6443' K3S_TOKEN="$TOKEN" sh -
else
echo "Failed to get token from master"
exit 1
fi
else
echo "k3s already installed"
fi

View file

@ -0,0 +1,30 @@
Manual K3s Installation Steps for node3:
1. First, get the vault password and run:
ansible-playbook install-k3s-node3.yml --ask-vault-pass
OR
2. If you have SSH access to a jump host or direct access to the nodes:
a. SSH to node1 and get the token:
ssh ansible@10.0.101.211
sudo cat /var/lib/rancher/k3s/server/node-token
# Copy this token
b. SSH to node3:
ssh ansible@10.0.101.213
c. Install k3s as an agent:
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION='v1.28.4+k3s1' K3S_URL='https://10.0.101.211:6443' K3S_TOKEN='<PASTE_TOKEN_HERE>' sh -
d. Verify installation:
sudo systemctl status k3s-agent
e. From node1, verify the node joined:
kubectl get nodes
3. Alternative - if you have kubectl configured locally with access to the cluster:
kubectl get nodes
# Should show node3 after installation

View file

@ -227,8 +227,6 @@ sections() {
cat <<EOF cat <<EOF
  northstar networks*  https://nsnw.ca/ 
 support@nsnw.ca · +1 403 808 9371 
--System---------------------------------------------------------------------- --System----------------------------------------------------------------------
$(sections | column -t -s "|") $(sections | column -t -s "|")

View file

@ -7,7 +7,7 @@
update_cache: yes update_cache: yes
state: latest state: latest
cache_valid_time: 3600 cache_valid_time: 3600
when: monitoring.icinga2 | default(True) == True when: "'monitoring_servers' in group_names"
register: icinga2_install register: icinga2_install
tags: tags:
- icinga2_install - icinga2_install
@ -19,7 +19,7 @@
- monitoring-plugins - monitoring-plugins
- nagios-plugins-contrib - nagios-plugins-contrib
state: absent state: absent
when: monitoring.icinga2 | default(True) == False when: "'monitoring_servers' not in group_names"
register: icinga2_uninstall register: icinga2_uninstall
tags: tags:
- icinga2_install - icinga2_install
@ -31,7 +31,7 @@
owner: 'nagios' owner: 'nagios'
group: 'nagios' group: 'nagios'
mode: '0700' mode: '0700'
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
tags: tags:
- icinga2_cert_dir - icinga2_cert_dir
@ -41,25 +41,25 @@
dest: "{{ base.monitoring.cert_dir }}/ca.crt" dest: "{{ base.monitoring.cert_dir }}/ca.crt"
owner: 'nagios' owner: 'nagios'
group: 'nagios' group: 'nagios'
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: check for trusted master certificate - name: check for trusted master certificate
stat: stat:
path: "{{ base.monitoring.cert_dir }}/trusted-master.crt }}" path: "{{ base.monitoring.cert_dir }}/trusted-master.crt }}"
register: trusted_master_cert register: trusted_master_cert
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: check trusted master certificate hash - name: check trusted master certificate hash
shell: shell:
cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/trusted-master.crt -noout -hash" cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/trusted-master.crt -noout -hash"
register: trusted_master_cert_hash register: trusted_master_cert_hash
when: monitoring.icinga2 | default(True) == True and trusted_master_cert.stat.exists when: '"monitoring_servers" in group_names and trusted_master_cert.stat.exists'
- name: delete old certificates - name: delete old certificates
file: file:
path: "{{ item }}" path: "{{ item }}"
state: absent state: absent
when: (monitoring.icinga2 | default(True) == True) and trusted_master_cert.stat.exists and trusted_master_cert_hash.stdout != trusted_master_hash when: "'monitoring_servers' in group_names and trusted_master_cert.stat.exists and trusted_master_cert_hash.stdout != trusted_master_hash"
loop: loop:
- "{{ base.monitoring.cert_dir }}/trusted-master.crt" - "{{ base.monitoring.cert_dir }}/trusted-master.crt"
- "{{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt" - "{{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt"
@ -68,18 +68,18 @@
- name: get trusted master certificate - name: get trusted master certificate
shell: shell:
cmd: "icinga2 pki save-cert --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt --host {{ base.monitoring.server }}" cmd: "icinga2 pki save-cert --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt --host {{ base.monitoring.server }}"
when: (monitoring.icinga2 | default(True) == True) and (not trusted_master_cert.stat.exists or trusted_master_cert_hash.stdout != trusted_master_hash) when: "'monitoring_servers' in group_names and (not trusted_master_cert.stat.exists or trusted_master_cert_hash.stdout != trusted_master_hash)"
- name: check for client certificate - name: check for client certificate
stat: stat:
path: "/var/lib/icinga2/certs/{{ inventory_hostname }}.crt" path: "/var/lib/icinga2/certs/{{ inventory_hostname }}.crt"
register: client_certificate register: client_certificate
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: icinga2 setup - name: icinga2 setup
shell: shell:
cmd: "icinga2 node setup --zone {{ inventory_hostname }} --endpoint {{ base.monitoring.server }} --parent_host {{ base.monitoring.server }} --parent_zone master --cn {{ inventory_hostname }} --accept-config --accept-commands --disable-confd --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt" cmd: "icinga2 node setup --zone {{ inventory_hostname }} --endpoint {{ base.monitoring.server }} --parent_host {{ base.monitoring.server }} --parent_zone master --cn {{ inventory_hostname }} --accept-config --accept-commands --disable-confd --trustedcert {{ base.monitoring.cert_dir }}/trusted-master.crt"
when: (monitoring.icinga2 | default(True) == True) and not client_certificate.stat.exists when: "'monitoring_servers' in group_names and not client_certificate.stat.exists"
register: setup register: setup
- name: zones.conf - name: zones.conf
@ -90,7 +90,7 @@
group: nagios group: nagios
mode: "0644" mode: "0644"
register: zones_config register: zones_config
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: icinga2.conf - name: icinga2.conf
template: template:
@ -100,7 +100,7 @@
group: nagios group: nagios
mode: "0644" mode: "0644"
register: icinga2_config register: icinga2_config
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: checks.conf - name: checks.conf
template: template:
@ -110,17 +110,17 @@
group: nagios group: nagios
mode: "0644" mode: "0644"
register: checks_config register: checks_config
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: check if certificate has been signed - name: check if certificate has been signed
shell: shell:
cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt -noout -issuer_hash -hash | uniq -d | wc -l" cmd: "openssl x509 -in {{ base.monitoring.cert_dir }}/{{ inventory_hostname }}.crt -noout -issuer_hash -hash | uniq -d | wc -l"
register: signed register: signed
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'
- name: restart icinga2 - name: restart icinga2
service: service:
name: icinga2 name: icinga2
state: reloaded state: reloaded
enabled: yes enabled: yes
when: monitoring.icinga2 | default(True) == True when: '"monitoring_servers" in group_names'

View file

@ -0,0 +1,23 @@
---
# K3s server configuration tasks
- name: Install K3s required packages
apt:
name: "{{ k3s_packages }}"
state: present
update_cache: yes
cache_valid_time: 3600
when: "'k3s_servers' in group_names"
tags:
- k3s
- k3s_packages
- name: Enable and start iscsid service
systemd:
name: iscsid
enabled: yes
state: started
when: "'k3s_servers' in group_names"
tags:
- k3s
- k3s_services

View file

@ -1,6 +1,6 @@
- name: Configure MOTD banner update script - name: Configure MOTD banner update script
copy: copy:
src: files/20-banner src: etc/update-motd.d/20-banner
dest: /etc/update-motd.d/20-banner dest: /etc/update-motd.d/20-banner
owner: root owner: root
group: root group: root

View file

@ -123,10 +123,8 @@
group: root group: root
mode: 00644 mode: 00644
vars: vars:
first_network_name: "{{ (network.interfaces | selectattr('network', 'defined') | first).network }}" domain: "{{ network.domain | default('local') }}"
first_network: "{{ networks | selectattr('name', 'eq', first_network_name) | first }}" search_domains: "{{ network.search_domains | default([domain]) }}"
domain: "{{ network.domain | default(first_network.zone) }}" nameservers: "{{ network.nameservers | default(['9.9.9.9', '149.112.112.112']) }}"
search_domains: "{{ [domain] + (first_network.search_domains | default([])) }}"
nameservers: "{{ network.nameservers | default(first_network.nameservers) }}"
tags: tags:
- network_resolv_conf - network_resolv_conf

View file

@ -1,61 +0,0 @@
- name: Install rsyslog
apt:
name: rsyslog
register: syslog_install
tags:
- syslog_install
- name: Add rsyslog.conf (Debian)
template:
src: templates/etc/rsyslog.conf.debian.j2
dest: /etc/rsyslog.conf
owner: root
group: root
mode: 0644
vars:
server: "{{ syslog.server | default(base.syslog.server) }}"
when: ansible_facts['os_family']|lower == 'debian'
register: syslog_config
tags:
- syslog_config
# - name: Add rsyslog.conf (Ubuntu)
# tags: rsyslog
# when: ansible_facts['os_family']|lower == 'ubuntu'
# template:
# src: templates/etc/rsyslog.conf.ubuntu
# dest: /etc/rsyslog.conf
# owner: root
# group: root
# mode: 0644
#
# - name: Add rsyslog.d/20-ufw.conf (Ubuntu)
# tags: rsyslog
# when: ansible_facts['os_family']|lower == 'ubuntu'
# copy:
# backup: yes
# src: files/etc/rsyslog.d/20-ufw.conf.ubuntu
# dest: /etc/rsyslog.d/20-ufw.ubuntu
# owner: root
# group: root
# mode: 0644
#
# - name: Add rsyslog.d/50-default.conf (Ubuntu)
# tags: rsyslog
# when: ansible_facts['os_family']|lower == 'ubuntu'
# copy:
# backup: yes
# src: files/etc/rsyslog.d/50-default.conf.ubuntu
# dest: /etc/rsyslog.d/50-default.ubuntu
# owner: root
# group: root
# mode: 0644
- name: reload rsyslog
systemd:
name: rsyslog
state: restarted
enabled: yes
when: syslog_install.changed or syslog_config.changed
tags:
- syslog_reload

View file

@ -23,10 +23,10 @@
- network - network
- tailscale - tailscale
- import_tasks: debian/syslog.yml - import_tasks: debian/k3s.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- syslog - k3s
- import_tasks: debian/icinga2.yml - import_tasks: debian/icinga2.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"

View file

@ -0,0 +1,40 @@
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
{% if interfaces | length > 0 %}
# Network interfaces
{% for interface in interfaces %}
{% if interface.auto | default(true) %}
auto {{ interface.name }}
{% endif %}
{% if interface.method is defined %}
iface {{ interface.name }} {{ interface.family | default('inet') }} {{ interface.method }}
{% if interface.address is defined %}
address {{ interface.address }}
{% endif %}
{% if interface.netmask is defined %}
netmask {{ interface.netmask }}
{% endif %}
{% if interface.gateway is defined %}
gateway {{ interface.gateway }}
{% endif %}
{% if interface.bridge_ports is defined %}
bridge_ports {{ interface.bridge_ports | join(' ') }}
{% endif %}
{% if interface.bridge_stp is defined %}
bridge_stp {{ interface.bridge_stp }}
{% endif %}
{% if interface.bridge_fd is defined %}
bridge_fd {{ interface.bridge_fd }}
{% endif %}
{% endif %}
{% endfor %}
{% else %}
# Include files from /etc/network/interfaces.d:
source /etc/network/interfaces.d/*
{% endif %}

View file

@ -0,0 +1,16 @@
# Generated by Ansible
# Do not edit this file manually
{% if domain is defined %}
domain {{ domain }}
{% endif %}
{% if search_domains is defined and search_domains | length > 0 %}
search {{ search_domains | join(' ') }}
{% endif %}
{% if nameservers is defined %}
{% for nameserver in nameservers %}
nameserver {{ nameserver }}
{% endfor %}
{% endif %}

View file

@ -0,0 +1,13 @@
# Managed by Ansible
[Match]
{% if interface.mac is defined %}
MACAddress={{ interface.mac }}
{% else %}
OriginalName={{ interface.name }}
{% endif %}
[Link]
Name={{ interface.name }}
{% if interface.mtu is defined %}
MTUBytes={{ interface.mtu }}
{% endif %}

View file

@ -1,8 +1,8 @@
apiVersion: v1 apiVersion: v1
clusters: clusters:
- cluster: - cluster:
insecure-skip-tls-verify: true certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkakNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTlRnek9EUXdOakV3SGhjTk1qVXdPVEl3TVRZd01UQXhXaGNOTXpVd09URTRNVFl3TVRBeApXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTlRnek9EUXdOakV3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUMUwxRHNza3prWmd5VGVuY1lISjhrdTJkZXF0WmF0VWJzbm1DVFRobHQKSWN1a3VKRkhNTENtZzN3VzdqM3BjRU90Z3Q0TUVUMWV4ZmRpNGt6ZUNiZU9vMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVS9DMkVzSWsxSVlYVm4xWkpvbVVFClorQitHU3d3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnSVlpdHZrMkQyQ0dSWkoybmJHZlhnL1AvVkcyVnNhNmsKT1crNVpGZ1VuTDhDSUVKZFphWWg3M3I3bnN6aGp4Nmk4NXlzVFEydUxHMkdUWllHOHlQanJlaXYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: https://204.110.191.2:6443 server: https://100.102.235.20:6443
name: default name: default
contexts: contexts:
- context: - context:
@ -15,5 +15,5 @@ preferences: {}
users: users:
- name: default - name: default
user: user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrRENDQVRlZ0F3SUJBZ0lJWHliZTEvMDh1N2N3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOelUzTURnMU9EUTRNQjRYRFRJMU1Ea3dOVEUxTWpRd09Gb1hEVEkyTURrdwpOVEUxTWpRd09Gb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOWEs5VndoYWNaT1BjNVQKVGp2bVdCdDJaZmxiWmkzM1pjZk5VWVRTSGUxbzZaMEhvUVhHdDN5V2lrOVdmUGF6OTRYSHZVZXdLSmpOTnJBWgpsYzk2U21HalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVE5CbDhSUGJnRTBFVXRUeGJyUXhyekE0Lzg2VEFLQmdncWhrak9QUVFEQWdOSEFEQkUKQWlBcmUySmNPa0lDbmhZWXptODZCVThEampNdFJZUTE1SWRoamJuenZPZ09WUUlnREtsaHIxL1FKWkMwellaLwoveUt5OEEzTWN4aXRQMEJkdXBvQzhnRDdrQkU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTlRjd09EVTRORGd3SGhjTk1qVXdPVEExTVRVeU5EQTRXaGNOTXpVd09UQXpNVFV5TkRBNApXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTlRjd09EVTRORGd3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUNlZCdUI4UStFblNXOUFZT0N3b0ZsUFcwdzdqUjZlZC9qdTArbVIySDgKVkdnTk1qdXFUalU0a3o0RWhrYmJsaHloVVc5ZE9FWVRJSDM2bVlGUHltaVBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXpRWmZFVDI0Qk5CRkxVOFc2ME1hCjh3T1AvT2t3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQVBja200cHA2anI1aStWcFRLbDNFTU5EWmNoQTZ5eXgKVDA4UCt5eHlieGxyQWlCZWJ6cDFqSDBYbUZKVjcxWjd2dDZFMzlsVTcyTTJJdlM0YW1zUncvd1lqdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJZko4aDRBSlc4MXN3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOelU0TXpnME1EWXhNQjRYRFRJMU1Ea3lNREUyTURFd01Wb1hEVEkyTURreQpNREUyTURFd01Wb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJEZjRwOE1BQ1JGaS9jTnUKa3QxRFoyb0tjVDlMeEM0aGtPeWZBdlJqUVRhQUFBN2Z6L3ZYdFJTd2dkN0JpMjlHMEF2WlViQ201anNoUGRRZwpEdVdMRksyalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVEt2Y3FLMnZyQmM4b1pzay80SkhRWUdSN2ZKVEFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlCZ2M0WDZqSmhBNzRpZ1VTZFNBanc0Yks1d29SVUFXLzFwMkNwaThvbXJnQUloQUxBQ2tBdWU3dmo2aFc0ZwpqNUhZL2VhMWN0RjVjUERycjB4NllsYWpXWDJFCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkakNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTlRnek9EUXdOakV3SGhjTk1qVXdPVEl3TVRZd01UQXhXaGNOTXpVd09URTRNVFl3TVRBeApXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTlRnek9EUXdOakV3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFScjR0a1IzZGUzOEhnTUxlNjBRYURyUjA2SmdCRHNRNng5cXp0dVVpNU8KSVpkekVwVWdCMHB6aUw1YkJ3eFVkVDVHTk5yUEt0OWlNVy9PMi9FQWgxc1pvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXlyM0tpdHI2d1hQS0diSlArQ1IwCkdCa2UzeVV3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnRmMrVVhselRMUWluRzM0bHlzeGdSK2JOTFhFS1RaS2gKbTBpV0dkZUhPRGNDSUNGdXZDdWxLWEx1TjFLNjkrT0dHNnhoUnNyRzAyUmY3TDJsVlZsekp4dDcKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUFPNjA5Q2tBNEl1NXQyRFdMVkhBMHRDTFBZSHlBZ21nQlBrU3V2OElXOUVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFMWNyMVhDRnB4azQ5emxOT08rWllHM1psK1Z0bUxmZGx4ODFSaE5JZDdXanBuUWVoQmNhMwpmSmFLVDFaODlyUDNoY2U5UjdBb21NMDJzQm1WejNwS1lRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5tTDRiZW5hQllDb3FZSGUwU2dWbzVaQ2hrQnNaQVZGOHYwQU5VeE9jOUpvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFTi9pbnd3QUpFV0w5dzI2UzNVTm5hZ3B4UDB2RUxpR1E3SjhDOUdOQk5vQUFEdC9QKzllMQpGTENCM3NHTGIwYlFDOWxSc0tibU95RTkxQ0FPNVlzVXJRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View file

@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
insecure-skip-tls-verify: true
server: https://100.102.235.20:6443
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrRENDQVRlZ0F3SUJBZ0lJWHliZTEvMDh1N2N3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOelUzTURnMU9EUTRNQjRYRFRJMU1Ea3dOVEUxTWpRd09Gb1hEVEkyTURrdwpOVEUxTWpRd09Gb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJOWEs5VndoYWNaT1BjNVQKVGp2bVdCdDJaZmxiWmkzM1pjZk5VWVRTSGUxbzZaMEhvUVhHdDN5V2lrOVdmUGF6OTRYSHZVZXdLSmpOTnJBWgpsYzk2U21HalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVE5CbDhSUGJnRTBFVXRUeGJyUXhyekE0Lzg2VEFLQmdncWhrak9QUVFEQWdOSEFEQkUKQWlBcmUySmNPa0lDbmhZWXptODZCVThEampNdFJZUTE1SWRoamJuenZPZ09WUUlnREtsaHIxL1FKWkMwellaLwoveUt5OEEzTWN4aXRQMEJkdXBvQzhnRDdrQkU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTlRjd09EVTRORGd3SGhjTk1qVXdPVEExTVRVeU5EQTRXaGNOTXpVd09UQXpNVFV5TkRBNApXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTlRjd09EVTRORGd3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUNlZCdUI4UStFblNXOUFZT0N3b0ZsUFcwdzdqUjZlZC9qdTArbVIySDgKVkdnTk1qdXFUalU0a3o0RWhrYmJsaHloVVc5ZE9FWVRJSDM2bVlGUHltaVBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXpRWmZFVDI0Qk5CRkxVOFc2ME1hCjh3T1AvT2t3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUloQVBja200cHA2anI1aStWcFRLbDNFTU5EWmNoQTZ5eXgKVDA4UCt5eHlieGxyQWlCZWJ6cDFqSDBYbUZKVjcxWjd2dDZFMzlsVTcyTTJJdlM0YW1zUncvd1lqdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUFPNjA5Q2tBNEl1NXQyRFdMVkhBMHRDTFBZSHlBZ21nQlBrU3V2OElXOUVvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFMWNyMVhDRnB4azQ5emxOT08rWllHM1psK1Z0bUxmZGx4ODFSaE5JZDdXanBuUWVoQmNhMwpmSmFLVDFaODlyUDNoY2U5UjdBb21NMDJzQm1WejNwS1lRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=

View file

@ -6,13 +6,16 @@ metadata:
namespace: aprs namespace: aprs
data: data:
CALLSIGN: "W5ISP-2" CALLSIGN: "W5ISP-2"
APRS_CALLSIGN: "W5ISP-1"
APRS_SERVER: "dallas.aprs2.net" APRS_SERVER: "dallas.aprs2.net"
APRS_PORT: "10152" APRS_PORT: "10152"
APRS_FILTER: "r/33/-96/1000000000000" APRS_FILTER: "r/33/-96/1000000000000"
APRS_PASSCODE: "15748" APRS_PASSCODE: "15748"
PACKET_RETENTION_DAYS: "7"
CLUSTER_ENABLED: "true"
PHX_SERVER: "true" PHX_SERVER: "true"
MIX_ENV: "prod" MIX_ENV: "prod"
PORT: "4000" PORT: "4000"
POOL_SIZE: "10" POOL_SIZE: "10"
RELEASE_DISTRIBUTION: "name" RELEASE_DISTRIBUTION: "name"
RELEASE_NODE: "aprs" RELEASE_NODE: "aprsme"

View file

@ -73,8 +73,12 @@ spec:
valueFrom: valueFrom:
fieldRef: fieldRef:
fieldPath: status.podIP fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: RELEASE_NAME - name: RELEASE_NAME
value: "aprs@$(POD_IP)" value: "aprsme@$(POD_NAME).aprs-headless.aprs.svc.cluster.local"
livenessProbe: livenessProbe:
httpGet: httpGet:
path: / path: /

View file

@ -50,7 +50,7 @@ data:
INTERNAL_TOKEN = ${FORGEJO_INTERNAL_TOKEN} INTERNAL_TOKEN = ${FORGEJO_INTERNAL_TOKEN}
[service] [service]
DISABLE_REGISTRATION = false DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = false REQUIRE_SIGNIN_VIEW = false
ENABLE_NOTIFY_MAIL = false ENABLE_NOTIFY_MAIL = false
DEFAULT_KEEP_EMAIL_PRIVATE = true DEFAULT_KEEP_EMAIL_PRIVATE = true

View file

@ -5,6 +5,6 @@ metadata:
namespace: git namespace: git
type: Opaque type: Opaque
stringData: stringData:
database-password: "d3hqtvHKzvcovdXtF7t8bq35Ancya90x" database-password: "nJWD2Iv44Y2j4eQSFupjq9fBKX3rI6pg"
secret-key: "a3995159a70c868e5815d6f5b097d4e347ab12b5d16621ec0075694e99cf8751" secret-key: "a3995159a70c868e5815d6f5b097d4e347ab12b5d16621ec0075694e99cf8751"
internal-token: "07715ac60541b6de1f1933a53e518614fc18a07666706c47875d7a8d98015266c1ea8cf3c38719a77842d1bc7b73749006c8079e9e" internal-token: "07715ac60541b6de1f1933a53e518614fc18a07666706c47875d7a8d98015266c1ea8cf3c38719a77842d1bc7b73749006c8079e9e"

View file

@ -0,0 +1,130 @@
apiVersion: v1
kind: Secret
metadata:
name: mariadb-secret
namespace: data
type: Opaque
stringData:
root-password: "TxN9RnbTQw9GarJg5mDvsuW2bFSYot7L"
replication-password: "nXhalxeheXryAy8R6qTJWhCw4P1CtUXu"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mariadb-config
namespace: data
data:
my.cnf: |
[mysqld]
bind-address = 0.0.0.0
default_storage_engine = InnoDB
binlog_format = ROW
innodb_autoinc_lock_mode = 2
innodb_flush_log_at_trx_commit = 0
query_cache_size = 0
query_cache_type = 0
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-data
namespace: data
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb
namespace: data
labels:
app: mariadb
spec:
replicas: 1
selector:
matchLabels:
app: mariadb
template:
metadata:
labels:
app: mariadb
spec:
containers:
- name: mariadb
image: mariadb:11
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: root-password
- name: MYSQL_DATABASE
value: "forgejo"
- name: MYSQL_USER
value: "forgejo"
- name: MYSQL_PASSWORD
value: "nJWD2Iv44Y2j4eQSFupjq9fBKX3rI6pg"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
- name: config
mountPath: /etc/mysql/conf.d
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1000m"
livenessProbe:
exec:
command:
- /bin/bash
- -c
- "mariadb-admin ping -h localhost -u root -p$MYSQL_ROOT_PASSWORD"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command:
- /bin/bash
- -c
- "mariadb-admin ping -h localhost -u root -p$MYSQL_ROOT_PASSWORD"
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
volumes:
- name: data
persistentVolumeClaim:
claimName: mariadb-data
- name: config
configMap:
name: mariadb-config
---
apiVersion: v1
kind: Service
metadata:
name: mariadb
namespace: data
labels:
app: mariadb
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
protocol: TCP
name: mysql
selector:
app: mariadb

View file

@ -0,0 +1,17 @@
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 10.0.101.30-10.0.101.50
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default-pool