Compare commits

...
Sign in to create a new pull request.

82 commits

Author SHA1 Message Date
2514e7cbaa png image added 2025-12-16 16:13:03 +01:00
e89c7a0bd2 Structure change 2025-10-20 13:38:34 +02:00
77d4dd3a0a Setup.sh updated 2025-10-20 12:25:49 +02:00
ffd681a654 Setup.sh updated 2025-10-18 20:30:17 +02:00
8b3ea9e89f Template updated 2025-10-16 17:13:19 +02:00
ef631b9c3f Some new features 2025-10-16 17:11:10 +02:00
0739547520 new functions added 2025-10-15 18:02:15 +02:00
ec25774fc2 Readme updated 2025-10-15 08:15:35 +02:00
45db22a155 setup script updated 2025-10-15 08:14:42 +02:00
8d99133efd update setup script 2025-10-14 21:55:57 +02:00
9e90100b9d few changes 2025-10-14 21:46:07 +02:00
7e5ead8f76 Structure change 2025-10-14 18:40:39 +02:00
bb63929a1e Structure change 2025-10-14 18:30:10 +02:00
d3be1e2984 changes implementing flask 2025-10-14 15:49:46 +02:00
30c4c40494 Structure change 2025-10-14 15:15:58 +02:00
fdd53445da lomes-app.py updated 2025-10-14 15:03:09 +02:00
c88020974e lomes-app.py updated 2025-10-14 15:00:37 +02:00
7dbd004057 Index.html updated 2025-10-14 14:58:30 +02:00
cc3f42b710 Notes update 2025-10-14 14:45:33 +02:00
ea2ce70de3 Readme updated 2025-10-14 14:42:10 +02:00
cb9c15b0e0 Readme updated 2025-10-14 14:41:15 +02:00
19db588525 Readme updated 2025-10-14 14:40:34 +02:00
55a08ee5a5 Readme updated 2025-10-14 14:39:10 +02:00
8e554ff849 Readme updated 2025-10-14 14:38:16 +02:00
9d1032d5f7 script updated 2025-10-14 14:29:43 +02:00
05129a734e fix 2025-10-14 14:12:01 +02:00
5edacf8d44 fix 2025-10-14 14:09:52 +02:00
5ff64fc340 fix 2025-10-14 14:09:18 +02:00
f90bc2c75b fix 2025-10-14 13:46:56 +02:00
37800c312f changes implementing flask 2025-10-14 13:41:05 +02:00
46035e996d debug mode enabled 2025-10-14 13:02:27 +02:00
c6f72d83c9 html links changed to flask style 2025-10-14 12:57:56 +02:00
294f8b84ab several changes implementing flask 2025-10-14 12:55:11 +02:00
b72fce9038 Update assets/notes/FrontToBackend.md 2025-10-13 09:20:32 +02:00
698c1d3076 Structure changes regarding flask 2025-10-13 09:19:32 +02:00
254fd49c08 Update assets/notes/FrontToBackend.md 2025-10-13 08:04:11 +02:00
ee87f6346f Update lomes-app.py 2025-10-12 20:16:47 +02:00
85551f5110 Structure changed 2025-10-12 20:16:39 +02:00
fe011be589 Flask config changed 2025-10-12 20:14:45 +02:00
368bd1ae9d flask config edited 2025-10-12 18:44:48 +02:00
91cc993841 flask config added 2025-10-12 18:41:50 +02:00
4e5339df5a setup script updated 2025-10-12 18:11:00 +02:00
da664519f3 setup script updated 2025-10-12 18:01:06 +02:00
753511958c setup script updated 2025-10-12 17:47:16 +02:00
9824d03655 setup script updated 2025-10-12 17:46:01 +02:00
c071de983f setup script updated 2025-10-12 17:33:34 +02:00
e0872eed11 setup script updated 2025-10-12 17:31:48 +02:00
033049430b setup script updated 2025-10-12 17:23:44 +02:00
f7589cafe0 Update README.md 2025-10-12 15:49:05 +02:00
57109b47bb typo fixed 2025-10-12 15:24:36 +02:00
d9525d1af0 typo fixed 2025-10-12 15:24:05 +02:00
1da601fb23 Script edited 2025-10-12 15:22:41 +02:00
444f7bffb0 Script edited 2025-10-12 15:13:04 +02:00
1bad92763d Landing Page added 2025-10-12 11:40:54 +02:00
45f990a1b8 Code cleanup 2025-10-12 09:49:35 +02:00
5a45c280fb notes edited 2025-10-11 19:43:49 +02:00
ba87998c7a notes edited 2025-10-11 19:42:30 +02:00
7c38625f49 notes edited 2025-10-11 19:32:59 +02:00
18997abc80 Multiple changes 2025-10-11 19:11:21 +02:00
61ad242506 multiple changes 2025-10-11 19:10:48 +02:00
733b059cf3 Base script finalized 2025-10-11 18:14:43 +02:00
e7dd6c62a8 Dependencies updated 2025-10-11 18:04:05 +02:00
2494e9d278 Code Cleanup 2025-10-11 17:36:02 +02:00
1bdb59d012 Update README.md 2025-10-11 17:23:34 +02:00
577ce1c885 Update README.md 2025-10-11 17:21:19 +02:00
6d37ad3af0 Dependencie Check updated 2025-10-11 17:16:38 +02:00
cffdc504ca update 2025-10-10 21:59:27 +02:00
6c06ee2b52 test script uploaded 2025-10-10 21:37:12 +02:00
5bb0d81df5 good for today 2025-10-10 20:42:05 +02:00
c031baf491 more fixed stuff 2025-10-10 20:38:19 +02:00
de000d134e fix 2025-10-10 20:30:49 +02:00
01f072742f more fixes 2025-10-10 20:29:07 +02:00
cd0632281f final fixes 2025-10-10 20:11:17 +02:00
4af3ec7276 test script added 2025-10-10 17:13:44 +02:00
a0f25306a2 bug fixed 2025-10-10 17:08:12 +02:00
389923c24b dev setup changes 2025-10-10 16:41:08 +02:00
cc9c738de2 Script & Deps updated 2025-10-10 15:12:52 +02:00
d3df81c908 Script updated 2025-10-10 13:28:40 +02:00
eed441b0d6 Update dev_env_setup.sh 2025-10-09 20:48:37 +02:00
eee7ee410c Script changed 2025-10-09 20:07:44 +02:00
c9223ecffc code added 2025-10-09 17:57:13 +02:00
1e5b6677d2 code added 2025-10-09 17:55:36 +02:00
40 changed files with 885 additions and 189 deletions

