{name.title()} Insights & Guides
Expert {name} articles, tutorials, and deep dives. Updated daily.
🚀 First article coming soon...
Coming Soon
Fresh {name} content will be published here automatically every day.
""" Deploy all 8 auto-publisher sites to Proxmox LXC containers. Creates CTs, installs nginx, configures cloudflared tunnels, and pushes code. """ import os import sys import time import json import subprocess from pathlib import Path PROXMOX = "root@10.30.20.85" PROXMOX_PASS = "czapiewski" STORAGE = "poolmaster" BRIDGE = "vmbr0" GATEWAY = "10.30.20.1" TEMPLATE = "local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst" DOMAIN = "thetempleofdoom.com" GITEA_HOST = "10.30.20.149:3000" GITEA_TOKEN = "dec25a837e0d85573706c4d5d608c2df215f3320" # Site definitions: name → (ct_id, ip) SITES = { "ai": (135, "10.30.20.240"), "tech": (136, "10.30.20.241"), "science": (137, "10.30.20.242"), "crypto": (138, "10.30.20.243"), "linux": (139, "10.30.20.244"), "gaming": (140, "10.30.20.246"), "diy": (141, "10.30.20.247"), "guides": (142, "10.30.20.248"), } def ssh(cmd: str, timeout: int = 30) -> str: """Run command on Proxmox host.""" result = subprocess.run( ["ssh", "-o", "StrictHostKeyChecking=accept-new", PROXMOX, cmd], capture_output=True, text=True, timeout=timeout ) return result.stdout.strip() def pct_exec(vmid: int, cmd: str, timeout: int = 30) -> str: """Run command inside a CT.""" return ssh(f"pct exec {vmid} -- bash -c '{cmd}'", timeout=timeout) def create_ct(name: str, vmid: int, ip: str) -> bool: """Create a Proxmox LXC container.""" print(f" Creating CT {vmid} ({name}) at {ip}...") # Check if CT already exists existing = ssh(f"pct list | grep '^{vmid} '") if existing: print(f" CT {vmid} already exists — skipping creation") return True cmd = ( f"pct create {vmid} {TEMPLATE} " f"--hostname {name}-publisher " f"--storage {STORAGE} " f"--memory 2048 --swap 512 --cores 2 " f"--net0 name=eth0,bridge={BRIDGE},ip={ip}/24,gw={GATEWAY} " f"--unprivileged 1 --password {PROXMOX_PASS} " f"--features nesting=1 --onboot 1" ) out = ssh(cmd) print(f" Created: {out}") # Start it ssh(f"pct start {vmid}") time.sleep(8) # Get assigned IP ip_check = ssh(f"pct exec {vmid} -- hostname -I") print(f" IP: {ip_check}") return True def setup_ct(name: str, vmid: int, ip: str) -> bool: """Install nginx and configure the site on a CT.""" print(f" Setting up CT {vmid} ({name})...") # Update packages pct_exec(vmid, "apt update -qq && apt install -y -qq nginx curl python3 python3-pip git 2>&1 | tail -5", timeout=120) # Create web root pct_exec(vmid, "mkdir -p /var/www/html/articles /var/www/html/assets/images") # Copy shared assets local_assets = Path(__file__).resolve().parent.parent / "shared" / "assets" if local_assets.exists(): # Create tarball of shared assets subprocess.run( f"cd {local_assets.parent} && tar czf /tmp/shared_assets.tar.gz assets/", shell=True, capture_output=True ) subprocess.run( f"scp /tmp/shared_assets.tar.gz {PROXMOX}:/tmp/shared_assets.tar.gz", shell=True, capture_output=True ) ssh(f"pct push {vmid} /tmp/shared_assets.tar.gz /tmp/shared_assets.tar.gz") pct_exec(vmid, "cd /var/www/html && tar xzf /tmp/shared_assets.tar.gz") # Create nginx config nginx_conf = f"""server {{ listen 80 default_server; server_name {name}.{DOMAIN}; root /var/www/html; index index.html; location / {{ try_files $uri $uri/ $uri.html =404; }} location /assets/ {{ expires 30d; add_header Cache-Control "public, immutable"; }} location /rss.xml {{ add_header Content-Type "application/rss+xml"; }} location /sitemap.xml {{ add_header Content-Type "application/xml"; }} # Gzip gzip on; gzip_types text/plain text/html text/css application/json application/javascript text/xml application/xml; gzip_min_length 1000; }}""" # Write nginx config via base64 to avoid quoting issues import base64 encoded = base64.b64encode(nginx_conf.encode()).decode() pct_exec(vmid, f"echo '{encoded}' | base64 -d > /etc/nginx/sites-available/default") pct_exec(vmid, "rm -f /etc/nginx/sites-enabled/default && " "ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default") # Verify and restart nginx result = pct_exec(vmid, "nginx -t 2>&1 && systemctl restart nginx && echo 'NGINX_OK'") print(f" Nginx: {'OK' if 'NGINX_OK' in result else 'FAILED'}") # Create a simple health endpoint pct_exec(vmid, f"echo '
Auto Publisher — coming soon
' > /var/www/html/index.html") return True def create_gitea_repo(name: str) -> bool: """Create a Gitea repository for a site.""" print(f" Creating Gitea repo: {name}-publisher...") # Check if repo already exists result = subprocess.run( ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", f"http://{GITEA_HOST}/api/v1/repos/drjones/{name}-publisher"], capture_output=True, text=True ) if result.stdout.strip() == "200": print(f" Repo {name}-publisher already exists") return True # Create via API result = subprocess.run( ["curl", "-s", "-X", "POST", f"http://{GITEA_HOST}/api/v1/user/repos", "-H", "Content-Type: application/json", "-H", f"Authorization: token {GITEA_TOKEN}", "-d", json.dumps({ "name": f"{name}-publisher", "description": f"Auto Publisher site: {name}.thetempleofdoom.com", "private": False, "auto_init": True, })], capture_output=True, text=True ) if "200" in result.stdout or "201" in result.stdout or "409" in result.stdout: print(f" Repo {name}-publisher created") return True else: print(f" Gitea API failed: {result.stdout[:200]}") # Fallback: create via filesystem + SQLite ssh(f"pct exec 525 -- mkdir -p /var/lib/gitea/data/gitea-repositories/drjones/{name}-publisher.git") ssh(f"pct exec 525 -- git init --bare /var/lib/gitea/data/gitea-repositories/drjones/{name}-publisher.git") ssh(f"pct exec 525 -- chown -R gitea:gitea /var/lib/gitea/data/gitea-repositories/drjones/{name}-publisher.git") return True def verify_site(name: str, ip: str) -> bool: """Verify a site is serving content.""" try: result = subprocess.run( ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", f"http://{ip}:80/"], capture_output=True, text=True, timeout=5 ) code = result.stdout.strip() print(f" HTTP status: {code}") return code == "200" except Exception as e: print(f" Verify failed: {e}") return False def deploy_site_code(name: str, vmid: int) -> bool: """Push site code to CT and to Gitea.""" print(f" Pushing code to CT {vmid}...") site_dir = Path(__file__).resolve().parent.parent / "sites" / name # Build a placeholder site if directory is empty if not site_dir.exists() or not list(site_dir.glob("*.html")): # Create placeholder site_dir.mkdir(parents=True, exist_ok=True) (site_dir / "articles").mkdir(exist_ok=True) placeholder = f"""Expert {name} articles, tutorials, and deep dives. Updated daily.
🚀 First article coming soon...
Fresh {name} content will be published here automatically every day.