Last time I went through using overlayfs on a Linux SBC to survive unwelcomed power hits.
Today's post is Part II of a two-parter; you may want to read or skim the last post.
I wanted to finish the indestructable SBC setup by adding a python virtual environment using uv, getting a basic webserver "hello world" going using Python flask, and getting the flask service to autostart at boot using systemd.
If you are a Linux/Python admin you probably already know how to do all of this; you should probably skip this post and check out these guys instead.
As usual, I am writing the steps down in this post because I forget everything. These steps worked for me 12-8-25, hopefully if you read this a few years hence some of will still work (and AI will do the whole thing for you?)
| Only 512MB but text only OS still gave me space to mess around in an overlayfs configuration |
BUT FIRST--A WORD FROM THIS BLOG'S SPONSOR:

After getting your SBC set, you will probably want to design a PCB for your SBC then get them fabricated.
MAKING CHANGES TO THE READ ONLY SBC
From last post: we set the Raspberry Lite OS to be read-only to survive power hits using overlayfs, but today we are making changes to the OS.
How?
- I temporarily made my RPi Zero's OS writable by:
- removing its SD card
- mounting it via a USB adapter on my PC editing /boot/firmware/config.txt, getting rid of overlayroot=tempfs at the end of the statement,
- then saved cmdline.txt.
Then I popped the SD back into the RPI and started it up--it was now a normal read-write device.
When I was ready to go back to indestructable mode, I added overlayroot=tempfs back to the cmdline.txt using vi, saved, and reboot.
WHAT IS UV?
I've been a python programmer for years and all the tools needed to set up/maintain python3 and Python projects-- pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv, and so on, drove me nuts.
I had a preflight checklist for creating new virtual environments and I'd still make stupid mistakes.
Imagine my excitement when a tech from my geeky tech group told me about uv, a single tool that kicks the other Python admin tools' butts.
Count me in!
I read about uv here; good getting started video is here.
For Raspberry Pi OS here are the commands I used to create a new project called pyflask using uv:
#hint: to make my SSH terminal not look crap, make sure to use UTF-8 encoding (I use secureCRT9.6 #and properties > appearace > encoding default is "automatic" which isn't working)
#install uv
apt update
apt install curl #needed for next command--may already be installed on your SBC
#install uv using less HD space vs using pip install.
curl -LsSf https://astral.sh/uv/install.sh | sh
#SET PATH needed for terminal app to find uv when you try to run it
#put into path--for rpi I could skip this step and just restart bash; not sure w othr distros
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
#for some distros .local above is replaced by .cargo
#restart bash
bash
#is uv working? This should show a list of basic uv commands.
uv
CREATE A NEW PYTHON PROJECT AND VIRTUAL ENV USING UV
#cd to ~ you should do the next command from your home dir.
#my home dir is /home/charlie, yours probably isn't.
uv init pyflask #pyflask is the name of the project
#cd to the project folder you just created.
cd ~/pyflask
uv run main.py
#creates venv and show you successful hello world.cd p
#ACTIVATE THE NEW PROJECT
#you still must be in the project dir.
#must use source here or term will open
#a new term, make the change, and pop you back to old one....
#not what we want...
source .venv/bin/activate
#INSTALL PYTHON PACKAGES
#in project root folder....
#uv add [whatever] # use this instead of pip, faster!
#I love how fast uv is at adding modules!
#much MUCH faster vs. pip install.
#let's add flask!
uv add flask
#ASIDE--with UV, WHERE DO YOUR FILES .py files GO?
#see what is where in uv--useful cmd!
uv tree
#in project root. See below. note-- never edit anything inside the .venv dir and its subdirs.
#/home/pi/my_weather_bot/ <-- YOUR PROJECT ROOT (You work here)
#├── main.py <-- Your code goes here
#├── utils.py <-- Your code goes here
#├── data/ <-- Your data folders go here
#│ └── weather_log.csv
#└── .venv/ <-- THE VIRTUAL ENV (Do not open/edit)
# ├── bin/
# ├── lib/
# └── pyvenv.cfg
After all of this I had a working venv for pyflask. Good start!
GETTING FLASK GOING....
Flask is a simple webserver for Python--more here. By using flask, I created a webserver that generated "hello world" when viewed from my browser--using only a few lines of code--super easy!
#I created the file below using vi in /home/charlie/pyflask/app.py
####################SNIP ###############
#we used uv to install the flash module in our venv already.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
#START PYTHON APP using UV
#use this to test your flask setup.
uv run python3 app.py
#if you just use python3 app.py the path gets
#wacked and it won't work
###what your term will show (if flask is ready to process browserGETS and #PUTS)
#* Serving Flask app 'app'
#* Debug mode: on
#WARNING: This is a development server. Do not use it in a production #deployment. Use a production WSGI server instead.
#* Running on all addresses (0.0.0.0)
#* Running on http://127.0.0.1:5000
#* Running on http://192.168.5.200:5000
#Press CTRL+C to quit
#* Restarting with stat
#* Debugger is active!
#* Debugger PIN: 430-777-572
####################SNIP ###############
ACCESSING THE FLASK WEBPAGE FROM A BROWSER
Once I had everything above working it was time to test from a browser.
#if I open browser or curl using PC on
#the same wifi subnet as RPi Zero using port 5000
#I see hello world.
Your IP will be different, but I hope you get the idea.
http://192.168.5.200:5000/
GETTING FLASK TO AUTO-START
Our indestructable SBC's test app (in this case app.py) had to start on power-up every time.
There were lots of ways I could have done this, but to me the "Debian way" was to use systemd--good video series about how systemd works starts here; let's get right to it.
#we need to create a .service file for our python app.
#in Raspberry pi and maybe other debian likes create this in this dir.
#/etc/systemd/system/
#remember that systemd only works with
#the full path to a file or executable
#the command to create the .service file using vi on a raspberry pi is this.
sudo vi /etc/systemd/system/flaskapp.service
###########SNIP!#############################
[Unit]
Description=My Flask App
# Wait for the network to be ready before starting (crucial for Flask)
After=network.target
[Service]
# The user the app should run as
User=charlie
# The group
Group=charlie
# The folder where your app.py is located
WorkingDirectory=/home/charlie/pyflask
# The command to start the app.
# format: /path/to/python /path/to/app.py
#we are using uv, so, we use the uv created venv virtual directory.
ExecStart=/home/charlie/pyflask/.venv/bin/python3 /home/charlie/pyflask/app.py
# Automatically restart the app if it crashes
Restart=always
# Send Python output to the system log immediately
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
###########SNIP!#############################
FINISHING UP OUR BUILD
#let's load it! first, make the system reread all systemd config files...
sudo systemctl daemon-reload
#enable at boot
sudo systemctl enable flaskapp.service
#start it
sudo systemctl start flaskapp.service
#see its status
sudo systemctl status flaskapp.service
#stop the service (no changes needed to the service file for this)
sudo systemctl stop flaskapp.service
#restart the service
sudo systemctl restart flaskapp.service
OUTTRO
No comments:
Post a Comment