cleanup(ingress): drop legacy Caddy/cloudflared/netbird-gateway tiers #70

Merged
k.renner merged 1 commits from simplify-ingress-drop-legacy into master 2026-06-27 09:44:22 +00:00
34 changed files with 2 additions and 1702 deletions
-35
View File
@@ -1,35 +0,0 @@
when:
- event: push
path: ".woodpecker/build-caddy.yml"
- event: manual
evaluate: 'PIPELINE == "build-caddy"'
steps:
- name: build
image: gitea.renner.uno/gitea_admin/ci-caddy-builder:2026-05-01
commands:
- xcaddy build v2.11.2
--with github.com/caddy-dns/cloudflare
--with github.com/ss098/certmagic-s3
--with github.com/hslatman/caddy-crowdsec-bouncer/http@v0.10.0
--with github.com/hslatman/caddy-crowdsec-bouncer/appsec@v0.10.0
--with github.com/mholt/caddy-l4
--output caddy
- ./caddy version
- ./caddy list-modules | grep -c layer4
- name: release
image: gitea.renner.uno/gitea_admin/ci-k8s:2026-04-29
environment:
GITEA_TOKEN:
from_secret: gitea_token
commands:
# Delete old asset from 'latest' release, then upload new one
- "RELEASE=$(curl -s -H \"Authorization: token $GITEA_TOKEN\" https://gitea.renner.uno/api/v1/repos/gitea_admin/homelab/releases/tags/latest)"
- "RELEASE_ID=$(echo $RELEASE | jq -r '.id')"
- "echo \"Release ID: $RELEASE_ID\""
# Delete existing caddy asset if present
- "ASSET_ID=$(echo $RELEASE | jq -r '.assets[]? | select(.name==\"caddy\") | .id')"
- "[ -n \"$ASSET_ID\" ] && curl -s -X DELETE -H \"Authorization: token $GITEA_TOKEN\" https://gitea.renner.uno/api/v1/repos/gitea_admin/homelab/releases/$RELEASE_ID/assets/$ASSET_ID || true"
# Upload new binary
- "curl -s -X POST -H \"Authorization: token $GITEA_TOKEN\" -F attachment=@caddy https://gitea.renner.uno/api/v1/repos/gitea_admin/homelab/releases/$RELEASE_ID/assets?name=caddy | jq '{name: .name, size: .size}'"
-20
View File
@@ -67,26 +67,6 @@ steps:
--destination gitea.renner.uno/gitea_admin/ci-tofu:$TAG \
--destination gitea.renner.uno/gitea_admin/ci-tofu:latest
- name: build-caddy-builder
image: gcr.io/kaniko-project/executor:v1.23.2-debug
directory: ci/images/caddy-builder
depends_on: []
environment:
GITEA_USER: gitea_admin
GITEA_TOKEN:
from_secret: gitea_token
commands:
- mkdir -p /kaniko/.docker
- AUTH=$(printf '%s:%s' "$GITEA_USER" "$GITEA_TOKEN" | base64 | tr -d '\n')
- printf '{"auths":{"gitea.renner.uno":{"auth":"%s"}}}' "$AUTH" > /kaniko/.docker/config.json
- TAG=$(date +%Y-%m-%d)
- |
/kaniko/executor \
--context . \
--dockerfile Containerfile \
--destination gitea.renner.uno/gitea_admin/ci-caddy-builder:$TAG \
--destination gitea.renner.uno/gitea_admin/ci-caddy-builder:latest
- name: build-claude
image: gcr.io/kaniko-project/executor:v1.23.2-debug
directory: ci/images/claude
-35
View File
@@ -1,35 +0,0 @@
when:
- event: push
path:
- "ansible/roles/caddy-ha/**"
- "ansible/plays/install-caddy-ha.yml"
- ".woodpecker/deploy-caddy.yml"
- event: manual
evaluate: 'PIPELINE == "deploy-caddy"'
timeout: 30
steps:
- name: deploy-caddy
image: gitea.renner.uno/gitea_admin/ci-ansible:2026-04-29
environment:
ANSIBLE_FORCE_COLOR: "true"
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_ROLES_PATH: "../roles:./roles"
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
VAULT_PASS:
from_secret: vault_pass
PROXMOX_TOKEN_ID:
from_secret: proxmox_token_id
PROXMOX_TOKEN_SECRET:
from_secret: proxmox_token_secret
commands:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- printf "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n" > ~/.ssh/config
- cd ansible
- echo "$VAULT_PASS" > .vault_pass && chmod 600 .vault_pass
- export ANSIBLE_VAULT_PASSWORD_FILE=.vault_pass
- ansible-playbook -i inventory/ plays/install-caddy-ha.yml -v
@@ -1,4 +0,0 @@
---
# NetBird client configuration for Caddy HA servers
# Setup key is stored in vault.yml
netbird_setup_key: "{{ vault_caddy_netbird_setup_key }}"
@@ -1,9 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
37363434633432396531333038633664663632333963646630353239316332646638323364383162
3338306237343739306231613164383064383037616463320a363961313964326438373762666365
35313464333033653130316539356431303063323861333734313766373061323365613431343966
3766636265626530370a643261653134313563663035623164353566653139383832313161386562
62376364336565313739306130336434323638306137326263663030393633333831646562623138
37313937363338393161313964396462346264633339636464663539383034373837376430366237
36626664623762623130316163373933383335396463616161333434303863636330633439376131
62393862393065396238
-18
View File
@@ -1,18 +0,0 @@
- name: Configure Caddy High Availability
hosts: proxmox_caddy_ha
serial: 1
become: true
tasks:
- name: Apply Caddy High Availability Role
import_role:
name: caddy-ha
vars:
caddy_ha_vip: 10.2.45.100
caddy_ha_keepalived_auth_pass: "SecureCaddyHA"
caddy_ha_primary_host: caddy.dmz.renner.uno
caddy_ha_priorities:
"caddy.dmz.renner.uno": 100
"caddy2.dmz.renner.uno": 90
"caddy3.dmz.renner.uno": 80
-7
View File
@@ -1,7 +0,0 @@
---
- name: Setup Cloudflared LXC
hosts: proxmox_cloudflared
remote_user: root
become: true
roles:
- cloudflared-lxc
-25
View File
@@ -1,25 +0,0 @@
---
- name: Deploy CrowdSec on Caddy HA servers
hosts: proxmox_caddy_ha
serial: 1
become: true
vars_files:
- vars/rustfs_vault.yml
- vars/caddy_setup_credentials.yml
- [ "vars/caddy_generated_credentials.yml", "vars/empty.yml" ]
tasks:
- name: Install and configure CrowdSec
import_role:
name: crowdsec
- name: Apply Caddy High Availability Role with CrowdSec
import_role:
name: caddy-ha
vars:
caddy_ha_vip: 10.2.45.100
caddy_ha_keepalived_auth_pass: "SecureCaddyHA"
caddy_ha_primary_host: caddy.srv.renner.uno
crowdsec_enabled: true
crowdsec_lapi_url: "http://127.0.0.1:8080"
crowdsec_appsec_url: "http://127.0.0.1:7422"
-17
View File
@@ -1,17 +0,0 @@
---
# Deploy NetBird Gateway to Homelab LXC
# Usage: ansible-playbook -i inventory/ plays/install-netbird-gateway.yml
#
# Prerequisites:
# - LXC 260 created via OpenTofu
# - NetBird server running at netbird.renner.uno
# - Setup key generated from NetBird management UI
# - Vault secrets configured:
# - netbird_gateway_setup_key
- name: Deploy NetBird Gateway
hosts: netbird-gateway.srv.renner.uno
become: true
roles:
- common
- netbird-gateway
@@ -1,18 +0,0 @@
---
caddy_ha_s3_access_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
62306337353164323163363334613963396563333133313634316164643632646537386463393730
3934363964613331326663363762303833393766353537650a663139623966316362646437653362
62356231623736333735643639326434333737323737623336366433373433643733323463396132
6230626633666137370a316239363837303038633738376531373261303633343635323737323732
6166
caddy_ha_s3_secret_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
35353431396362333634613134643733383562366230303035383563653131383134376238373539
3765623535373439343637373733303531653565663561380a306364303962613265623363623231
31303430646131313737306361343661373238346166386562636361383437376561373161303234
6164313036613065370a393662373466326361396134633434633034616235386366323132373964
37386361373262396438396633613865643235346563396434336330636330643438383638343661
3365333063663835393635306439613137313161343232333565
@@ -1,10 +0,0 @@
$ANSIBLE_VAULT;1.1;AES256
66343132346639356335353436323062303930326233386334653465663837326237643939623132
6431623632316361656564333137323038323034326365370a396262643664396533616139623162
64626635626364383561623964373236316335343633616230353530633933356661326532616666
3639663032636630330a653264623562303433343830663437313239373135643362373864396537
62323733373461336164323864346530386262623764386433326163663561626466666634326234
33356639373364393431373236656537613434323638333033336137306535326133636666373565
66333363316339376131633434373435343139393666623264366463653262346237333564643536
39636335376330383133333062616637656530333366633266663531386537626163646566303637
64653834653439316133323034303764643535353165343635343539613162636635
-37
View File
@@ -1,37 +0,0 @@
---
caddy_ha_primary_host: caddy.dmz.renner.uno
caddy_ha_vip: 10.2.45.100
caddy_ha_keepalived_auth_pass: "SecureCaddyHA"
caddy_ha_keepalived_interface: "{{ ansible_default_ipv4.interface | default('ens18') }}"
# Keepalived priorities per host (higher = more preferred)
caddy_ha_priorities:
"caddy.dmz.renner.uno": 100
"caddy2.dmz.renner.uno": 90
"caddy3.dmz.renner.uno": 80
# RustFS / S3 Storage for Certificates
caddy_ha_s3_endpoint: "s3.renner.uno:9000"
caddy_ha_s3_bucket: "caddy-certificates"
# Default credentials for Caddy (will be overridden by vault or setup script)
# caddy_ha_s3_access_key: ""
# caddy_ha_s3_secret_key: ""
caddy_ha_s3_insecure: true
# Admin credentials for setup (should be loaded from secure vars/vault)
# caddy_ha_s3_admin_access_key: "..."
# caddy_ha_s3_admin_secret_key: "..."
caddy_version: "v2.11.2"
# Caddy Binary Download URL
# Replace 'owner' with the user/org where the caddy-builder repo is located
caddy_ha_caddy_binary_url: "https://git.renner.uno/gitea_admin/homelab/releases/download/latest/caddy"
# CrowdSec Integration
crowdsec_enabled: true
crowdsec_lapi_url: "http://127.0.0.1:8080"
crowdsec_appsec_url: "http://127.0.0.1:7422"
crowdsec_ticker_interval: "15s"
# API key is set per-host from the crowdsec role output
# crowdsec_caddy_api_key: ""
-199
View File
@@ -1,199 +0,0 @@
import boto3
import sys
import os
import json
import subprocess
import requests
from botocore.client import Config
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials
from botocore.exceptions import ClientError
from urllib.parse import urlparse
endpoint = os.environ.get("S3_ENDPOINT")
admin_access_key = os.environ.get("S3_ADMIN_ACCESS_KEY")
admin_secret_key = os.environ.get("S3_ADMIN_SECRET_KEY")
existing_access_key = os.environ.get("S3_EXISTING_ACCESS_KEY")
existing_secret_key = os.environ.get("S3_EXISTING_SECRET_KEY")
bucket_name = os.environ.get("S3_BUCKET")
insecure = os.environ.get("S3_INSECURE", "false").lower() == "true"
vault_output_file = os.environ.get("S3_VAULT_FILE")
target_user = "caddy-ha"
if not endpoint.startswith("http"):
endpoint = f"http://{endpoint}" if insecure else f"https://{endpoint}"
# Security Check: Ensure existing keys are not the admin keys
if existing_access_key and existing_access_key == admin_access_key:
sys.stderr.write("Warning: Provided existing access key matches admin access key. Ignoring to prevent using admin credentials for Caddy.\n")
existing_access_key = None
existing_secret_key = None
# Test existing keys if provided
if existing_access_key and existing_secret_key:
try:
s3_check = boto3.client('s3',
endpoint_url=endpoint,
aws_access_key_id=existing_access_key,
aws_secret_access_key=existing_secret_key,
config=Config(signature_version='s3v4'),
region_name='us-east-1',
verify=not insecure)
s3_check.head_bucket(Bucket=bucket_name)
# If successful, return existing keys
print(json.dumps({
"bucket_created": False,
"access_key": existing_access_key,
"secret_key": existing_secret_key,
"used_existing": True
}))
sys.exit(0)
except Exception as e:
sys.stderr.write(f"Warning: Existing keys invalid or insufficient permissions: {e}. Generating new ones.\n")
# Clients (Admin)
s3 = boto3.client('s3',
endpoint_url=endpoint,
aws_access_key_id=admin_access_key,
aws_secret_access_key=admin_secret_key,
config=Config(signature_version='s3v4'),
region_name='us-east-1',
verify=not insecure)
# RustFS Admin API helper
def rustfs_admin_request(method, path, params=None, data=None):
import hashlib
if params is None:
params = {}
url = f"{endpoint}{path}"
# Calculate Payload Hash
content = data.encode('utf-8') if data else b''
payload_hash = hashlib.sha256(content).hexdigest()
headers = {}
if data:
headers["Content-Type"] = "application/json"
headers["x-amz-content-sha256"] = payload_hash
request = AWSRequest(
method=method,
url=url,
data=data,
params=params,
headers=headers
)
# Sign Request
creds = Credentials(admin_access_key, admin_secret_key)
auth = SigV4Auth(creds, "s3", "us-east-1")
auth.add_auth(request)
# Send Request
response = requests.request(
method=method,
url=request.url,
headers=dict(request.headers),
data=data,
params=params,
verify=not insecure
)
return response
def ensure_bucket():
sys.stderr.write(f"Checking bucket {bucket_name}...\n")
try:
s3.head_bucket(Bucket=bucket_name)
sys.stderr.write(f"Bucket {bucket_name} exists.\n")
except ClientError as e:
error_code = int(e.response['Error']['Code'])
if error_code == 404:
sys.stderr.write(f"Bucket {bucket_name} not found. Creating...\n")
s3.create_bucket(Bucket=bucket_name)
sys.stderr.write(f"Bucket {bucket_name} created.\n")
else:
raise
def generate_random_key(length=20):
import secrets
import string
alphabet = string.ascii_letters + string.digits
return ''.join(secrets.choice(alphabet) for i in range(length))
def ensure_user_and_keys():
# RustFS specific implementation
new_secret_key = generate_random_key(40)
payload = json.dumps({
"secretKey": new_secret_key,
"status": "enabled"
})
# 1. Add User (or update password)
sys.stderr.write(f"Updating user {target_user}...\n")
resp = rustfs_admin_request("PUT", "/rustfs/admin/v3/add-user", params={"accessKey": target_user}, data=payload)
if resp.status_code != 200:
sys.stderr.write(f"Warning: Failed to create/update user via RustFS API: {resp.status_code} {resp.text}\n")
return None, None
# 2. Set Policy (Assign 'readwrite' canned policy)
# Note: Ideally we should create a custom policy restricted to the bucket,
# but for now we use 'readwrite' to ensure functionality.
sys.stderr.write(f"Setting policy for user {target_user}...\n")
resp_policy = rustfs_admin_request("PUT", "/rustfs/admin/v3/set-user-or-group-policy",
params={
"userOrGroup": target_user,
"policyName": "readwrite",
"isGroup": "false"
}
)
if resp_policy.status_code != 200:
sys.stderr.write(f"Warning: Failed to set policy for user: {resp_policy.status_code} {resp_policy.text}\n")
# Proceed anyway? Or fail? The user might not work.
# We'll return keys but warn.
return target_user, new_secret_key
def encrypt_string(value, var_name):
cmd = ["ansible-vault", "encrypt_string", value, "--name", var_name]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"Failed to encrypt string: {result.stderr}")
return result.stdout
try:
ensure_bucket()
ak, sk = ensure_user_and_keys()
if ak and sk and vault_output_file:
# Write to vault file
with open(vault_output_file, "w") as f:
f.write("---\n")
f.write(encrypt_string(ak, "caddy_ha_s3_access_key"))
f.write("\n")
f.write(encrypt_string(sk, "caddy_ha_s3_secret_key"))
f.write("\n")
print(f"Credentials encrypted and written to {vault_output_file}", file=sys.stderr)
elif not ak or not sk:
raise Exception("Failed to generate access keys")
result = {
"bucket_created": True,
"access_key": ak,
"secret_key": sk,
"used_existing": False
}
print(json.dumps(result))
except Exception as e:
import traceback
traceback.print_exc()
sys.stderr.write(f"Error: {e}\n")
sys.exit(1)
-10
View File
@@ -1,10 +0,0 @@
---
- name: Restart Keepalived
service:
name: keepalived
state: restarted
- name: Reload Caddy
service:
name: caddy
state: restarted
-201
View File
@@ -1,201 +0,0 @@
---
- name: Determine HA State
set_fact:
keepalived_state: "{{ 'MASTER' if inventory_hostname == caddy_ha_primary_host else 'BACKUP' }}"
keepalived_priority: "{{ caddy_ha_priorities[inventory_hostname] | default(80) }}"
- name: Install dependencies
apt:
pkg:
- debian-keyring
- debian-archive-keyring
- apt-transport-https
- keepalived
- curl
- tar
- libcap2-bin
state: present
update_cache: yes
register: result
- name: Ensure caddy group exists
group:
name: caddy
system: yes
state: present
- name: Ensure caddy user exists
user:
name: caddy
group: caddy
system: yes
home: /var/lib/caddy
shell: /usr/sbin/nologin
create_home: yes
state: present
- name: Download Caddy Custom Binary
get_url:
url: "{{ caddy_ha_caddy_binary_url }}"
dest: /usr/bin/caddy
mode: '0755'
owner: root
group: root
notify: Reload Caddy
register: caddy_download
ignore_errors: true
- name: Build Caddy with xcaddy (Fallback)
when: caddy_download is failed
block:
- name: Install Build Dependencies (git, curl)
apt:
pkg:
- curl
- git
- tar
state: present
update_cache: yes
- name: Download Go
get_url:
url: "https://go.dev/dl/go1.24.0.linux-amd64.tar.gz"
dest: "/tmp/go1.24.0.linux-amd64.tar.gz"
- name: Remove existing Go installation
file:
path: /usr/local/go
state: absent
- name: Extract Go
unarchive:
src: "/tmp/go1.24.0.linux-amd64.tar.gz"
dest: "/usr/local"
remote_src: yes
- name: Link Go binary
file:
src: /usr/local/go/bin/go
dest: /usr/bin/go
state: link
force: yes
- name: Install xcaddy (Add GPG key)
get_url:
url: https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key
dest: /usr/share/keyrings/caddy-xcaddy-archive-keyring.asc
mode: '0644'
- name: De-armor GPG key
shell: cat /usr/share/keyrings/caddy-xcaddy-archive-keyring.asc | gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
args:
creates: /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
- name: Install xcaddy (Add Repository)
copy:
content: "deb [signed-by=/usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/xcaddy/deb/debian any-version main"
dest: /etc/apt/sources.list.d/caddy-xcaddy.list
- name: Install xcaddy
apt:
name: xcaddy
state: present
update_cache: yes
- name: Build Caddy
command:
cmd: >
xcaddy build {{ caddy_version }}
--output /usr/bin/caddy
--with github.com/caddy-dns/cloudflare
--with github.com/ss098/certmagic-s3
--with github.com/hslatman/caddy-crowdsec-bouncer/http@v0.10.0
--with github.com/hslatman/caddy-crowdsec-bouncer/appsec@v0.10.0
environment:
GOCACHE: "/tmp/.gocache"
PATH: "/usr/local/go/bin:{{ ansible_env.PATH }}"
register: xcaddy_build
notify: Reload Caddy
# Compatibility: Allow binding to 80/443 without root
- name: Set capabilities for Caddy
command: setcap cap_net_bind_service=+ep /usr/bin/caddy
when: caddy_download.changed or (xcaddy_build is defined and xcaddy_build.changed)
- name: Create Caddy config directory
file:
path: /etc/caddy
state: directory
owner: caddy
group: caddy
mode: '0755'
- name: Ensure Caddy log directory exists
file:
path: /var/log/caddy
state: directory
owner: caddy
group: caddy
mode: '0755'
- name: Configure Caddyfile
template:
src: Caddyfile.j2
dest: /etc/caddy/Caddyfile
owner: caddy
group: caddy
mode: '0644'
notify: Reload Caddy
- name: Install Systemd Service
template:
src: caddy.service.j2
dest: /etc/systemd/system/caddy.service
owner: root
group: root
mode: '0644'
notify: Reload Caddy
- name: Setup Caddy Dashboard Generator
template:
src: generate_dashboard.py.j2
dest: /usr/local/bin/generate_dashboard.py
mode: '0755'
- name: Setup Dashboard Service
template:
src: caddy-dashboard.service.j2
dest: /etc/systemd/system/caddy-dashboard.service
mode: '0644'
- name: Setup Dashboard Timer
template:
src: caddy-dashboard.timer.j2
dest: /etc/systemd/system/caddy-dashboard.timer
mode: '0644'
- name: Enable Dashboard Timer
systemd:
name: caddy-dashboard.timer
state: started
enabled: yes
daemon_reload: yes
- name: Enable and Start Caddy Service
systemd:
name: caddy
state: started
enabled: yes
daemon_reload: yes
- name: Configure Keepalived
template:
src: keepalived.conf.j2
dest: /etc/keepalived/keepalived.conf
owner: root
group: root
mode: '0644'
notify: Restart Keepalived
vars:
keepalived_vip: "{{ caddy_ha_vip }}"
keepalived_auth_pass: "{{ caddy_ha_keepalived_auth_pass }}"
@@ -1,395 +0,0 @@
# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.
{
# BEGIN ANSIBLE MANAGED BLOCK
# Admin API for metrics - listen on all interfaces for Prometheus scraping
admin :2019
servers {
trusted_proxies static 127.0.0.1 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
metrics
}
# Layer4 TCP proxy — Gitea SSH on port 2222
layer4 {
:2222 {
route {
proxy gitea.srv.renner.uno:22
}
}
}
{% if crowdsec_enabled | default(true) and crowdsec_caddy_api_key is defined %}
# CrowdSec configuration
crowdsec {
api_url {{ crowdsec_lapi_url }}
api_key {{ crowdsec_caddy_api_key }}
ticker_interval {{ crowdsec_ticker_interval }}
{% if crowdsec_appsec_url is defined %}
appsec_url {{ crowdsec_appsec_url }}
{% endif %}
}
# Log configuration for CrowdSec analysis
log {
output file /var/log/caddy/access.log {
roll_size 30MiB
roll_keep 5
}
}
{% endif %}
# END ANSIBLE MANAGED BLOCK
email tls@renner.uno
# acme_dns cloudflare {
# zone_token 8NcEXu8fSEv-gRVnh1kdL_sCh0cRCcUnRLgPGTA0
# api_token 9Oncv6wU-R85y0FmgPnMQHhrANLiO2osRMNdRNeJ
# }
default_sni caddy.renner.uno
}
# BEGIN ANSIBLE MANAGED BLOCK: Error Page Snippet
(custom_error) {
handle_errors {
rewrite * /custom_error.html
file_server {
root /var/www/html/errors
}
}
}
# END ANSIBLE MANAGED BLOCK: Error Page Snippet
{% if crowdsec_enabled | default(true) and crowdsec_caddy_api_key is defined %}
# BEGIN ANSIBLE MANAGED BLOCK: CrowdSec Snippet
(crowdsec_protect) {
crowdsec
{% if crowdsec_appsec_url is defined %}
appsec
{% endif %}
}
# END ANSIBLE MANAGED BLOCK: CrowdSec Snippet
{% endif %}
(cloudflare) {
tls {
dns cloudflare {
zone_token 8NcEXu8fSEv-gRVnh1kdL_sCh0cRCcUnRLgPGTA0
api_token 9Oncv6wU-R85y0FmgPnMQHhrANLiO2osRMNdRNeJ
}
resolvers 1.1.1.1
}
}
(loadbalancer) {
lb_policy ip_hash
#fail_duration 30s
health_interval 15s
health_timeout 10s
}
caddy.nerdcave.eu {
import cloudflare
# Set this path to your site's directory.
root * /usr/share/caddy
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
caddy.renner.uno {
import cloudflare
root * /var/www/caddy-dashboard
file_server
}
# Internal Dashboard Access (Port 80) for Monitoring Script
:80 {
root * /var/www/caddy-dashboard
file_server
}
pve.nerdcave.eu {
import cloudflare
# import cloudflare
redir https://pve.renner.uno{uri} permanent
}
pve.renner.uno {
import cloudflare
# import cloudflare
#import authelia
reverse_proxy {
to https://jupiter.renner.uno:8006 https://neptune.renner.uno:8006 https://saturn.renner.uno:8006
health_port 8006
#dynamic srv srv+https://_pveweb._tcp.nerdcave.eu {
# resolvers 10.2.40.12 10.2.0.11
#}
import loadbalancer
}
}
pbs.renner.uno {
import cloudflare
reverse_proxy https://pbs.obg.renner.uno:8007
}
home.nerdcave.eu {
import cloudflare
log
# import cloudflare
redir https://home.renner.uno{uri} permanent
}
home.renner.uno {
import cloudflare
reverse_proxy http://10.2.30.11:8123 {
flush_interval -1
transport http {
keepalive 30s
keepalive_idle_conns 10
}
}
}
home.internal.renner.uno {
import cloudflare
reverse_proxy http://10.2.30.11:8123 {
flush_interval -1
transport http {
keepalive 30s
keepalive_idle_conns 10
}
}
}
photos.nerdcave.eu {
import cloudflare
redir https://photos.renner.uno{uri} permanent
}
photos.renner.uno {
import cloudflare
# import cloudflare
redir /mo/sharing/mGwOwC3ZW https://immich.renner.uno/share/i8gRTJ6Kj0IczirRP6y-BvKcq3zXUnSIEYdtWjlcRJvDaHjStUgBmdKYeU58xZkzTWE
redir /mo/sharing/4qry70DZG https://immich.renner.uno/share/i8gRTJ6Kj0IczirRP6y-BvKcq3zXUnSIEYdtWjlcRJvDaHjStUgBmdKYeU58xZkzTWE
#reverse_proxy https://immich.renner.uno
redir https://immich.renner.uno{uri} permanent
}
file.nerdcave.eu {
import cloudflare
# import cloudflare
reverse_proxy https://nas.renner.uno:7001
}
file.renner.uno {
import cloudflare
# import cloudflare
reverse_proxy https://nas.renner.uno:7001
}
docs.renner.uno {
import cloudflare
@local {
remote_ip 10.3.0.0/16
#vars {tls_client_subject} ""
}
#@trusted {
# vars {tls_client_issuer} "CN=Renner Home Intermediate CA,O=Renner Home"
#}
#import cloudflare
handle @local {
reverse_proxy http://paperless.srv.renner.uno:8000
}
handle {
route {
# always forward outpost path to actual outpost
reverse_proxy /outpost.goauthentik.io/* http://authentik-app-1.srv.renner.uno:9000 http://authentik-app-2.srv.renner.uno:9000 {
header_up Host {http.reverse_proxy.upstream.hostport}
lb_policy round_robin
}
# forward authentication to outpost
forward_auth http://authentik-app-1.srv.renner.uno:9000 http://authentik-app-2.srv.renner.uno:9000 {
uri /outpost.goauthentik.io/auth/caddy
# capitalization of the headers is important, otherwise they will be empty
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
# trust both authentik HA nodes
trusted_proxies 10.2.40.0/24
}
reverse_proxy http://paperless.srv.renner.uno:8000
}
}
}
influx.renner.uno {
import cloudflare
# import cloudflare
reverse_proxy http://influxdb.srv.renner.uno:8086
}
dash.renner.uno {
import cloudflare
# import cloudflare
reverse_proxy http://grafana.srv.renner.uno:3000
}
media.renner.uno {
import cloudflare
# import cloudflare
#reverse_proxy http://10.2.40.15:8096
reverse_proxy http://nas.renner.uno:8096
}
git.renner.uno {
import cloudflare
# import cloudflare
reverse_proxy http://gitea.srv.renner.uno:3000
}
auth.renner.uno {
import cloudflare
reverse_proxy http://authentik-app-1.srv.renner.uno:9000 http://authentik-app-2.srv.renner.uno:9000 {
lb_policy round_robin
health_uri /-/health/live/
health_interval 10s
}
}
audiobooks.renner.uno {
import cloudflare
reverse_proxy http://audiobookshelf.srv.renner.uno:13378
}
wazuh.renner.uno {
import cloudflare
log {
level info
}
reverse_proxy https://wazuh.srv.renner.uno:443 {
transport http {
tls_insecure_skip_verify
}
}
}
# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile
# BEGIN ANSIBLE MANAGED BLOCK homeassistant-dev
homeassistant-dev.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://10.2.40.121:8123
}
# END ANSIBLE MANAGED BLOCK homeassistant-dev
# BEGIN ANSIBLE MANAGED BLOCK GITEA
gitea.renner.uno {
reverse_proxy gitea.srv.renner.uno:3000
import cloudflare
}
# END ANSIBLE MANAGED BLOCK GITEA
# BEGIN ANSIBLE MANAGED BLOCK IMMICH
immich.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://immich.srv.renner.uno:2283
}
# END ANSIBLE MANAGED BLOCK IMMICH
ical-proxy.renner.uno {
import cloudflare
reverse_proxy http://ical-proxy.srv.renner.uno:8080
}
# BEGIN ANSIBLE MANAGED BLOCK MUSIC-ASSISTANT
music.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://music-assistant.iot.renner.uno:8095
}
# END ANSIBLE MANAGED BLOCK MUSIC-ASSISTANT
# BEGIN ANSIBLE MANAGED BLOCK WIKI
wiki.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://wiki.srv.renner.uno:80
}
# END ANSIBLE MANAGED BLOCK WIKI
# BEGIN ANSIBLE MANAGED BLOCK WOODPECKER
ci.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://woodpecker.srv.renner.uno:8000
}
# END ANSIBLE MANAGED BLOCK WOODPECKER
# BEGIN ANSIBLE MANAGED BLOCK OWNCLOUD
owncloud.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://owncloud.srv.renner.uno:9200
}
# END ANSIBLE MANAGED BLOCK OWNCLOUD
# BEGIN ANSIBLE MANAGED BLOCK ONLYOFFICE
office.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://owncloud.srv.renner.uno:9980 {
header_down X-Frame-Options "ALLOWALL"
header_down -Content-Security-Policy
}
}
# END ANSIBLE MANAGED BLOCK ONLYOFFICE
# BEGIN ANSIBLE MANAGED BLOCK GATUS
status.renner.uno {
import cloudflare
import custom_error
reverse_proxy http://gatus.srv.renner.uno:8080
}
# END ANSIBLE MANAGED BLOCK GATUS
# BEGIN ANSIBLE MANAGED BLOCK KASM
kasm.renner.uno {
import cloudflare
import custom_error
reverse_proxy https://kasm.srv.renner.uno:443 {
transport http {
tls_insecure_skip_verify
keepalive 30s
}
flush_interval -1
}
}
# END ANSIBLE MANAGED BLOCK KASM
@@ -1,12 +0,0 @@
[Unit]
Description=Generate Caddy HA Dashboard
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/bin/generate_dashboard.py
User=root
Group=root
[Install]
WantedBy=multi-user.target
@@ -1,9 +0,0 @@
[Unit]
Description=Run Caddy Dashboard Generator every 5 seconds
[Timer]
OnBootSec=10s
OnUnitActiveSec=5s
[Install]
WantedBy=timers.target
@@ -1,35 +0,0 @@
# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
@@ -1,199 +0,0 @@
#!/usr/bin/env python3
import subprocess
import socket
import datetime
import os
import sys
import ssl
import urllib.request
# Constants
HOSTNAME = socket.gethostname()
VIP_IP = "10.2.45.100" # Adjust if your VIP is different
OUTPUT_FILE = "/var/www/caddy-dashboard/index.html"
NODES = [
{% for host in groups['proxmox_caddy_ha'] %}
{
"name": "{{ hostvars[host].ansible_host }} ({{ host }})",
"host": "{{ hostvars[host].ansible_host }}"
},
{% endfor %}
]
{% raw %}
def check_remote_node_status(host):
"""Checks the status of a remote node by fetching its dashboard."""
try:
# Use HTTP on port 80 to bypass TLS/SNI issues
url = f"http://{host}"
req = urllib.request.Request(url)
with urllib.request.urlopen(req, timeout=1) as response:
html = response.read().decode('utf-8')
if "MASTER (Active Node)" in html:
return "Online (MASTER)"
elif "BACKUP (Standby Node)" in html:
return "Online (BACKUP)"
else:
return "Online"
except Exception:
return "Offline"
def get_service_status(service):
"""Checks if a systemd service is active."""
try:
subprocess.check_call(["systemctl", "is-active", "--quiet", service])
return "Active"
except subprocess.CalledProcessError:
return "Inactive"
except FileNotFoundError:
return "Not Installed"
def get_keepalived_role():
"""Checks if the VIP is present on any interface."""
try:
output = subprocess.check_output(["ip", "addr", "show"]).decode()
if VIP_IP in output:
return "MASTER (Active Node)"
return "BACKUP (Standby Node)"
except Exception:
return "Unknown"
def generate_html():
caddy_status = get_service_status("caddy")
keepalived_status = get_service_status("keepalived")
node_role = get_keepalived_role()
last_updated = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Generate Node Status List
nodes_html = ""
for node in NODES:
status = check_remote_node_status(node["host"])
status_class = "inactive"
if "Online" in status:
status_class = "active"
if "MASTER" in status:
status_class = "master"
elif "BACKUP" in status:
status_class = "backup"
nodes_html += f"""
<div class="item">
<span class="label">{node['name']}</span>
<span class="status {status_class}">{status}</span>
</div>
"""
# CSS classes based on status
role_class = "master" if "MASTER" in node_role else "backup"
caddy_class = "active" if caddy_status == "Active" else "inactive"
keepalived_class = "active" if keepalived_status == "Active" else "inactive"
html_content = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Caddy HA Status - {HOSTNAME}</title>
<meta http-equiv="refresh" content="5">
<style>
body {{
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #1a1a1a;
color: #e0e0e0;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}}
.card {{
background-color: #2d2d2d;
border-radius: 12px;
box-shadow: 0 10px 20px rgba(0,0,0,0.4);
padding: 2rem;
width: 90%;
max-width: 450px;
}}
h1 {{
margin-top: 0;
border-bottom: 2px solid #404040;
padding-bottom: 1rem;
text-align: center;
font-size: 1.8rem;
color: #fff;
}}
.item {{
display: flex;
justify-content: space-between;
align-items: center;
margin: 1.2rem 0;
font-size: 1.1rem;
}}
.label {{
color: #aaa;
font-weight: 500;
}}
.status {{
font-weight: 700;
padding: 0.25rem 0.75rem;
border-radius: 6px;
}}
.active {{ color: #4caf50; background: rgba(76, 175, 80, 0.1); }}
.inactive {{ color: #f44336; background: rgba(244, 67, 54, 0.1); }}
.master {{ color: #4caf50; background: rgba(76, 175, 80, 0.1); border: 1px solid #4caf50; }}
.backup {{ color: #ff9800; background: rgba(255, 152, 0, 0.1); border: 1px solid #ff9800; }}
.footer {{
margin-top: 2rem;
text-align: right;
font-size: 0.8rem;
color: #666;
border-top: 1px solid #404040;
padding-top: 1rem;
}}
</style>
</head>
<body>
<div class="card">
<h1>{HOSTNAME}</h1>
<div class="item">
<span class="label">HA Role</span>
<span class="status {role_class}">{node_role}</span>
</div>
<div class="item">
<span class="label">Caddy Service</span>
<span class="status {caddy_class}">{caddy_status}</span>
</div>
<div class="item">
<span class="label">Keepalived</span>
<span class="status {keepalived_class}">{keepalived_status}</span>
</div>
<h2 style="font-size: 1.2rem; margin-top: 2rem; border-bottom: 1px solid #404040; padding-bottom: 0.5rem; color: #fff; margin-bottom: 1rem;">Cluster Nodes</h2>
{nodes_html}
<div class="footer">
Updated: {last_updated}
</div>
</div>
</body>
</html>
"""
# Ensure directory exists
os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)
with open(OUTPUT_FILE, "w") as f:
f.write(html_content)
if __name__ == "__main__":
try:
generate_html()
except Exception as e:
print(f"Error generating dashboard: {e}", file=sys.stderr)
sys.exit(1)
{% endraw %}
@@ -1,23 +0,0 @@
vrrp_script chk_caddy {
script "/usr/bin/pgrep caddy"
interval 2
weight -50
}
vrrp_instance VI_1 {
state {{ keepalived_state }}
interface {{ ansible_facts["default_ipv4"].interface | default('ens18') }}
virtual_router_id 51
priority {{ keepalived_priority }}
advert_int 1
authentication {
auth_type PASS
auth_pass {{ keepalived_auth_pass | default('42secret') }}
}
virtual_ipaddress {
{{ keepalived_vip }}
}
track_script {
chk_caddy
}
}
@@ -1,2 +0,0 @@
---
cloudflared_token: "{{ vault_cloudflared_token }}"
@@ -1,43 +0,0 @@
---
- name: Install dependencies
apt:
name:
- curl
- lsb-release
state: present
update_cache: yes
- name: Create keyring directory
file:
path: /usr/share/keyrings
state: directory
mode: '0755'
- name: Add Cloudflare GPG key
get_url:
url: https://pkg.cloudflare.com/cloudflare-main.gpg
dest: /usr/share/keyrings/cloudflare-main.gpg
mode: '0644'
- name: Add Cloudflare repository
apt_repository:
repo: "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared {{ ansible_distribution_release | default('bookworm') }} main"
filename: cloudflare
state: present
- name: Install cloudflared
apt:
name: cloudflared
state: present
update_cache: yes
- name: Install cloudflared service
command: cloudflared service install {{ cloudflared_token }}
args:
creates: /etc/systemd/system/cloudflared.service
- name: Enable and start cloudflared service
service:
name: cloudflared
state: started
enabled: yes
@@ -1,12 +0,0 @@
---
# NetBird Gateway Configuration
netbird_server_url: "https://netbird.renner.uno"
netbird_setup_key: "" # Set in vault: netbird_gateway_setup_key
# Routes to advertise to the NetBird network
netbird_routes:
- "10.2.40.0/24" # v40srv - services network
- "10.2.45.0/24" # v42ing - ingress network
# DNS settings for split DNS
netbird_dns_server: "10.2.40.53" # Proxmox DNS VIP
@@ -1,12 +0,0 @@
---
- name: Save iptables rules
ansible.builtin.shell: |
iptables-save > /etc/iptables/rules.v4 || true
ip6tables-save > /etc/iptables/rules.v6 || true
args:
creates: /etc/iptables/rules.v4
- name: Restart netbird
ansible.builtin.service:
name: netbird
state: restarted
@@ -1,82 +0,0 @@
---
- name: Install required packages
ansible.builtin.apt:
name:
- curl
- ca-certificates
- iptables
- gnupg
state: present
update_cache: true
- name: Enable IP forwarding
ansible.posix.sysctl:
name: "{{ item }}"
value: "1"
sysctl_set: true
state: present
reload: true
loop:
- net.ipv4.ip_forward
- net.ipv6.conf.all.forwarding
- name: Add NetBird repository key
ansible.builtin.shell:
cmd: |
curl -sSL https://pkgs.netbird.io/debian/public.key | gpg --dearmor -o /usr/share/keyrings/netbird-archive-keyring.gpg
creates: /usr/share/keyrings/netbird-archive-keyring.gpg
- name: Add NetBird repository
ansible.builtin.apt_repository:
repo: "deb [signed-by=/usr/share/keyrings/netbird-archive-keyring.gpg] https://pkgs.netbird.io/debian stable main"
state: present
filename: netbird
- name: Install NetBird client
ansible.builtin.apt:
name: netbird
state: present
update_cache: true
- name: Check if NetBird is already connected
ansible.builtin.command: netbird status
register: netbird_status
changed_when: false
failed_when: false
- name: Connect NetBird to management server
ansible.builtin.command: >
netbird up
--management-url {{ netbird_server_url }}
--setup-key {{ netbird_gateway_setup_key }}
when: "'Connected' not in netbird_status.stdout"
register: netbird_connect
changed_when: netbird_connect.rc == 0
- name: Enable NetBird service
ansible.builtin.service:
name: netbird
state: started
enabled: true
- name: Configure iptables for NAT (masquerade)
ansible.builtin.iptables:
table: nat
chain: POSTROUTING
source: "100.64.0.0/10"
jump: MASQUERADE
comment: "NetBird NAT for VPN clients"
notify: Save iptables rules
- name: Display gateway status
ansible.builtin.debug:
msg: |
NetBird gateway configured.
Server: {{ netbird_server_url }}
Routes advertised: {{ netbird_routes | join(', ') }}
To add routes in NetBird management:
1. Go to {{ netbird_server_url }}
2. Navigate to Network Routes
3. Add routes for: {{ netbird_routes | join(', ') }}
4. Select this peer as the routing peer
+2 -1
View File
@@ -92,4 +92,5 @@
To create a setup key:
1. Log into https://{{ netbird_server_host }} with your Authentik credentials
2. Go to Setup Keys > Create Setup Key
3. Use the key with the netbird-gateway role
3. Use the key with the netbird-ingress DaemonSet
(kubernetes/infrastructure/netbird-ingress) or the netbird-proxy role
-5
View File
@@ -1,5 +0,0 @@
FROM golang:1.26
ARG XCADDY_VERSION=v0.4.5
RUN go install github.com/caddyserver/xcaddy/cmd/xcaddy@${XCADDY_VERSION}
-5
View File
@@ -28,7 +28,6 @@ locals {
# LXCs
[
"114", # gitea
"117", # cloudflared
"118", # proxmox-dns-1 (jupiter)
"121", # ical-proxy
"130", # authentik-app-1
@@ -42,10 +41,6 @@ locals {
"227", # prometheus
"229", # music-assistant
"231", # woodpecker
"232", # caddy-1
"233", # caddy-2
"234", # caddy-3
"260", # netbird-gateway
"318", # proxmox-dns-3 (neptune)
],
# Woodpecker CI agents (VMIDs 910..)
-43
View File
@@ -1,43 +0,0 @@
# Example: Manage a Cloudflare Tunnel
# 1. Create the Tunnel Resource
# resource "cloudflare_tunnel" "homelab_tunnel" {
# account_id = var.cloudflare_account_id
# name = "homelab-tunnel"
# secret = base64sha256(random_password.tunnel_secret.result)
# }
#
# 2. Generate a random secret for the tunnel
# resource "random_password" "tunnel_secret" {
# length = 32
# special = false
# }
#
# 3. Configure the Tunnel (Ingress Rules)
# resource "cloudflare_tunnel_config" "homelab_config" {
# account_id = var.cloudflare_account_id
# tunnel_id = cloudflare_tunnel.homelab_tunnel.id
#
# config {
# ingress_rule {
# hostname = "gitea.renner.uno"
# service = "http://10.2.40.114:3000"
# origin_request {
# connect_timeout = "1m"
# }
# }
#
# # Catch-all rule (Required)
# ingress_rule {
# service = "http_status:404"
# }
# }
# }
#
# 4. Create DNS Records pointing to the Tunnel
# resource "cloudflare_record" "gitea" {
# zone_id = "your_zone_id_here"
# name = "gitea"
# value = "${cloudflare_tunnel.homelab_tunnel.id}.cfargotunnel.com"
# type = "CNAME"
# proxied = true
# }
-106
View File
@@ -1,106 +0,0 @@
moved {
from = proxmox_lxc.caddy_srv_renner_uno
to = module.caddy_srv_renner_uno.proxmox_lxc.this
}
module "caddy_srv_renner_uno" {
source = "./modules/proxmox_lxc"
target_node = "neptune"
hostname = "caddy.dmz.renner.uno"
vmid = 232
memory = 1024
cores = 1
unprivileged = true
cpuunits = 1024
tags = "caddy_ha,netbird_client"
hagroup = "olymp"
hastate = "stopped"
storage = "local-zfs"
disk_size = "8G"
network_bridge = "v42ing"
# ip_address = "10.2.45.101"
mac_address = "bc:24:11:de:8f:a4"
ssh_public_keys = local.common_ssh_keys
start = false
onboot = false
# All Caddy ingress hostnames retired:
# pve/home/auth/dash dropped in the prior commit (5eb8ad5).
# file.renner.uno: now served by apps/file (ExternalName -> nas:7001).
# dir.renner.uno + caddy.renner.uno: stale (no live backend).
ingress_cnames = []
}
moved {
from = proxmox_lxc.caddy2_srv_renner_uno
to = module.caddy2_srv_renner_uno.proxmox_lxc.this
}
module "caddy2_srv_renner_uno" {
source = "./modules/proxmox_lxc"
target_node = "saturn"
hostname = "caddy2.dmz.renner.uno"
vmid = 233
memory = 1024
cores = 1
unprivileged = true
cpuunits = 1024
tags = "caddy_ha,netbird_client"
hagroup = "olymp"
hastate = "stopped"
storage = "local-zfs"
disk_size = "8G"
network_bridge = "v42ing"
# ip_address = "10.2.45.103"
mac_address = "bc:24:11:85:43:9c"
ssh_public_keys = local.common_ssh_keys
start = false
onboot = false
}
module "caddy3_srv_renner_uno" {
source = "./modules/proxmox_lxc"
target_node = "jupiter"
hostname = "caddy3.dmz.renner.uno"
vmid = 234
memory = 1024
cores = 1
unprivileged = true
cpuunits = 1024
tags = "caddy_ha,netbird_client"
hagroup = "olymp"
hastate = "stopped"
storage = "local-zfs"
disk_size = "8G"
network_bridge = "v42ing"
ssh_public_keys = local.common_ssh_keys
start = false
onboot = false
}
# caddy_vip A record removed: no CNAMEs point at ingress.renner.uno
# anymore (caddy module's ingress_cnames is empty + every per-LXC/VM
# ingress_cnames was emptied in the cleanup pass). Keepalived-managed
# 10.2.45.100 dies with the Caddy LXCs anyway.
# Old authentik.renner.uno CNAME removed - migrated to auth.renner.uno with HA setup
# auth.renner.uno is handled via Caddy reverse proxy to authentik-app-1/2.srv.renner.uno
-34
View File
@@ -1,34 +0,0 @@
moved {
from = proxmox_lxc.lxc["117"]
to = proxmox_lxc.cloudflared_lxc
}
module "cloudflared_lxc" {
source = "./modules/proxmox_lxc"
target_node = "saturn"
hostname = "cloudflared.srv.renner.uno"
vmid = 117
memory = 1024
cores = 1
unprivileged = false
cpuunits = 1024
hagroup = "olymp"
hastate = "started"
storage = "local-zfs"
disk_size = "4G"
network_bridge = "v42ing"
start = false
onboot = false
tags = "cloudflared"
}
moved {
from = proxmox_lxc.cloudflared_lxc
to = module.cloudflared_lxc.proxmox_lxc.this
}
-28
View File
@@ -1,28 +0,0 @@
module "netbird_gateway" {
source = "./modules/proxmox_lxc"
target_node = "jupiter"
hostname = "netbird-gateway.srv.renner.uno"
vmid = 260
memory = 512
cores = 1
unprivileged = true
cpuunits = 1024
hagroup = "olymp"
hastate = "stopped"
storage = "local-zfs"
disk_size = "4G"
network_bridge = "v40srv"
start = false
onboot = false
tags = "netbird,gateway"
description = "NetBird gateway - routes VPN traffic to internal services"
ansible_playbook = "plays/install-netbird-gateway.yml"
}
-11
View File
@@ -1,11 +0,0 @@
variable "cloudflare_api_token" {
type = string
description = "The Cloudflare API Token"
sensitive = true
}
variable "cloudflare_account_id" {
type = string
description = "The Cloudflare Account ID"
sensitive = true
}