5.6 KiB
Guide to get this online
Awesome—here’s 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
-
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 Let’s Encrypt certs itself.
- Option B: keep Proxied (orange cloud) and install a Cloudflare Origin Certificate on Traefik (Full/Strict).
- Name:
-
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 that’s 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
-
Download a Debian 12 template (UI: Datacenter → local → CT Templates → Debian 12)
-
Create an unprivileged LXC (example CTID 201), with:
- CPU/RAM as needed (e.g., 2 vCPU / 2–4 GB RAM)
- Root disk: 8–16 GB is fine
- Network: static IP, e.g.
192.168.88.20/24, GW192.168.88.1 - Features: you don’t need NFS inside; we’ll bind-mount from host.
-
Bind-mount the NAS app dir into the container:
# From the Proxmox host:
pct set 201 -mp0 /mnt/nas/jobs-app,mp=/srv/app
- 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 that’s 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: Let’s 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 Traefik’s static config has:
-
entryPoints.websecure.address=:443 -
(If using Let’s 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:8000from Traefik host should return200. -
curl -I https://jobs.allucanget.bizfrom outside should return200and a valid cert. -
Confirm Cloudflare SSL mode:
- If DNS only: Traefik should have a Let’s 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/appon NAS backed up (snapshot on the NAS).
That’s it. If you want, tell me which option you picked for Cloudflare (DNS only vs proxied), and I’ll give you the exact Traefik static TLS snippet to match.