Add Proxmox host role, WireGuard VPN, and public Gitea via Traefik HTTPS
Ansible Lint / lint (push) Successful in 4s

Proxmox host role:
- Admin user setup, SSH hardening (port 2222, no root login)
- claude-code SFTP chroot user
- Unattended upgrades, DuckDNS dynamic DNS updater (vault-encrypted token)
- WireGuard VPN server (10.10.10.0/24) with Fedora client registered
- Proxmox firewall management via pvesh API (idempotent Python script)

Public Gitea exposure:
- Traefik: add HTTPS entrypoint, Let's Encrypt ACME (HTTP-01), StripPrefix
  middleware for /git subpath, HTTP→HTTPS redirect
- Gitea ROOT_URL updated to https://adyrem.duckdns.org/git/
- Pi-hole split DNS: adyrem.duckdns.org → 10.10.1.3 for internal hairpin bypass

SSH config fixes:
- StrictHostKeyChecking no → accept-new across all hosts
- Proxmox jump host: port 2222, user adyrem (root login disabled)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Adyrem
2026-05-16 04:06:56 +02:00
parent e888560175
commit 7ba749c620
26 changed files with 644 additions and 11 deletions
+4
View File
@@ -4,11 +4,15 @@ traefik_http_port: 80
traefik_https_port: 443
traefik_dashboard_port: 8080
traefik_log_level: "INFO"
traefik_acme_email: "fanfohcd@gmail.com"
traefik_services:
- name: gitea
host: "gitea.homelab"
backend: "http://10.10.1.125:3000"
public_host: "adyrem.duckdns.org"
public_path: "/git"
strip_prefix: "/git"
- name: grafana
host: "grafana.homelab"
backend: "http://10.10.1.137:3000"
+9
View File
@@ -26,6 +26,15 @@
- /etc/traefik
- /etc/traefik/conf.d
- name: Create acme.json for Let's Encrypt certificate storage
ansible.builtin.copy:
dest: /etc/traefik/acme.json
content: ""
owner: traefik
group: traefik
mode: "0600"
force: false
- name: Check installed Traefik version
ansible.builtin.command:
cmd: /usr/local/bin/traefik version
+35 -1
View File
@@ -1,11 +1,45 @@
http:
routers:
{% for svc in traefik_services %}
{{ svc.name }}:
{{ svc.name }}-internal:
rule: "Host(`{{ svc.host }}`)"
service: {{ svc.name }}
entryPoints:
- web
{% if svc.public_host is defined %}
{{ svc.name }}-public-redirect:
rule: "Host(`{{ svc.public_host }}`){% if svc.public_path is defined %} && PathPrefix(`{{ svc.public_path }}`){% endif %}"
service: {{ svc.name }}
entryPoints:
- web
middlewares:
- redirect-https
{{ svc.name }}-public:
rule: "Host(`{{ svc.public_host }}`){% if svc.public_path is defined %} && PathPrefix(`{{ svc.public_path }}`){% endif %}"
service: {{ svc.name }}
entryPoints:
- websecure
tls:
certResolver: letsencrypt
{% if svc.strip_prefix is defined %}
middlewares:
- {{ svc.name }}-strip-prefix
{% endif %}
{% endif %}
{% endfor %}
middlewares:
redirect-https:
redirectScheme:
scheme: https
permanent: true
{% for svc in traefik_services %}
{% if svc.strip_prefix is defined %}
{{ svc.name }}-strip-prefix:
stripPrefix:
prefixes:
- "{{ svc.strip_prefix }}"
{% endif %}
{% endfor %}
services:
@@ -5,11 +5,21 @@ api:
entryPoints:
web:
address: ":{{ traefik_http_port }}"
websecure:
address: ":{{ traefik_https_port }}"
providers:
file:
directory: /etc/traefik/conf.d
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: {{ traefik_acme_email }}
storage: /etc/traefik/acme.json
httpChallenge:
entryPoint: web
log:
level: {{ traefik_log_level }}