My Debian Home Server

This page documents the setup and architecture of my personal server hosting isaacstephens.com.

[ System Architecture ]

Internet → Cloudflare Tunnel → Nginx → Gunicorn → Flask App → MariaDB

Traffic flows securely from Cloudflare to my server, is reverse-proxied through Nginx, and served dynamically via Flask and Gunicorn.

[ Project Structure ]


/isaacstephens.com/
├── dependencies.sh
├── LICENSE
├── main.py
├── README.md
├── venv/
├── website/
│   ├── auth.py
│   ├── .env files (contain credentials, NOT committed lol)
│   ├── __init__.py
│   ├── models.py
│   ├── static/
│   └── templates/
└── other project files
    

[ Python Environment ]

Python Interpreter: venv/bin/python

Python Version: 3.13.5

Installed Packages:

[ Nginx Configuration ]


server {
    listen 8080;
    server_name isaacstephens.com www.isaacstephens.com;

    access_log /var/log/nginx/isaac_access.log;
    error_log /var/log/nginx/isaac_error.log;

    if ($host != "isaacstephens.com") {
        return 301 https://isaacstephens.com$request_uri;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_redirect off;
    }

    location /static/ {
        alias /home/isaac/local_isaacstephens/isaacstephens.com/website/static/;
        expires 30d;
        add_header Cache-Control "public";
    }
}
    

[ Gunicorn Setup ]

Gunicorn runs the Flask app on 127.0.0.1:8000 and is managed by systemd for auto-start and stability.


[Unit]
Description=Gunicorn instance to serve Flask app
After=network.target

[Service]
User=isaac
Group=www-data
WorkingDirectory=/path/to/isaacstephens.com
Environment="PATH=/path/to/isaacstephens.com/venv/bin"
ExecStart=/path/to/isaacstephens.com/venv/bin/gunicorn --workers 4 --bind 127.0.0.1:8000 main:app

[Install]
WantedBy=multi-user.target
    

[ Cloudflare Tunnel ]

Cloudflare Tunnel securely exposes my local server to the internet, routing HTTPS traffic to Nginx.


tunnel: your_tunnel_name
credentials-file: /path/to/credentials.json

ingress:
  - hostname: isaacstephens.com
    service: http://localhost:8080
  - hostname: www.isaacstephens.com
    service: http://localhost:8080
  - service: http_status:404
    

[ Tech Stack ]

ComponentDescription
FlaskPython web framework
GunicornWSGI HTTP server for production
NginxReverse proxy + static file handler
MariaDBBackend Database
Cloudflare TunnelSecure remote access to local server

[ Conclusion ]

This architecture provides a secure, performant personal website hosted entirely on a home server, with traffic flowing through Cloudflare, managed by Nginx, and served dynamically via Flask and Gunicorn.

Author: Isaac Stephens