Repository navigation
Releases
v1.1.0
The first update since the release on October 11: the Python base image is pinned by digest, CI checks every build of the image against requirements.txt, and the README covers what to check after an update.
Upgrading from 1.0.0
docker-compose.yaml, .env.example, webserver/ and static/ are unchanged, and main.py only has the new version number, so a deployment of 1.0.0 updates in place: git pull and docker compose up -d --build, then the checks in After an update.
If you copied 1.0.0 into a project of your own:
- Take the
FROMline from theDockerfile. The Python base image is now pinned by digest and changes only through a pull request, so keep Dependabot on: without it the base image never gets updates, security fixes included. - Take
requirements.txtas a whole: it pins the full set the image was tested with. - If you take the CI workflow, take the
github-actionsentry in.github/dependabot.ymlwith it, so the action pinned by SHA keeps getting updates. - FastAPI 0.144 to 0.157 removed
openapi_prefixand extra keyword arguments fromFastAPI()and deprecatedroot_path. Sclerotin uses none of them, but code you added on top might.
What's changed
Build and updates
- Pin the Python base image by digest (#19). With the tag alone, the build checked it against Docker Hub every time, so a rebuilt
python:3.14.8-slimreached the server without passing CI (#15) - Add a CI workflow that builds the image, compares
pip freezewithrequirements.txtand runspip checkon every pull request and every commit tomain(#4, #18). Dependabot now updates the action it uses (#4)
Security policy
- Add
SECURITY.md: private reporting through GitHub, scope and supported versions (#3)
Documentation
- Add what to do after an update: the commit to return to, checks on the server and from another machine, and cleanup, including the previous Nginx image (#11, #20)
- Correct the README sentence that said the build reuses a cached Python base image (#19)
Dependencies
- Python from 3.14.7 to 3.14.8, an expedited security release (#7)
- FastAPI from 0.142.3 to 0.157.0 (#6, #8, #14)
- Starlette from 1.7.0 to 1.9.0 (#9, #13)
- Pydantic from 2.13.5 to 2.14.1 (#5, #10)
Full Changelog: v1.0.0...v1.1.0
v1.0.0
First public release. A hardened reference deployment of FastAPI behind Nginx with Docker Compose, running at https://sclerotin.args.tech
The application is one endpoint, trivial on purpose: the release is everything around it.
What's in place
- A Content Security Policy per kind of response:
default-src 'none'for the API, a policy of its own for the landing page, a relaxed one for the docs only while they are switched on - Security headers split between Nginx and the app, error responses included
- The app on an internal network with no route out of the host
- Read-only root filesystems, all capabilities dropped,
no-new-privileges, memory, CPU and PID limits, an unprivileged app user - Unknown host names and bare-IP requests dropped without an answer
- Per-address rate limits that see real IPv6 addresses, request size limits and timeouts against slow clients
- TLS 1.2 and 1.3 with Mozilla's intermediate profile, post-quantum hybrid key exchange (X25519MLKEM768) and HSTS; Let's Encrypt with automatic renewal
Pinned in this release
- Python 3.14.7 (slim), FastAPI 0.142.3, Uvicorn 0.54.0 and the rest of the dependency set in
requirements.txt nginx:stable-alpineby SHA256 digestopentelemetry-apiis pinned too: FastAPI 0.142 requires it. With no OpenTelemetry SDK in the image it stays inert, and the app has no route out anyway- Weekly Dependabot pull requests keep the pins current
Requirements
Docker Engine 27+ and Compose 2.17+, a rootful daemon without userns-remap. Why each of them is needed is in the README.
Check the live headers
curl -sD - https://sclerotin.args.tech/api/v1/ping
Every choice is explained in How it works.