Host Flet web app behind Apache web server by Reverse Proxy

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.

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

  1. Install requirements on Ubuntu server.
  2. Build a Python virtual environment and install Flet.
  3. Prepare a Flet app code.
  4. Enable Apache modules required for reverse proxy.
  5. Write an Apache configuration file.
  6. 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 like
  • User= and Group= your own username (whoami)
  • WorkingDirectory= is the full path to the directory of counter.py.
  • Environment="PATH= is the full path to the directory of python3 (output of which python3 up to bin/)
  • ExecStart= first arg is full path to Python3 (output of which 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

© Peddals.com