-
Notifications
You must be signed in to change notification settings - Fork 0
Security and Deployment
MeadOS is designed to run happily on a trusted home LAN with no password at all. If you want to reach it from outside, it has the pieces to do that safely.
Settings → Server Data → External Access Password. When set:
- Any connection from outside your LAN gets a styled login page. After a correct password, the browser keeps a signed, HttpOnly session cookie (30 days) so it isn't re-prompted.
- LAN devices are never prompted — unless you also enable "require password on LAN".
- The password is stored as a salted PBKDF2 hash, never in plain text.
- It can only be set or changed from inside the LAN, so a remote attacker can't lock you out or take over.
- HTTP Basic credentials are still accepted for programmatic clients.
Combine the password with HTTPS on your proxy — a password sent over plain HTTP travels readably.
Beyond standard security headers (CSP, X-Frame-Options, nosniff, etc.) on every response, the server includes:
- Login throttling — failed logins are rate-limited per IP, with a temporary lockout after repeated failures, so the password can't be brute-forced from the open internet.
- CSRF / Origin checks — state-changing requests must come from the same origin (a belt to the SameSite session cookie's braces).
- Home Assistant proxy allowlist — the optional HA proxy forwards only a small set of endpoints (sensor reads, history, notifications), never HA config, admin or service-restart.
- Audit log — security-relevant events (logins, setting and token changes, restores, proxy denials) are written to the server's stderr/log, without ever recording passwords, tokens or cookies.
- The development test page is LAN-only, and the
Serverheader doesn't advertise the Python version.
The security card in Settings shows what IP address each connection appears to come from. If legitimate requests show up as a public IP (NAT hairpin, a CDN, a VPN), add those ranges as trusted networks (in the UI, or with --trust CIDR on the command line) so they count as LAN.
Behind Cloudflare, enable the CF-Connecting-IP option so the real client IP is used instead of a Cloudflare edge address — but only when your domain genuinely runs through Cloudflare, otherwise that header is client-spoofable.
- On a trusted LAN with no port-forwarding, you can skip the password entirely.
- For serious internet exposure, put MeadOS behind a reverse proxy with its own auth (Caddy, nginx, or a VPN/Tailscale). That's the more battle-tested outer layer; the built-in password is the inner one.
- Set Public URL (Settings → Server Data) so share links and QR codes use your external address.
- The original client IP is read from
X-Forwarded-Forwhen behind a proxy.
The only external asset is Google Fonts. Chart.js and the QR library are self-hosted, so charts and the bottle scanner work offline too — without internet, fonts simply fall back to system defaults and everything else keeps working.
Run server.py under your OS's service manager so it starts at boot and restarts if it stops.
/etc/systemd/system/meados.service:
[Unit]
Description=MeadOS server
After=network.target
[Service]
User=youruser
WorkingDirectory=/home/youruser/MeadOS
ExecStart=/usr/bin/python3 /home/youruser/MeadOS/server.py --port 8080
Restart=always
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now meados
journalctl -u meados -f # logs (and the audit lines)~/Library/LaunchAgents/com.meados.server.plist (a LaunchAgent starts at login; use /Library/LaunchDaemons/ owned by root for a machine that boots without logging in):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>com.meados.server</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/youruser/MeadOS/server.py</string>
<string>--port</string><string>8080</string>
</array>
<key>WorkingDirectory</key><string>/Users/youruser/MeadOS</string>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>StandardOutPath</key><string>/Users/youruser/Library/Logs/meados.log</string>
<key>StandardErrorPath</key><string>/Users/youruser/Library/Logs/meados.log</string>
</dict></plist>launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.meados.server.plist
launchctl bootout gui/$(id -u)/com.meados.server # stop/removenohup python3 server.py >> meados.log 2>&1 &- Backups & Data — protect the database
- Home Assistant — the HA proxy and token handling
Copyright © 2026 icemanxbe - https://github.com/icemanxbe/MeadOS
Crafted with patience — like mead.
Plan carefully. Brew confidently. Age beautifully.
Getting going
Using MeadOS
- Recipes & Designer
- Batches & Fermentation
- Brewing Tools
- Formulas & Methods
- Libraries
- Cellar & Inventory
- Labels, Sharing & Calendar
Running it well
Help