Repository navigation
feat: production container, Render deployment, and cutover runbook (Hosting Interval E) - #50
Merged
Merged
Conversation
One non-root Uvicorn process in a python:3.13-slim image. The build context is an allow-list, so no database, attachment, credential, backup, .env, or context file can enter the image. The image defaults to hosted security mode and a /var/data/flipper data directory; the entrypoint refuses to start unless that directory is on a mounted volume, hands the root-owned disk to the app user, and drops privileges before exec. render.yaml defines only the new flipper-app service: one instance, a 1 GB persistent disk, GET /login as the health check, deploys of main after CI passes, and every secret as sync:false. The existing eBay compliance service is not part of the Blueprint.
Checks headers, HSTS, CSP, no-store, sign-in redirects, generic wrong password, __Host- cookie flags, CSRF origin checks, the public eBay route, hidden framework docs, and sign-out without changing any data. The password comes from the environment or a no-echo prompt and is never printed.
Builds the image, inspects it for data and secrets, proves it refuses to start without a volume or hosted secrets, runs the security smoke, checks the unprivileged user, proves persistence across restart and container replacement, and rehearses backup/verify/restore on the volume. Nothing deploys and no production secret is used.
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 37670708 | Triggered | Generic High Entropy Secret | 55fbd53 | tests/test_deployment.py | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hosting Interval E, repository part: everything needed to deploy the one private Flipper instance. Nothing is deployed by this PR, and no real data is involved.
What it adds
Dockerfile:python:3.13-slim-bookworm(the version CI tests) with the pinnedrequirements.txt. Runs one Uvicorn process (web.app:app, no workers, no reload,--no-proxy-headers, graceful shutdown) as non-root uid 10001. Image defaults fail closed:FLIPPER_WEB_SECURITY_MODE=hosted,FLIPPER_DATA_DIR=/var/data/flipper,FLIPPER_CREDENTIAL_BACKEND=file. Includesopenssh-sftp-serverand/root/.sshso Render's SSH/scp -scan move a verified backup at cutover. The image runs no SSH server of its own..dockerignore: an allow-list..env, databases, attachments, credentials, backups,context.md,.claude/, tests, docs, and.gitcannot enter the image.deploy/entrypoint.sh: refuses to start unless the data directory is on a mounted volume, so SQLite can never land on ephemeral disk. Gives the root-owned disk to the app user, setsumask 077, drops root withsetpriv, andexecs the command.deploy/flipper-cli(flipperon PATH): runs the CLI as the app user inside the container.deploy/smoke.py: read-only HTTPS security smoke covering headers, HSTS, CSP, no-store, sign-in redirects, generic wrong password,__Host-/Secure/HttpOnly/SameSite cookie, CSRF origin checks, the public eBay route, hidden framework docs, and sign-out.render.yaml: Blueprint for a newflipper-appservice only. Starter plan,numInstances: 1, 1 GB disk at/var/data, health checkGET /login, deploysmainonly after CI passes, and every secretsync: false.containerjob: builds the image, inspects it for data and secrets, proves it refuses to start without a volume or secrets, runs the smoke with synthetic secrets, checks the non-root uid, proves persistence across restart and container replacement, and rehearses backup, verify, restore, and verify-restore on the volume.docs/operations/deployment.mdcovers architecture, container, Render, environment and secrets, synthetic first deploy, real-data cutover, equivalence, authority transition, eBay reconnect, backups and disaster recovery, rollback, logs, and a phone checklist. Cross-links in the web-security, backup, and configuration docs and the README.Deliberately unchanged
flipper-zyui.onrender.com, standaloneebay.compliance:app) is not in the Blueprint and keeps working. Both services coexist, and the eBay developer account is untouched./loginis already public and serves as the health check, so the route classification table is unchanged.Verification
pytest: 802 passed, 4 skipped (the Blueprint path test is POSIX-only and runs in CI).ruff check .andruff format --check .pass;mkdocs build --strictpasses;git diff --checkis clean; tracked-ignored hygiene passes.git archiveof the tree.FLIPPER_DATA_DIRat the restored directory and restarting gives equivalent data.After merge (human actions)
Creating the Render service needs the owner's Render account (a paid Starter plan plus a disk, about USD 7.25/month) and an owner password chosen by the owner. The real-data cutover needs separate explicit approval. See the runbook.