View file

@ -1,11 +1,11 @@
# LoMeS
<img src="assets/images/lomes.svg" alt="Meshtastic" width="100">
<!--<img src="https://meshtastic.org/design/logo/svg/Mesh_Logo_White.svg" alt="Meshtastic" width="100" height="100">-->
# LoMeS
**LOcal MEshtastic Server** _in development_
Idea is to:
- develop an offline web app client and python backend, running in your local network and **nowhere** else.
- develop an offline Meshtastic server, running in your local network and **nowhere** else.
- create a web app, coded in `html`, `css`, `js` and `php` and make it a bit prettier than the original.
- code a backend utilising `flask`, `python`, `python3-meshtastic` and `python3-requests`.
- make it as light but versatile as possible _let's see how this is gonna work out..._
@ -26,9 +26,16 @@ for now everything will be developed and tested on Raspberry Pi 3B and newer act
## Development Setup
1. Flash Raspberry Pi OS lite 64bit
2. Install dependencies:
2. Install git:
```bash
sudo apt install --install-suggests -y nginx python3-meshtastic python3-flask python3-requests
sudo apt install -y git
```
3. Configure `nginx` the way you need | _or use the example config located [here](https://lab.c95.org/fr4nz/LoMeS/src/branch/main/assets/config/nginx/nginx.conf) edit at least lines 9 & 15 - 18 to your needs_
4. Start developing
3. Clone repository
```bash
git clone https://lab.c95.org/fr4nz/LoMeS.git && cd LoMeS
```
4. Run development environment setup
```bash
chmod +x lomes-setup.sh && sudo ./lomes-setup.sh
```
5. Start developing

View file

@ -0,0 +1,2 @@
#deps="openssl nginx nginx-common python3-meshtastic python3-flask python3-requests"
deps=("openssl" "nginx" "python3-meshtastic" "python3-flask" "python3-requests" "usbip" "python3-usb")

View file

@ -0,0 +1,12 @@
#!/bin/python3
from flask import Flask, render_template
app = Flask(__name__, static_folder="/var/www/html", static_url_path="/var/www/html", send_from_directory("data/images, lomes.svg"))
@app.route("/")
def index():
return app.send_static_file("index.html")
app.run(host="127.0.0.1", port=5000)

View file

@ -0,0 +1,14 @@
###########################################################
### ###
### MESHPI NGINX CONFIG ###
### ###
###########################################################
server {
listen 80;
server_name DOMAIN IPADDR;
location / {
proxy_pass http://127.0.0.1:5000;
}
}

View file

@ -14,8 +14,8 @@ server {
listen 443 ssl;
server_name DOMAIN IPADDR;
ssl_certificate /etc/nginx/ssl/CERTNAME.crt;
ssl_certificate_key /etc/nginx/ssl/CERTNAME.key;
ssl_certificate CERTPATH.crt;
ssl_certificate_key KEYPATH.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
@ -26,8 +26,6 @@ server {
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
try_files $uri $uri/ =404;
root /var/www/html;
index index.html;
proxy_pass http://127.0.0.1:5000;
}
}

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 100 55" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.802386,0,0,0.460028,-421.748,-122.127)">
<g transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)">
<path d="M250.908,330.267L193.126,415.005L180.938,406.694L244.802,313.037C246.174,311.024 248.453,309.819 250.889,309.816C253.326,309.814 255.606,311.015 256.982,313.026L320.994,406.536L308.821,414.869L250.908,330.267Z" style="fill:white;"/>
</g>
<g transform="matrix(0.582378,0,0,1.01579,485.019,-211.182)">
<path d="M87.642,581.398L154.757,482.977L142.638,474.713L75.523,573.134L87.642,581.398Z" style="fill:white;"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

