From 627795efce1924b35cd21237088e0cd57f0ba276 Mon Sep 17 00:00:00 2001 From: Ignace Date: Sun, 26 Jul 2026 11:17:19 +0200 Subject: [PATCH] updated for deployment on suy.nl --- README.md | 59 +++++++++++++++++------------------------------- requirements.txt | 3 +-- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 422decb..c5a7a31 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The app is served below `/fatima` by default. Configure the external path in ```yaml flask: - url_prefix: "/fatima" + url_prefix: "" # no prefix if site sits under fatima.suy.nl log_file: "/tmp/fatima.log" database: "instance/calendar.sqlite" ``` @@ -51,8 +51,8 @@ server (Waitress or Gunicorn). The following example targets a Debian/Ubuntu server using: -- `/srv/fatima` for the application and virtual environment -- `/etc/fatima/config.yaml` for secrets and application configuration +- `/srv/Fatima` for the application and virtual environment +- `/etc/Fatima/config.yaml` for secrets and application configuration - `/var/lib/fatima/calendar.sqlite` for persistent data - `/run/fatima/gunicorn.sock` for the private Gunicorn socket - `fatima.service` to run the application as an unprivileged `fatima` user @@ -67,17 +67,17 @@ Install the operating-system packages and create a service account: ```sh sudo apt update sudo apt install nginx python3 python3-venv -sudo useradd --system --user-group --home-dir /srv/fatima --shell /usr/sbin/nologin fatima +sudo useradd --system --user-group --home-dir /srv/Fatima --shell /usr/sbin/nologin fatima ``` -Copy or clone the repository into `/srv/fatima`, then create the virtual +Copy or clone the repository into `/srv/Fatima`, then create the virtual environment and install the dependencies. Gunicorn is an additional production dependency; Waitress remains suitable for the local command documented above. ```sh -sudo chown -R fatima:fatima /srv/fatima -sudo -u fatima python3 -m venv /srv/fatima/.venv -sudo -u fatima /srv/fatima/.venv/bin/pip install -r /srv/fatima/requirements.txt gunicorn +sudo chown -R fatima:fatima /srv/Fatima +sudo -u fatima python3 -m venv /srv/Fatima/.venv +sudo -u fatima /srv/Fatima/.venv/bin/pip install -r /srv/Fatima/requirements.txt gunicorn ``` For repeatable deployments, pin the Gunicorn version used by the server in your @@ -91,16 +91,11 @@ Generate a signing key: python3 -c "import secrets; print(secrets.token_hex(32))" ``` -Create `/etc/fatima/config.yaml` using `config.example.yaml` as a guide: - -```sh -sudo install -d -o root -g fatima -m 750 /etc/fatima -``` ```yaml flask: secret_key: "paste-the-generated-random-value-here" - url_prefix: "/fatima" + url_prefix: "" log_file: "/var/log/fatima/startup.log" database: "/var/lib/fatima/calendar.sqlite" @@ -117,8 +112,8 @@ amounts: Protect the file because it contains the login password and Flask signing key: ```sh -sudo chown root:fatima /etc/fatima/config.yaml -sudo chmod 640 /etc/fatima/config.yaml +sudo chown root:fatima /srv/Fatima/config.yaml +sudo chmod 640 /srv/Fatima/config.yaml ``` The systemd unit below creates `/var/lib/fatima`, `/var/log/fatima`, and @@ -140,9 +135,8 @@ Type=simple User=fatima Group=www-data SupplementaryGroups=fatima -WorkingDirectory=/srv/fatima -Environment=APP_CONFIG=/etc/fatima/config.yaml -ExecStart=/srv/fatima/.venv/bin/gunicorn \ +WorkingDirectory=/srv/Fatima +ExecStart=/srv/Fatima/.venv/bin/gunicorn \ --workers 2 \ --bind unix:/run/fatima/gunicorn.sock \ --umask 007 \ @@ -184,7 +178,7 @@ configuring Nginx, verify Gunicorn directly: ```sh sudo -u www-data curl --unix-socket /run/fatima/gunicorn.sock \ - --head http://localhost/fatima/ + --head http://localhost ``` A redirect to `/fatima/login` is the expected response when no authenticated @@ -204,38 +198,27 @@ server { listen [::]:80; server_name calendar.example.com; - location = /fatima { - return 301 /fatima/; - } - - location /fatima/ { - proxy_pass http://fatima_gunicorn; - proxy_http_version 1.1; + location / { + proxy_pass http://unix:/run/fatima/gunicorn.sock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; + + proxy_read_timeout 60s; } } ``` -There is deliberately no URI after `proxy_pass`: Nginx must forward -`/fatima/...` unchanged because Fatima's prefix middleware removes that prefix -before Flask routes the request. Do not rewrite it to `/`. - -Enable and validate the site: - ```sh sudo ln -s /etc/nginx/sites-available/fatima /etc/nginx/sites-enabled/fatima sudo nginx -t sudo systemctl reload nginx -curl --head http://calendar.example.com/fatima/ +curl --head http://calendar.example.com/ ``` -Add TLS before exposing the login publicly. Once the certificate is configured, -redirect HTTP to HTTPS and keep the same `/fatima/` proxy block in the TLS -server. The application stores authentication in a signed browser session, so +The application stores authentication in a signed browser session, so keep `secret_key` stable across restarts and deployments; changing it logs out all existing sessions. @@ -244,7 +227,7 @@ all existing sessions. After deploying new source or dependencies: ```sh -sudo -u fatima /srv/fatima/.venv/bin/pip install -r /srv/fatima/requirements.txt +sudo -u fatima /srv/Fatima/.venv/bin/pip install -r /srv/Fatima/requirements.txt sudo systemctl restart fatima sudo systemctl reload nginx ``` diff --git a/requirements.txt b/requirements.txt index 4f4e2d1..e192a26 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ Flask==3.1.1 PyYAML==6.0.2 openpyxl==3.1.5 -gunicorn - +gunicorn \ No newline at end of file