From 7194aaf7e96189c85457d47e9e33590349a33cce Mon Sep 17 00:00:00 2001 From: marc Date: Sat, 20 Jun 2026 16:48:02 +0200 Subject: [PATCH] Move config files to /etc/micronas/, fix WebDAV passwd permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /etc/micronas.env → /etc/micronas/micronas.env - /etc/micronas-webdav.passwd → /etc/micronas/webdav.passwd - _save_credentials creates /etc/micronas/ if missing - _write_webdav_conf: chown root:www-data on passwd file so Apache can read it - micronas.service EnvironmentFile updated - README: credentials now set via /setup, config dir step added Co-Authored-By: Claude Sonnet 4.6 --- README.md | 13 ++++++------- app.py | 9 ++++++--- micronas.service | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e976c06..c5dc1ad 100644 --- a/README.md +++ b/README.md @@ -44,16 +44,15 @@ python3 -m venv /opt/micronas/venv /opt/micronas/venv/bin/pip install flask gunicorn ``` -### 4. Credentials +### 4. Config directory ```bash -cat > /etc/micronas.env <:5000` — you will be redirected to the login page automatically. Credentials come from `MICRONAS_USER` / `MICRONAS_PASS` in `/etc/micronas.env`. If `MICRONAS_PASS` is not set the app starts unprotected and logs a warning — do not do this in production. +All routes require a login session. On first run you are redirected to `/setup` to create the admin account. Credentials are stored hashed in `/etc/micronas/micronas.env`. The WebDAV htpasswd file lives at `/etc/micronas/webdav.passwd` (readable by `www-data`, not world-readable). --- diff --git a/app.py b/app.py index cdf42ee..a5bddc6 100644 --- a/app.py +++ b/app.py @@ -17,7 +17,8 @@ VALID_NAME = re.compile(r'^[A-Za-z0-9_-]+$') VALID_NFS_CLIENT = re.compile(r'^[A-Za-z0-9.*:/\-]+$') ALLOWED_PATH_BASE = Path('/srv').resolve() -_ENV_FILE = '/etc/micronas.env' +_CONF_DIR = '/etc/micronas' +_ENV_FILE = '/etc/micronas/micronas.env' # Mutable credential store — updated by setup/change without restart (single gunicorn worker). _creds = { @@ -48,6 +49,7 @@ def _verify_password(password): def _save_credentials(user, password): h = _hash_password(password) + os.makedirs(_CONF_DIR, exist_ok=True) Path(_ENV_FILE).write_text(f'MICRONAS_USER={user}\nMICRONAS_PASS_HASH={h}\n') os.chmod(_ENV_FILE, 0o600) _creds['user'] = user @@ -291,7 +293,7 @@ def add_nfs_share(path, clients, ro=False): # ===== WEBDAV ===== WEBDAV_CONF = '/etc/apache2/conf-available/micronas-webdav.conf' -WEBDAV_PASSWD = '/etc/micronas-webdav.passwd' +WEBDAV_PASSWD = '/etc/micronas/webdav.passwd' _WEBDAV_MARK = 'MICRONAS' @@ -340,9 +342,10 @@ def _write_webdav_conf(shares): ] with open(WEBDAV_CONF, 'w') as f: f.writelines(lines) - # Ensure the passwd file exists so Apache doesn't 500 before any user has logged in + # Ensure passwd file exists and is readable by www-data (Apache) but not world-readable if not os.path.exists(WEBDAV_PASSWD): Path(WEBDAV_PASSWD).touch(mode=0o640) + subprocess.run(['chown', 'root:www-data', WEBDAV_PASSWD], capture_output=True) subprocess.run(['a2enconf', 'micronas-webdav'], capture_output=True) subprocess.run(['systemctl', 'reload', 'apache2'], capture_output=True) diff --git a/micronas.service b/micronas.service index 68663f6..1b3432f 100644 --- a/micronas.service +++ b/micronas.service @@ -7,7 +7,7 @@ Wants=smbd.service nfs-server.service Type=simple User=root WorkingDirectory=/opt/micronas -EnvironmentFile=/etc/micronas.env +EnvironmentFile=/etc/micronas/micronas.env ExecStart=/opt/micronas/venv/bin/gunicorn -w 1 -b 0.0.0.0:5000 app:app Restart=on-failure RestartSec=5