Production-grade deployment
Run Flask Permanently on Ubuntu
Gunicorn + systemd ยท Auto-restart ยท Survives reboots & disconnections
Standard Architecture (Production)
๐ Internet
โ๏ธ Nginx (80/443)
๐ Gunicorn
๐ฆ Flask App
๐ฌ MySQL
Minimal: Internet โ Gunicorn โ Flask โ MySQL
Explanation: Nginx acts as a reverse proxy (handles static files, SSL, load balancing). Gunicorn is the WSGI server that runs your Flask code. systemd ensures the process stays alive even after reboots or crashes.
1Connect to your Ubuntu server
ssh ubuntu@SERVER_IP
Explanation: The
ssh command securely connects to your remote server. Replace SERVER_IP with your server's public IP address. Example: ssh ubuntu@115.178.xxx.xxx. You will be prompted for a password or key.2Navigate to your application directory
cd ~/upload/regapicta
Explanation:
cd changes the current directory to your Flask project folder. ~/upload/regapicta is an example path; adjust it to where your app lives. Run ls -la to verify that app.py, venv/, and other files exist.3Activate the Python virtual environment
source venv/bin/activate
Explanation: The virtual environment isolates project dependencies.
source runs the activate script, changing your prompt to (venv) user@server:.... All subsequent pip install commands will affect only this project.4Install Gunicorn
pip install gunicorn
gunicorn --version
Explanation: Gunicorn is a production-grade WSGI HTTP server for Flask.
pip install gunicorn installs it inside the active virtual environment. gunicorn --version confirms successful installation.5Test the application with Gunicorn
Assume your main Flask file is app.py containing app = Flask(__name__)
gunicorn -w 4 -b 0.0.0.0:5000 app:app
| Parameter | Meaning |
|---|---|
-w 4 | Number of worker processes (4) |
-b 0.0.0.0:5000 | Bind to all network interfaces on port 5000 |
app:app | Import app object from app.py file |
Explanation: This starts Gunicorn with 4 worker processes to handle concurrent requests.
0.0.0.0 makes the server accessible from outside, port 5000. app:app means "from file app.py, import the variable app". Test by opening http://SERVER_IP:5000 in a browser. Press Ctrl+C to stop.6Browser access test
http://SERVER_IP:5000
Explanation: If your Flask page loads, Gunicorn is correctly configured. Stop it with Ctrl+C before proceeding to systemd setup.
7Create a systemd service
sudo nano /etc/systemd/system/regapicta.service
Insert the following configuration:
[Unit]
Description=Regapicta Flask Application
After=network.target
[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/upload/regapicta
ExecStart=/home/ubuntu/upload/regapicta/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 app:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Explanation of each section:
โข
โข
โข
โข
โข
Save with CTRL+O, ENTER, then CTRL+X.
โข
[Unit]: Metadata; After=network.target ensures the service starts after the network is ready.โข
[Service]: Defines the user/group, working directory, and the exact command to run Gunicorn (using the full path to the venv binary).โข
Restart=always: systemd will automatically restart the app if it crashes.โข
RestartSec=5: Wait 5 seconds before restarting.โข
[Install]: WantedBy=multi-user.target means the service will start automatically at boot.Save with CTRL+O, ENTER, then CTRL+X.
8Reload systemd
sudo systemctl daemon-reload
Explanation: This command tells systemd to reload all unit files. It is required after creating or modifying a
.service file so that systemd recognizes the new configuration.9Enable automatic startup on boot
sudo systemctl enable regapicta
Explanation:
enable creates a symbolic link so the service starts automatically every time the server boots. Without this, you would need to manually start it after each reboot.10Start the service
sudo systemctl start regapicta
Explanation: Starts the service immediately. Use
start whenever you want to run the service after it has been stopped.11Check service status and logs
sudo systemctl status regapicta
sudo journalctl -u regapicta -f
sudo journalctl -u regapicta -n 100
Explanation:
status shows whether the service is active (running). journalctl -u name -f follows live logs (like tail -f). -n 100 displays the last 100 log lines. Logs are essential for debugging application errors.12Daily operations
sudo systemctl stop regapicta # stop the service
sudo systemctl start regapicta # start the service
sudo systemctl restart regapicta # restart (after code changes)
sudo systemctl status regapicta # check health
Explanation:
stop halts the application, start launches it, restart is a convenient stop+start sequence used after updating Flask files. No need to reboot the server.13Deploy code changes
cd ~/upload/regapicta
git pull # or edit files manually
sudo systemctl restart regapicta
Explanation: After modifying your Flask application (routes, models, templates), you must restart Gunicorn to load the new code. systemd will stop the old workers and start fresh ones with the updated version.
14Verify it works without SSH
Disconnect: exit or simply close your laptop. Then try accessing http://SERVER_IP:5000 from a browser.
Explanation: Because the service is managed by systemd, the application continues running as a background daemon even after the SSH session ends. systemd keeps Gunicorn alive independently.
15Verify automatic startup after reboot
sudo reboot
Explanation: After the server reboots, reconnect via SSH and run
sudo systemctl status regapicta. You will see active (running) without any manual intervention. This proves that enable successfully configured the service to start at boot.โ๏ธStartup process: Before vs After systemd
BEFORE systemd
SSH โ activate venv โ python app.py โ site works. If SSH disconnects โ app stops โ
AFTER systemd
Ubuntu boots โ systemd reads regapicta.service โ executes Gunicorn โ Flask becomes available automatically โจ
Technical explanation: systemd is the modern init system on Ubuntu. At boot, it parses .service files and launches the process defined in
ExecStart. With Restart=always, if the process dies (crash), systemd restarts it within 5 seconds.๐Recommended production setup
Add Nginx as a reverse proxy + Let's Encrypt SSL. Final architecture:
๐ Internet โ ๐ก๏ธ Nginx (80/443) โ ๐ Gunicorn (5000) โ ๐ Flask App โ ๐ฌ MySQL
Explanation: Nginx receives client requests (ports 80/443) and forwards them to Gunicorn on localhost:5000. Nginx efficiently serves static files and manages SSL certificates (HTTPS), making it the standard production reverse proxy for Flask.
๐Useful systemd commands
sudo systemctl daemon-reload # after editing .service file
sudo systemctl restart regapicta # restart the application
sudo journalctl -u regapicta -f # follow live logs
sudo systemctl is-enabled regapicta # check if service starts at boot
Explanation:
is-enabled returns enabled if the service is set to auto-start. restart is commonly used after git pull or file updates to apply changes immediately.
Comments