Repository navigation
personal-site-2: vladmesh.dev: redirect old secretary project URL, 404 for unknown slugs, fix red CI (greenlet), retarget deploy to h01o - #34
Merged
Conversation
…el host
- frontend: middleware 301s /{en,ru}/projects/<old>/ to the current slug
from a data map (src/config/redirects.ts: secretary -> ummanu); an unknown
slug now returns 404 instead of throwing a 500.
- backend: depend on sqlalchemy[asyncio]. SQLAlchemy 2.1 ships greenlet only
in that extra, and poetry.lock is not committed, so a fresh resolve in CI
failed with "SQLAlchemy asyncio requires greenlet".
- deploy: ship infra/docker-compose.tunnel.yml + Caddyfile.tunnel (Cloudflare
Tunnel, no published ports) to ~/personal_site of an unprivileged user with
rootless Docker. No sudo, no registry login (public ghcr images), no prune,
pull only backend/frontend, and never write the host's .env (fail if it is
missing). VPS_* secrets now come from the production environment
(main only); add a smoke check through the public domain.
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.
Card:
personal-site-2— vladmesh.dev: redirect old secretary project URL, 404 for unknown slugs, fix red CI (greenlet), retarget deploy to h01oBranch:
pipeline/personal-site-2→mainWhat the card asks for
Goal
Follow-up to personal-site-1 (report in its completion record; site access notes in knowledge
projects/personal-site/access.md). Production vladmesh.dev runs on h01o (188.40.87.82, uservlad, rootless docker,~/personal_site, compose projectpersonal-site, ingress Cloudflare Tunnelpersonal-site-h01o). Three defects, one card:secretary->ummanu,/en/projects/secretary/and/ru/projects/secretary/return 500:[slug].astrothrows on an unknown slug. Add a permanent redirectsecretary->ummanufor both locales (a redirect map in middleware orastro.configredirects; keep it data-driven if the codebase allows). Make an unknown slug render 404, not 500.ImportError: SQLAlchemy asyncio requires greenlet.poetry.lockis gitignored, so a fresh resolve drops greenlet. Pinsqlalchemy[asyncio]orgreenletexplicitly in the backend dependencies, so CI is green from a fresh resolve..github/workflows/deploy.ymland theVPS_*secrets point at 185.81.166.84, which is gone. Retarget the deploy to the h01o layout so a merge to main deploys again:sudo docker/sudo chown;VPS_*secrets withgh secret set, using a deploy key that h01o'svladaccepts (~/.ssh/h01o_vlador a dedicated key you add tovlad's authorized_keys, recorded in access.md)..env. Today it rewrites.envfrom GitHub secrets:POSTGRES_PASSWORDmust match the existing DB, and the admin hash must be the PBKDF2 one now live (personal-site-1 set the matching GitHub secrets,$$-escaped). Either verify every value matches before the first run, or change the workflow to leave an existing.envalone.h01o is a friend's host. Its root docker daemon runs his production. Stay inside
vlad's home and rootless daemon. Never prune, restart docker, reboot or touch host config. Log host changes in/home/vlad/HOST_CHANGES.md. Commits carry no AI co-author trailer. The owner authorised these site changes (2026-10-02).Acceptance
curl -sI https://vladmesh.dev/en/projects/secretary/(and/ru/) is a 301/308 to/…/projects/ummanu/./en/projects/ummanu/and/ru/projects/ummanu/are still 200 with Ummanu, and admin login still works.What the worker reports
personal-site-2: done (one commit on pipeline/personal-site-2, no AI trailer)
1. Old project URL (500 -> 301) and unknown slug (500 -> 404)
services/frontend/src/config/redirects.ts: a data map of renamed project slugs (secretary: 'ummanu').services/frontend/src/middleware.ts:/{en,ru}/projects/<slug>with or without the trailing slash goes 301 to/{locale}/projects/<new>/when the slug is in the map.[slug].astro(en and ru): an unknown slug now returnsnew Response(null, {status: 404})(the documented Astro pattern) instead of throwing.2. CI red (greenlet)
services/backend/pyproject.toml:sqlalchemy = {extras = ["asyncio"], version = "^2.0.36"}. The installed SQLAlchemy 2.1.2 declaresgreenlet>=1; extra == "asyncio", so a fresh resolve without the extra has no greenlet.3. Deploy retargeted to h01o
infra/docker-compose.tunnel.ymlandinfra/configs/Caddyfile.tunnelmirror the live hand-made layout: projectpersonal-site, tunnel, caddy on :8080,/cvbind mount,/apiroute. The only difference is that frontend comes from ghcr instead ofpersonal-site-frontend:local.docker compose config --hash '*', which is read-only. The hashes of postgres, caddy and cloudflared match the live ones, and backend's hash is the same too. A deploy recreates only frontend, plus backend when its image changed.deploy:environment: production.~/personal_site(repo varDEPLOY_DIRcan override this) andDOCKER_HOST=unix:///run/user/$(id -u)/docker.sock.docker login(the ghcr packages are public, and a login would overwrite vlad's stored ghcr credential that codegen uses), no prune.docker compose pull backend frontend(only those two) anddocker compose up -d, then waits for health..env, and it fails if.envis missing.https://$SITE_DOMAIN/{en/,ru/,api/health}must be 200. All three return 200 today from the control host.bash -swith quoted heredocs, with no nested quoting.infra/.env.exampleupdated. No owner or host names were added to the repo, to keep the repo depersonalized.Secrets, key, host changes
~/.ssh/personal_site_h01o_deploy(SHA256:), added to vlad's authorized_keys withrestrict. I tested ssh and scp with it.gh secret set --env productionVPS_HOST=h01o.aipika.tech, VPS_USER=vlad, VPS_SSH_PORT=22, VPS_SSH_KEY. The existing emptyproductionenvironment is now limited to deployments frommain.sudo docker compose upin /opt. If repo-level VPS_* pointed at h01o, any run of the old workflow before this merge would start a stack on the friend's root daemon. So the repo-level VPS_* still point at the dead host. They can be deleted after the merge.REGISTRY_OWNER=vladmeshto~/personal_site/.env. Nothing else in it changed. Live config hashes were checked before and after and are unchanged, and no container was recreated.~/backups/personal-site/*-before-personal-site-2-*./home/vlad/HOST_CHANGES.md.ummanu knowledge write(instance commit eeaae9b63), with the deploy path, key, environment secrets, stale repo secrets, redirect map and the no-prune note.Checks
ImportError ... requires greenletat conftest. The workspace venv lacked greenlet, which is the defect this card fixes.sqlalchemy[asyncio]==2.1.2into the workspace v… (truncated; the full text is on the card)
Opened by the ummanu CI gate so that the
pull_requestworkflow runs. Title and body are built from the card and the worker's done report.