Flet, desktop and web app framework is really useful for Python developers. With only little modifications, your standalone desktop app can be hosted on a web server. In this post you can find how to self-host your Flet app on an Apache web server. This is not covered in the Flet official website.
Contents
Quick introduction of Flet.
Flet is a Python framework to build desktop or web application without having knowledges of GUI or web frontend. Flet is developed based on Flutter mobile app framework developed by Google for the Dart language. You’ll find word “Flutter” when you writing codes and getting errors with Flet. I’m not going to provide more information around Flet or Flutter in this post.
What I’m going to demonstrate in this post
The goal is publish a Flet app on an Apache web server using TCP port based reverse proxy. In my case the web app is only accessible within the LAN. Should you have a publicly accessible Apache server (and admin privileges), you can publish your app to the public. The Flet official webpage Self Hosting introduces the process to publish on an NGINX web server. You can do pretty much the same thing on an Apache web server by following this post.
Environment
- Ubuntu 20.04 LTS
- Apache 2.4.41
High-level steps
- Install requirements on Ubuntu server.
- Build a Python virtual environment and install Flet.
- Prepare a Flet app code.
- Enable Apache modules required for reverse proxy.
- Write an Apache configuration file.
- Write an auto-start configuration file.
Detailed steps
Install requirements on Ubuntu server.
As introduced in the official website, you need to install GStreamer to execute Flet app on a Linux server. Simply follow the steps and install requirements.
sudo apt-get update
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio
Build a Python virtual environment and install Flet.
I use pipenv
as below. Use your preferred virtual env and install Flet. Flet supports Python 3.8 and above.
pipenv --python 3.11
pipenv shell
pip install flet
Prepare a Flet app code.
Just for testing, let’s use a code posted on the official website. To check simple interaction, I copied Counter app and saved as counter.py
. Change the last line as below.
ft.app(target=main, view=None, port=8501)
Quick explanation: view=None
won’t open GUI or web browser window, and port=8501
sets the TCP port to listen to. As long as it does not conflict on your server, any port number works fine. By executing python3 counter.py
, you can see the app on web browser if installed on your web server by opening http://localhost:8501
. Next step is publishing to external access.
Enable Apache modules required for reverse proxy.
At least following 4 modules are required to configure Apache as a reverse proxy. As Flet uses web socket, wstunnel
is also required. Following commands enable modules, load modules and check Apache status respectively.
sudo a2enmod proxy proxy_http proxy_wstunnel headers
sudo systemctl restart apache2
sudo systemctl status apache2
Write an Apache configuration file.
In this example, accessing flet.dev.peddals.com will open the Flet web app. In my environment, access to the subdomain uses always HTTPS as posted separately. So, listening port is 443, and reverse proxy port is 8501 that the Flet app is listening to. Please edit these based on your environment.
Line 13-14 for wss://
may not be required.
<VirtualHost *:443>
ServerName flet.dev.peddals.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/dev.peddals.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/dev.peddals.com/privkey.pem
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /ws ws://localhost:8501/ws
ProxyPassReverse /ws ws://localhost:8501/ws
ProxyPass /ws wss://localhost:8501/ws
ProxyPassReverse /ws wss://localhost:8501/ws
ProxyPass / http://localhost:8501/
ProxyPassReverse / http://localhost:8501/
ErrorLog ${APACHE_LOG_DIR}/flet.error.log
CustomLog ${APACHE_LOG_DIR}/flet.log combined
</VirtualHost>
Load Apache configuration (check syntax, load config, and check status).
sudo apachectl configtest
sudo systemctl reload apache2
sudo systemctl status apache2
Now, let’s execute python3 counter.py
and check if the web app opens from a client PC. If you removed the lines for wss://
and the app kept loading, add them, reload, and try again.
Write an auto-start configuration file.
Let’s follow the Flet official page and write an auto-start configuration file. Below is an example in my server. Save this as fletcounter.service
.
[Unit]
Description=Flet Counter Service
After=network.target
[Service]
User=handsome
Group=handsome
WorkingDirectory=/home/handsome/codes/flet
Environment="PATH=/home/handsome/.local/share/virtualenvs/flet-xuR7EMBP/bin/"
ExecStart=/home/handsome/.local/share/virtualenvs/flet-xuR7EMBP/bin/python3 /home/handsome/codes/flet/counter.py
[Install]
WantedBy=multi-user.target
Modifications:
Description=
as you likeUser=
andGroup=
your own username (whoami
)WorkingDirectory=
is the full path to the directory ofcounter.py
.Environment="PATH=
is the full path to the directory of python3 (output ofwhich python3
up tobin/
)ExecStart=
first arg is full path to Python3 (output ofwhich python3
), and the second arg is the full path to the Flet app.
Lastly, start and enable it as a service by following the official page. The target of the symbolic link (#2) is the file created in the previous step.
cd /etc/systemd/system
sudo ln -s /home/handsome/codes/flet/fletcounter.service
sudo systemctl start fletcounter
sudo systemctl enable fletcounter
sudo systemctl status fletcounter
That’s all. Access your app from a client PC and confirm the counter opens. When possible, reboot your server and confirm the service starts automatically.
Trouble that I encountered.
In my environment, loading of the app kept forever initially. I finally figured out that the reverse proxy settings needed wss://
as well as ws://
(the NGINX config on the official page does not have wss://
either). It took me some time to figure out that wss stood for Web Socket Secured, just like https stood for http Secured. However, another Apache server doesn’t require wss — my SSD for the web server (Raspberry Pi) died after reverse proxy setup, and needed to build another. I’m still not sure why wss was required…
Image by Stable Diffusion
Date:
2023-Nov-25 23:02:10
Model:
realisticVision-v20_split-einsum
Size:
512 x 512
Include in Image:
cartoon, clolorful,
modern ladies working at post office classifying letters
Exclude from Image:
Seed:
4084494267
Steps:
23
Guidance Scale:
11.0
Scheduler:
DPM-Solver++
ML Compute Unit:
CPU & Neural Engine
Thank you for your article, I will try it later.
I tried using Flet with NGINX by following the exact example in the guide, but it didn’t work. My page opens with the Flet icon but keeps loading indefinitely. Here is the link to the example: https://flet.dev/docs/guides/python/deploying-web-app/hosting-providers/self-hosting/.
Do you have any ideas regarding this problem?
Hi Vilounha,
As I do not have an NGINX server my suggestion might be pointless, but let me advise what happened to me.
In my case, my web app kept loading icon at first, so I used the inspect feature on Chrome and figured out there were errors regarding wss.
My domain is https preload configured for subdomains as well, and it means access to *.peddals.com is forced on httpS OR wsS – HTTP or WebSockets over SSL/TLS.
So, I added proxypass entries over wss in the apache config file to make reverse proxy load the app as expected.
First thing I’d suggest is check logs — NGINX, console and web browser’s inspection.
If any of these warn about wss and your site is SSL/TLS enforced, try adding https and/or wss blocks to your NGINX site config.
Also, you can find expers including the author of Flet in the Help channel of the Flet official Discord server. Search for NGINX or error message or ask people there for help.
https://discord.com/channels/981374556059086931/1000264673284857866