57
assets/images/favicon.ico Normal file
View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="23.797873mm"
height="12.931701mm"
viewBox="0 0 23.797873 12.931701"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="favicon.ico"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="11.782177"
inkscape:cx="30.6395"
inkscape:cy="19.308826"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="g3" /><defs
id="defs1" /><g
transform="matrix(0.21229796,0,0,0.12171574,-113.52852,-33.25759)"
id="g3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<g
transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)"
id="g1">
<path
d="m 250.908,330.267 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 64.012,93.51 -12.173,8.333 z"
style="fill:#ffffff"
id="path1" />
</g><g
transform="matrix(0.579082,0,0,1.01004,441.72359,108.2802)"
id="g1-3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<path
d="m 230.63238,183.77092 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 16.93449,24.73698 -12.173,8.333 z"
style="fill:#ffffff"
id="path1-5"
sodipodi:nodetypes="ccccccccc" />
</g>
</g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/images/lomes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

57
assets/images/lomes.svg Normal file
View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="23.797873mm"
height="12.931701mm"
viewBox="0 0 23.797873 12.931701"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="lomes.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="11.782177"
inkscape:cx="30.6395"
inkscape:cy="19.308826"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="g3" /><defs
id="defs1" /><g
transform="matrix(0.21229796,0,0,0.12171574,-113.52852,-33.25759)"
id="g3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<g
transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)"
id="g1">
<path
d="m 250.908,330.267 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 64.012,93.51 -12.173,8.333 z"
style="fill:#ffffff"
id="path1" />
</g><g
transform="matrix(0.579082,0,0,1.01004,441.72359,108.2802)"
id="g1-3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<path
d="m 230.63238,183.77092 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 16.93449,24.73698 -12.173,8.333 z"
style="fill:#ffffff"
id="path1-5"
sodipodi:nodetypes="ccccccccc" />
</g>
</g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,3 +1,11 @@
[CRUD REST API](https://youtu.be/I07FyMH1DzI)
---
[Meshtastic Python API Documentation](https://python.meshtastic.org/)
---
To send commands from a Python script to a web server, you can use HTTP requests. The requests library is a popular and user-friendly option for making HTTP calls in Python.
For example, you can send a POST request with data to a specific URL:

View file

@ -1,7 +1,7 @@
# Notes
## To Do
1. [ ] define actions and plan
2. [ ] create simple web interface with flask and nginx
1. [x] define actions and plan
2. [ ] create setup script
3. [ ] communicate with Meshtastic device via web interface
## Follow up
@ -19,3 +19,87 @@
- Environment setup script in development
### Frontend
### Thoughts
- Play with usbip
To establish a connection between a website and a USB device connected to a Linux server, you cannot directly connect a web application to a USB device over a network using standard web protocols. However, you can achieve this functionality by creating a bridge between the web application and the USB device using a local service on the Linux server. Heres how:
1. Use USB/IP to Share the USB Device Over the Network: The USB/IP project allows you to share a physical USB device connected to a Linux server over a TCP/IP network, making it appear as a local USB device on a client machine. This is the most direct method for network access.
- On the Server (where the USB device is physically connected):
- Install the usbip package.
- Load the required kernel modules: usbip_core and usbip_host by creating a `.conf` file in `/etc/modules-load.d/` and adding the modules.
- Start and enable the usbipd.service daemon.
- List the available USB devices using usbip list -l to find the device's bus ID.
- Bind the specific USB device to the USB/IP service using usbip bind -b <busid>. This makes the device available for remote access.
- On the Client (the machine running the web application):
- Ensure the vhci_hcd kernel module is loaded.
- List the available devices from the server using usbip list -r <server_ip_address>.
- Attach the device to the client using usbip attach -r <server_ip_address> -b <busid>. Once attached, the device will appear as a local USB device on the client machine.
2. Integrate the Attached Device with Your Web Application: Once the USB device is attached to the client machine via USB/IP, it will be accessible to any software running on that machine, including a web application. The web application can then communicate with the device using standard USB communication libraries (e.g., libusb for C/C++, pyusb for Python) just as if the device were directly connected to the client machine. The web server (e.g., Apache, Nginx) and the application framework (e.g., Node.js, Django) on the client machine handle the web interface, while the application code uses the local USB device.
3. Alternative: Use a Local Service (e.g., a Web API): Instead of attaching the device to the web server machine, you can create a separate local service (a daemon or a small application) on the server that communicates directly with the USB device. This service can then expose a simple HTTP API (e.g., using a lightweight framework like Flask or Express) that the web application can call to send commands to or receive data from the USB device. This approach keeps the USB device connection confined to the server and uses standard web protocols for communication.
In summary, the most practical approach is to use USB/IP to make the USB device appear as a local device on the machine hosting the web application, allowing the application to interact with it directly through standard USB libraries.
### Troubble Shooting
**usbip: error: could not connect to 192.168.1.8:3240: System error** adjust firewall? `vhci_hcd` on client machine?
So for the daemon - /etc/systemd/system/usbipd.service
```
[Unit]
Description=usbip host daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
Restart=always
ExecStartPre=/usr/sbin/modprobe usbip-core
ExecStartPre=/usr/sbin/modprobe usbip-host
ExecStart=/usr/sbin/usbipd
ExecStopPost=/usr/sbin/rmmod usbip-host
ExecStopPost=/usr/sbin/rmmod usbip-core
[Install]
WantedBy=multi-user.target
```
And the template for the binds - /etc/systemd/system/usbip-bind@.service
```
[Unit]
Description=Bind USB device to usbipd
After=network-online.target usbipd.service
Wants=network-online.target usbipd.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/usbip bind --busid %i
ExecStop=/usr/sbin/usbip unbind --busid %i
[Install]
WantedBy=multi-user.target
```
Enable and start the daemon with:
```
systemctl enable usbipd
systemctl start usbuipd
```
Then add binds with:
```
systemctl enable usbip-bind@1-1.2.3
systemctl start usbip-bind@1-1.2.3
```
Replace 1-1.2.3 with the bind id of the USB device you want to share. You can use as many of these as devices you want to share and you can then bind and unbind each one individually and have then bind at machine startup (or not).
Find the bind ids with:
`usbip list -l`
Note that usbip binds seem to expire if not attached by a remote machine within around 10 mins - not very helpful!
I haven't yet decided how I'm going to tackle the client attach, possibly not with systemd. It would be really helpful if usbip had a bit more intelligence...

View file

@ -1,14 +1,15 @@
#!/bin/bash
source assets/shell/shell_colors
source assets/shell/colors
source assets/config/deps/dependencies
### DEPENDENCY CHECK & INSTALLER
pkgs="openssl nginx"
echo -e "\n${CYN} Dependency and Privilege Check running...${CRS}\n"
echo -e "\n ${LCY}Dependency and Privilege Check running...${CRS}\n"
### PRIVILEGES
if (( $(id -u) == 0 )); then
if (( $(id -u) == 0 )); then ### AM I ROOT?
echo -e " ${GRN}Privilege check passed...${CRS}\n"
else
@ -18,82 +19,42 @@ fi
### DEPENDENCIES
if command -v "$pkgs" >/dev/null 2>&1; then
echo -e "${GRN} Dependency check passed...${CRS}\n"
dep_check() {
local pkg="$1"
if dpkg -s "$pkg" >/dev/null 2>&1; then
echo "$pkg" >>/tmp/installed_dev
else
echo -e "${YEL} Dependencies not met.${CRS}\n"
echo "$pkg" >>/tmp/missing_dev
fi
}
for pkg in "${deps[@]}"; do
dep_check "$pkg"
done
installed="$(cat /tmp/installed_dev 2>/dev/null)"
missing="$(cat /tmp/missing_dev 2>/dev/null)"
if ! [ "$missing" ]; then
echo -e "\n ${GRN}Dependencies met. Proceeding...${CRS}\n"
else
echo -e "\n ${RED}Following dependencies are missing :${CRS}\n\n$missing"
while true; do
echo -e " ${YEL}Do you wish to install via APT? (${GRN}Y${YEL}/${RED}n${YEL})${CRS}"
read -p " --> " install
echo ""
if [[ "$install" = "" || "$install" = "y" || "$install" = "Y" ]]; then
sudo apt update && sudo apt install --install-suggests -y $pkgs --simulate ## DEV
echo -e "\n ${YEL}Do you wish to install via APT?"
read -p " (Y/n) --> " install_dep
echo -e "${CRS}"
if [[ "$install_dep" = "" || "$install_dep" = "y" || "$install_dep" = "Y" ]]; then
sudo apt update && sudo apt install -y $missing --simulate
echo -e "\n ${GRN}Dependencies installed. Proceeding...${CRS}\n"
sudo rm /tmp/installed_dev /tmp/missing_dev 2>/dev/null
break
elif [[ "$install" == "n" || "$install" = "N" ]]; then
elif [[ "$install_dep" == "n" || "$install_dep" = "N" ]]; then
echo -e "\n ${RED}Missing dependencies... Exiting!${CRS}\n"
sudo rm /tmp/installed_dev /tmp/missing_dev 2>/dev/null
exit 1
else
echo -e "\n ${YEL}Invalid response... Try again...\n\n ${GRN}Y ${YEL}= (Yes, install dependencies and continue)\n ${RED}N ${YEL}= (No, don't install dependencies and exit)${CRS}\n "
fi
done
fi
### NGINX SETUP & CONFIG
###### CERTIFICATION
while true; do
echo -e " ${YEL}Configure SSL and create a self signed cetrificate? (Y/n)${CRS}"
read -p " --> " installSSL
if [[ "$installSSL" = "" || "$installSSL" = "y" || "$installSSL" = "Y" ]]; then
echo -e " ${YEL}Enter path to certificates folder${CRS}"
read -p " default = /etc/nginx/ssl --> " cert_path
if ! [ "$cert_path" ]; then
cert_path=/etc/nginx/ssl
elif [[ "$cert_path" = "." ]]; then
cert_path=$PWD
else
:
fi
echo ""
echo -e " ${YEL}Enter file name for certificate and key${CRS}"
read -p " default --> $HOSTNAME --> " cert_name
if ! [ "$cert_name" ]; then
cert_name=$HOSTNAME
else
:
fi
echo ""
sudo mkdir -p "$cert_path"
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout "$cert_path"/"$cert_name".key -out "$cert_path"/"$cert_name".crt
echo -e "\n${GRN} SSL certificate files ${YEL}$cert_name.crt ${GRN}and ${YEL}$cert_name.key ${GRN}created and stored in ${YEL}$cert_path${CRS}\n"
break
elif [[ "$installSSL" == "n" || "$installSSL" = "N" ]]; then
echo -e "\n${RED} No encryption established${CRS}\n"
break
else
echo -e "\n${YEL} Invalid response... Try again...\n\nY = (Yes, configure SSL certificate and continue)\nN = (No, leave unencrypted and continue)${CRS}\n "
fi
done
echo -e "${YEL} Your current hostname is ${CYN}$HOSTNAME${CRS} would you like to change it?${CRS}"
# ask for network interface & get IP
# ask to change hostname in /etc/hosts & /etc/hostname
### DEV STATUS
#sudo cp -R assets/config/nginx/nginx.conf /etc/nginx/sites-enabled/
## JEFF
# utilise sed to edit config
# test nginx config
# restart nginx
## JEFF END
echo -e "${GRN}\nScript ran through...${CRS}"

View file

@ -1,82 +0,0 @@
#!/bin/bash
source assets/shell/shell_colors
### DEPENDENCY CHECK & INSTALLER
pkgs="openssl nginx"
echo -e "\n${CYN} Dependency and Privilege Check running...${CRS}\n"
### PRIVILEGES
if (( $(id -u) == 0 )); then
echo -e "${GRN} Privilege check passed...${CRS}\n"
else
echo -e "${RED} Privilege check failed... Please run script with sudo or as root!${CRS}\n"
exit 1
fi
### DEPENDENCIES
if command -v "$pkgs" >/dev/null 2>&1; then
echo -e "${GRN} Dependency check passed...${CRS}\n"
else
echo -e "${YEL} Dependencies not met.${CRS}\n"
while true; do
echo -e " ${YEL}Do you wish to install via APT? (${GRN}Y${YEL}/${RED}n${YEL})${CRS}"
read -p " --> " install
echo ""
if [[ "$install" = "" || "$install" = "y" || "$install" = "Y" ]]; then
sudo apt update && sudo apt install --install-suggests -y $pkgs --simulate ## DEV
echo -e "\n${GRN} Dependencies installed. Proceeding...${CRS}\n"
break
elif [[ "$install" == "n" || "$install" = "N" ]]; then
echo -e "\n${RED} Missing dependencies... Exiting!${CRS}\n"
exit 1
else
echo -e "\n${YEL} Invalid response... Try again...\n\n ${GRN}Y ${YEL}= (Yes, install dependencies and continue)\n ${RED}N ${YEL}= (No, don't install dependencies and exit)${CRS}\n "
fi
done
fi
### NGINX SETUP & CONFIG
###### CERTIFICATION
while true; do
echo -e " ${YEL}Configure SSL and create a self signed cetrificate? (Y/n)${CRS}"
read -p " --> " installSSL
if [[ "$installSSL" = "" || "$installSSL" = "y" || "$installSSL" = "Y" ]]; then
echo -e " ${YEL}Enter path to certificates folder${CRS}"
read -p " default = /etc/nginx/ssl --> " cert_path
if ! [ "$cert_path" ]; then
cert_path=/etc/nginx/ssl
elif [[ "$cert_path" = "." ]]; then
cert_path=$PWD
else
:
fi
echo ""
echo -e " ${YEL}Enter file name for certificate and key${CRS}"
read -p " default --> $HOSTNAME --> " cert_name
if ! [ "$cert_name" ]; then
cert_name=$HOSTNAME
else
:
fi
echo ""
sudo mkdir -p "$cert_path"
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout "$cert_path"/"$cert_name".key -out "$cert_path"/"$cert_name".crt
echo -e "\n${GRN} SSL certificate files ${YEL}$cert_name.crt ${GRN}and ${YEL}$cert_name.key ${GRN}created and stored in ${YEL}$cert_path${CRS}\n"
break
elif [[ "$installSSL" == "n" || "$installSSL" = "N" ]]; then
echo -e "\n${RED} No encryption established${CRS}\n"
break
else
echo -e "\n${YEL} Invalid response... Try again...\n\nY = (Yes, configure SSL certificate and continue)\nN = (No, leave unencrypted and continue)${CRS}\n "
fi
done

21
lomes-app.py Executable file
View file

@ -0,0 +1,21 @@
#!/bin/python3
from flask import Flask, render_template
import datetime
import getpass
import os
app = Flask(__name__)
@app.route("/")
def index():
user = getpass.getuser()
preTime = datetime.datetime.now()
time = preTime.strftime("%H:%M:%S - %a %d.%m.%Y")
uname_fields = ("System", "Hostname", "Kernel")
uname_info = os.uname()
sysinfo = "\n".join(f"{field}: {value} | " for field, value in zip(uname_fields, uname_info))
return render_template("index.html", user=user, time=time, sysinfo=sysinfo)
app.run(host="127.0.0.1", port=5000, debug=True)

276
lomes-setup.sh Executable file
View file

@ -0,0 +1,276 @@
#!/bin/bash
trap "exit" INT
chmod +x lomes-app.py
mkdir -p /tmp/LoMeS
source assets/shell/colors
source assets/config/deps/dependencies
### DEPENDENCY CHECK & INSTALLER
echo -e "\n ${LCY}Dependency and Privilege Check running...${CRS}\n"
### PRIVILEGES
if (( $(id -u) == 0 )); then ### AM I ROOT ?
echo -e " ${LCY}- ${GRN}Privilege check passed...${CRS}\n"
else
echo -e " ${LCY}- ${RED}Privilege check failed... Please run script with sudo or as root!${CRS}\n"
exit 1
fi
### DEPENDENCIES
dep_check() { ### MISSING PKGS ?
local pkg="$1"
if dpkg -s "$pkg" >/dev/null 2>&1; then
echo "$pkg" >>/tmp/LoMeS/installed_dev
else
echo "$pkg" >>/tmp/LoMeS/missing_dev
fi
}
for pkg in "${deps[@]}"; do
dep_check "$pkg"
done
installed="$(cat /tmp/LoMeS/installed_dev 2>/dev/null)"
missing="$(cat /tmp/LoMeS/missing_dev 2>/dev/null)"
if ! [ "$missing" ]; then
echo -e " ${LCY}- ${GRN}Dependencies met. Proceeding...${CRS}\n"
else ### INSTALLING PKGS !
echo -e " ${LCY}- ${RED}Following dependencies are missing :\n\n$missing${CRS}"
while true; do
echo -e "\n ${YEL}Do you wish to install via APT?"
read -p " (Y/n) --> " install_dep
echo -e "${CRS}"
if [[ "$install_dep" = "" || "$install_dep" = "y" || "$install_dep" = "Y" ]]; then
sudo apt update > /dev/null 2>&1 && sudo apt install -y $missing --simulate > /dev/null 2>&1
echo -e " ${LCY}- ${GRN}Dependencies installed. Proceeding...${CRS}\n"
sudo rm /tmp/LoMeS/installed_dev /tmp/LoMeS/missing_dev 2>/dev/null
break
elif [[ "$install_dep" == "n" || "$install_dep" = "N" ]]; then
echo -e " ${RED}Missing dependencies... Exiting!${CRS}\n"
sudo rm /tmp/LoMeS/installed_dev /tmp/LoMeS/missing_dev 2>/dev/null
exit 1
else
echo -e " ${YEL}Invalid response... Try again...\n\n ${GRN}Y ${YEL}= (Yes, install dependencies and continue)\n ${RED}N ${YEL}= (No, don't install dependencies and exit)${CRS}\n "
fi
done
fi
### NGINX SETUP & CONFIG
###### CONNECTION & INTERFACE
onif=$(/sbin/ip route get 162.249.72.1 | awk '{print $5}' | cut -d/ -f1)
while true; do ### SELECT NETWORK INTERFACE !
echo -e " ${YEL}What network interface will nginx be using?"
read -p " current = "$onif" --> " nif
echo -e "${CRS}"
if ! [ "$nif" ]; then
nif="$onif"
break
elif [ -d "/sys/class/net/$nif" ]; then
break
else
echo -e "\n ${LRD}Interface not found... Try again!${CRS}\n"
fi
done
ip4=$(/sbin/ip -o -4 addr list "$nif" | awk '{print $4}' | cut -d/ -f1) ### GET IP FOR CHOSEN INTERFACE !
echo -e "\n ${YEL}Current hostname : ${LCY}$(hostname)${CRS}"
echo -e " ${YEL}Current ip address : ${LCY}$ip4 ${YEL}@ ${LCY}$nif${CRS}"
echo -e "\n ${YEL}This information will be used to configure ${LCY}nginx.conf ${YEL}during the next steps."
while true; do ### HOST NAME CHANGE ?
read -p " Would you like to change the hostname? (y/N) --> " conf_hostname
echo -e "${CRS}"
if [[ "$conf_hostname" = "" || "$conf_hostname" = "n" || "$conf_hostname" = "N" ]]; then
new_hostname=$(hostname)
break
elif [[ "$conf_hostname" = "y" || "$conf_hostname" = "Y" ]]; then
read -p " Enter new hostname --> " new_hostname
sudo sed -i.backup "s/$(hostname)/$new_hostname/g" /etc/hosts
sudo echo "$new_hostname" > /etc/hostname
sudo systemctl restart NetworkManager 2>/dev/null
hostname -F /etc/hostname 2>/dev/null
echo -e "\n ${GRN}Host name changed to ${LCY}$(hostname)${CRS}"
echo "HC" > /tmp/LoMeS/honacha
break
else
echo -e "\n ${YEL}Invalid response... Try again...\n\n Y = (Yes, set new hostname)\n N = (No, leave as is)${CRS}\n "
fi
done
while true; do ### CERTIFICATION & CONFIGURATION HTTPS
echo -e "\n ${YEL}Configure nginx with SSL and create a self signed cetrificate?"
read -p " (Y/n) --> " nginxSSL
echo -e "${CRS}"
if [[ "$nginxSSL" = "" || "$nginxSSL" = "y" || "$nginxSSL" = "Y" ]]; then
echo -e " ${YEL}Enter path to certificates folder"
read -p " default = /etc/nginx/ssl --> " cert_path
echo -e "${CRS}"
if ! [ "$cert_path" ]; then
cert_path=/etc/nginx/ssl
elif [[ "$cert_path" = "." ]]; then
cert_path=$PWD
else
:
fi
echo -e " ${YEL}Enter file name for certificate and key"
read -p " default = $(hostname) --> " cert_name
echo -e "${CRS}"
if ! [ "$cert_name" ]; then
cert_name=$(hostname)
else
:
fi
sudo mkdir -p "$cert_path"
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout "$cert_path"/"$cert_name".key -out "$cert_path"/"$cert_name".crt
echo -e "\n ${GRN}SSL certificate files ${LCY}$cert_name.crt ${GRN}and ${LCY}$cert_name.key ${GRN}created and stored in ${LCY}$cert_path${CRS}"
sudo chmod 644 "$cert_path"/"$cert_name".crt
sudo chmod 600 "$cert_path"/"$cert_name".key
sudo cp assets/config/nginx/nginx_SSL.conf /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s/DOMAIN/$(hostname).local/g" /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s/IPADDR/$ip4/g" /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s|CERTPATH|$cert_path/$cert_name|" /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s|KEYPATH|$cert_path/$cert_name|" /etc/nginx/sites-enabled/$(hostname).conf
break
elif [[ "$nginxSSL" == "n" || "$nginxSSL" = "N" ]]; then
while true; do ### CONFIGURATION HTTP
echo -e " ${YEL}Configure nginx with HTTP?"
read -p " (Y/n) --> " nginxHTTP
echo -e "${CRS}"
if [[ "$nginxHTTP" = "" || "$nginxHTTP" = "y" || "$nginxHTTP" = "Y" ]]; then
sudo cp assets/config/nginx/nginx_HTTP.conf /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s/DOMAIN/$(hostname).local/g" /etc/nginx/sites-enabled/$(hostname).conf
sudo sed -i "s/IPADDR/$ip4/g" /etc/nginx/sites-enabled/$(hostname).conf
break
elif [[ "$nginxHTTP" = "n" || "$nginxHTTP" = "N" ]]; then
echo -e " ${LCY}- ${LRD}Keeping nginx default configuration!${CRS}"
break
else
echo -e " ${YEL}Invalid response... Try again...\n\n Y = (Yes, configure nginx)\n N = (No, skip nginx configuration)${CRS}\n "
break
fi
done
break
else
echo -e "\n ${YEL}Invalid response... Try again...\n\n Y = (Yes, configure SSL certificate and continue)\n N = (No, leave unencrypted and continue)${CRS}\n "
fi
done
###### NGINX MAINTENANCE
sudo rm -rf /var/www/html
if ! [ "$(sudo nginx -t > /dev/null 2>&1)" ]; then ### NGINX CONF CHECK
echo -e "\n ${LCY}- ${LGN}Nginx configuration checks out...${CRS}"
else
echo -e "\n ${LRD}Nginx configuration is malformed!${CRS}"
echo "nginx -t --> failed" >> /tmp/LoMeS/install_log
fi
if ! [ "$(sudo nginx -s reload > /dev/null 2>&1)" ]; then ### RELOAD NGINX
echo -e "\n ${LCY}- ${LGN}Nginx reloaded...${CRS}"
else
echo -e "\n ${LRD}Nginx couldn't reload!${CRS}"
echo "nginx -s reload --> failed" >> /tmp/LoMeS/install_log
fi
if ! [ -f "/tmp/LoMeS/install_log" ]; then ### LOG CHECK
echo -e "\n ${LCY}- ${LGN}No errors while setting up...${CRS}"
else
echo -e "\n ${LRD}Error occured during setup! Please check ${LCY}/tmp/LoMeS/install_log ${LRD}for details...${CRS}"
fi
if [ -f "/tmp/LoMeS/honacha" ]; then ### REBOOT DUE TO HOST NAME CHANGE
echo -e "\n ${YEL}During setup you changed this machines host name. For the change to take effect, you should reboot! "
while true; do
read -p " Would you like to reboot? (Y/n) --> " reboot
echo -e "${CRS}"
if [[ "$reboot" = "" || "$reboot" = "y" || "$reboot" = "Y" ]]; then
echo -e " ${YEL}Rebooting in 10sec..."
echo -e " ${YEL}to start flask manually, run ${LCY}python3 lomes-app.py ${YEL}from LoMeS directory${CRS}"
sleep 10s
sudo reboot
elif [[ "$reboot" = "n" || "$reboot" = "N" ]]; then
echo -e " ${YEL}to start flask manually, run ${LCY}python3 lomes-app.py ${YEL}from LoMeS directory${CRS}"
break
else
echo -e "\n ${YEL}Invalid response... Try again...\n\n Y = (Yes, reboot)\n N = (No, don't reboot)${CRS}\n "
fi
done
else
while true; do
echo -e "${YEL}" ### START FLASK ?
read -p " Would you like to start flask? (Y/n) --> " flask_start
echo -e "${CRS}"
if [[ "$flask_start" = "" || "$flask_start" = "y" || "$flask_start" = "Y" ]]; then
echo -e " ${YEL}Starting flask in 10sec..."
echo -e " ${YEL}to start flask manually, run ${LCY}python3 lomes-app.py ${YEL}from LoMeS directory${CRS}\n"
sleep 10s
python3 lomes-app.py
break
elif [[ "$flask_start" = "n" || "$flask_start" = "N" ]]; then
echo -e " ${YEL}to start flask manually, run ${LCY}python3 lomes-app.py ${YEL}from LoMeS directory${CRS}\n"
break
else
echo -e "\n ${YEL}Invalid response... Try again...\n\n Y = (Yes, to start flask)\n N = (No, start flask later)${CRS}\n "
fi
done
fi

146
static/css/style.css Normal file
View file

@ -0,0 +1,146 @@
*{
margin: 0;
padding: 0;
font-family: Gravity;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-UltraLight.woff2') format('woff2'),
url('font/Gravity-UltraLight.woff') format('woff');
font-weight: 200;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-Light.woff2') format('woff2'),
url('font/Gravity-Light.woff') format('woff');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-Bold.woff2') format('woff2'),
url('font/Gravity-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-LightItalic.woff2') format('woff2'),
url('font/Gravity-LightItalic.woff') format('woff');
font-weight: 300;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-Italic.woff2') format('woff2'),
url('font/Gravity-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Gravity Book';
src: url('font/Gravity-Book.woff2') format('woff2'),
url('font/Gravity-Book.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-BoldItalic.woff2') format('woff2'),
url('font/Gravity-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Gravity Book';
src: url('font/Gravity-BookItalic.woff2') format('woff2'),
url('font/Gravity-BookItalic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-Regular.woff2') format('woff2'),
url('font/Gravity-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Gravity';
src: url('font/Gravity-UltraLightItalic.woff2') format('woff2'),
url('font/Gravity-UltraLightItalic.woff') format('woff');
font-weight: 200;
font-style: italic;
font-display: swap;
}
body {
background-color: darkslategrey;
}
header {
display: flex;
align-items: center;
justify-content: center;
padding-top: 30px;
}
.icon {
height: 80px;
}
.textBox {
padding-top: 20px;
}
h1 {
font-size: 26px;
padding: 5px;
padding-bottom: 10px;
text-align: center;
color: lightgray;
}
h3 {
font-size: 20px;
padding: 5px;
padding-bottom: 10px;
text-align: center;
color: lightgray;
}
p {
font-size: 16px;
padding: 5px;
padding-bottom: 10px;
text-align: center;
color: lightgray;
}
li {
font-size: 16px;
padding: 5px;
padding-bottom: 10px;
text-align: center;
color: lightgray;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

57
static/images/favicon.ico Normal file
View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="23.797873mm"
height="12.931701mm"
viewBox="0 0 23.797873 12.931701"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="favicon.ico"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="11.782177"
inkscape:cx="30.6395"
inkscape:cy="19.308826"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="g3" /><defs
id="defs1" /><g
transform="matrix(0.21229796,0,0,0.12171574,-113.52852,-33.25759)"
id="g3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<g
transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)"
id="g1">
<path
d="m 250.908,330.267 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 64.012,93.51 -12.173,8.333 z"
style="fill:#ffffff"
id="path1" />
</g><g
transform="matrix(0.579082,0,0,1.01004,441.72359,108.2802)"
id="g1-3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<path
d="m 230.63238,183.77092 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 16.93449,24.73698 -12.173,8.333 z"
style="fill:#ffffff"
id="path1-5"
sodipodi:nodetypes="ccccccccc" />
</g>
</g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

57
static/images/lomes.svg Normal file
View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="23.797873mm"
height="12.931701mm"
viewBox="0 0 23.797873 12.931701"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="lomes.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="11.782177"
inkscape:cx="30.6395"
inkscape:cy="19.308826"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="g3" /><defs
id="defs1" /><g
transform="matrix(0.21229796,0,0,0.12171574,-113.52852,-33.25759)"
id="g3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<g
transform="matrix(0.579082,0,0,1.01004,460.975,-39.6867)"
id="g1">
<path
d="m 250.908,330.267 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 64.012,93.51 -12.173,8.333 z"
style="fill:#ffffff"
id="path1" />
</g><g
transform="matrix(0.579082,0,0,1.01004,441.72359,108.2802)"
id="g1-3"
style="clip-rule:evenodd;display:inline;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
<path
d="m 230.63238,183.77092 -57.782,84.738 -12.188,-8.311 63.864,-93.657 c 1.372,-2.013 3.651,-3.218 6.087,-3.221 2.437,-0.002 4.717,1.199 6.093,3.21 l 16.93449,24.73698 -12.173,8.333 z"
style="fill:#ffffff"
id="path1-5"
sodipodi:nodetypes="ccccccccc" />
</g>
</g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

33
templates/index.html Normal file
View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html" charset="utf-8">
<meta name="viewport" content="width=device-width" initial-scale="1.0">
<title>LoMeS | Meshtastic</title>
<link rel="icon" href="{{ url_for('static', filename='images/lomes.svg') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<section>
<header>
<img class="icon" src="{{ url_for('static', filename='images/lomes.svg') }}">
<h1>Welcome to LoMeS</h1>
</header>
<div class="textBox">
<h3>A Local Meshtastic Server in development</h3><br>
<p>If you see this site, means "LoMeS" development environment is running!</p>
<p>Thanks for collaborating and trying to make things more real...</p>
</div>
<div class="textBox">
<h3>Configuration Summary</h3>
<div class="confBox">
<ul>
<li>User executing flask : {{user}}</li>
<li>Machine time : {{time}}</li>
<li>{{sysinfo}}</li>
</ul>
</div>
</div>
</section>
</body>
</html>