Files
jobs/online.md
georg.sinn-schirwitz 23a67d7fe1 initial project commit
2025-08-29 15:07:58 +02:00

5.6 KiB
Raw Blame History

Guide to get this online

Awesome—heres a concise, battle-tested set of steps to get your Flask app running behind Traefik on Proxmox, with the code living on your NAS via NFS and exposed as jobs.allucanget.biz.


0) DNS & inbound ports

  1. In Cloudflare, add an A record

    • Name: jobs
    • IPv4: 5.226.148.100
    • Decide one of these:
    • Option A (simpler): set to DNS only (grey cloud). Traefik will get Lets Encrypt certs itself.
    • Option B: keep Proxied (orange cloud) and install a Cloudflare Origin Certificate on Traefik (Full/Strict).
  2. Ensure your router/NAT forwards 80/tcp and 443/tcp from WAN to your Traefik box at 192.168.88.10.


1) Mount the NAS on the Proxmox host (then bind into the container)

This avoids NFS-in-container headaches and makes the directory accessible outside the LXC too.

On the Proxmox host (not inside a container):

# Create a mount point for the NAS share
sudo mkdir -p /mnt/nas

# Install NFS client (Debian-based Proxmox)
sudo apt update && sudo apt install -y nfs-common

# (Optional) test mount once
sudo mount -t nfs 192.168.88.9:/mnt/HD/HD_a2/NASNFS /mnt/nas

# Make it permanent in /etc/fstab (add this line):
echo '192.168.88.9:/mnt/HD/HD_a2/NASNFS  /mnt/nas  nfs  defaults,_netdev  0  0' | sudo tee -a /etc/fstab

# Re-mount from fstab to verify
sudo umount /mnt/nas || true
sudo mount -a

# Create your app directory on the NAS thats visible outside the container too
sudo mkdir -p /mnt/nas/jobs-app
sudo chown -R 1000:1000 /mnt/nas/jobs-app   # or set to whatever UID/GID you want

2) Create the LXC on Proxmox

  1. Download a Debian 12 template (UI: Datacenter → local → CT Templates → Debian 12)

  2. Create an unprivileged LXC (example CTID 201), with:

    • CPU/RAM as needed (e.g., 2 vCPU / 24 GB RAM)
    • Root disk: 816 GB is fine
    • Network: static IP, e.g. 192.168.88.20/24, GW 192.168.88.1
    • Features: you dont need NFS inside; well bind-mount from host.
  3. Bind-mount the NAS app dir into the container:

# From the Proxmox host:
pct set 201 -mp0 /mnt/nas/jobs-app,mp=/srv/app
  1. Start the container:
pct start 201

3) Prepare Python + Gunicorn inside the LXC

# Inside CT 201 (ssh or pct enter 201)
apt update && apt install -y python3-venv python3-pip build-essential

# Your code directory is the NAS mount:
cd /srv/app
python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade pip
pip install flask gunicorn

Minimal Flask app structure (in /srv/app):

/srv/app
├─ app.py
└─ wsgi.py

app.py:

from flask import Flask
app = Flask(__name__)

@app.get("/")
def hello():
    return "Hello from jobs.allucanget.biz!"

wsgi.py:

from app import app

if __name__ == "__main__":
    app.run()

Test locally (inside CT):

. .venv/bin/activate
gunicorn -b 0.0.0.0:8000 wsgi:app
# Visit http://192.168.88.20:8000 from LAN to confirm

Create a systemd service so it starts on boot:

cat >/etc/systemd/system/jobs.service <<'EOF'
[Unit]
Description=Jobs Flask app (gunicorn)
After=network.target

[Service]
User=root
WorkingDirectory=/srv/app
Environment="PATH=/srv/app/.venv/bin"
ExecStart=/srv/app/.venv/bin/gunicorn -b 0.0.0.0:8000 wsgi:app
Restart=always

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now jobs.service
systemctl status jobs.service --no-pager

4) Wire Traefik to the LXC service

Assumptions:

  • Traefik runs at 192.168.88.10
  • You have a file provider mounted, e.g. /etc/traefik/dynamic/

Create a dynamic config file on the Traefik container host (or inside the Traefik container if thats where the file provider lives), e.g. /etc/traefik/dynamic/jobs.yml:

http:
  routers:
    jobs-router:
      rule: "Host(`jobs.allucanget.biz`)"
      entryPoints:
        - websecure
      service: jobs-svc
      tls:
        # Option A: Lets Encrypt (Traefik must be set up with a certResolver in static config)
        certResolver: letsencrypt
        # Option B (Cloudflare proxied + origin cert): omit certResolver and make sure Traefik serves the CF origin cert

  services:
    jobs-svc:
      loadBalancer:
        servers:
          - url: "http://192.168.88.20:8000"

Reload Traefik (or it auto-watches the file). Make sure Traefiks static config has:

  • entryPoints.websecure.address=:443

  • (If using Lets Encrypt) a certResolver (HTTP-01 or DNS-01) configured.

    • With Cloudflare “DNS only”, HTTP-01 is easiest.
    • With Cloudflare proxied, use a Cloudflare Origin Certificate on Traefik (Full/Strict) or use DNS-01.

Optional (X-Forwarded-For): behind Cloudflare, trust CF IP ranges in Traefik so client IPs are correct.


5) Quick checks

  • curl -I http://192.168.88.20:8000 from Traefik host should return 200.

  • curl -I https://jobs.allucanget.biz from outside should return 200 and a valid cert.

  • Confirm Cloudflare SSL mode:

    • If DNS only: Traefik should have a Lets Encrypt cert.
    • If proxied: Traefik should present the CF Origin Cert, and Cloudflare set to Full (strict).

6) (Nice to have) Security & hardening

  • Create a non-root user to run the service; adjust User= and file permissions.
  • Set a firewall rule so port 8000 on the LXC is only reachable from 192.168.88.10 (Traefik) and your admin IPs.
  • Keep /srv/app on NAS backed up (snapshot on the NAS).

Thats it. If you want, tell me which option you picked for Cloudflare (DNS only vs proxied), and Ill give you the exact Traefik static TLS snippet to match.