This page documents the setup and architecture of my personal server hosting isaacstephens.com.
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.
/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 Interpreter: venv/bin/python
Python Version: 3.13.5
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 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 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
| Component | Description |
|---|---|
| Flask | Python web framework |
| Gunicorn | WSGI HTTP server for production |
| Nginx | Reverse proxy + static file handler |
| MariaDB | Backend Database |
| Cloudflare Tunnel | Secure remote access to local server |
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