id: 0c1e140a415f4f4187e5acec77e7485c
parent_id: 
item_type: 1
item_id: a69d84030b1742ffb63ff3248a02cb92
item_updated_time: 1787985957991
title_diff: "[{\"diffs\":[[1,\"Hetzner Server — Audit & Container Setup (Plan)\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":47}]"
body_diff: "[{\"diffs\":[[1,\"# Hetzner Server — Audit & Container Setup (Plan)\\\n\\\n> Created 2026-08-29, topology corrected same day after grounding the git\\\n> remotes; private-repo policy added 2026-08-29. Mission: audit the Hetzner\\\n> machine, improve performance, set up the container platform (reverse proxy,\\\n> Forgejo role per below, optionally Jenkins) — **in the context of the real\\\n> topology: the FreeBSD basement server (192.168.1.2) is the current canonical\\\n> git hub running Jenkins on bare repos; Codeberg is a manual public mirror\\\n> for some repos.**\\\n\\\n## Repository topology (grounded 2026-08-29)\\\n\\\n| Repo | origin (canonical) | Public mirror |\\\n|---|---|---|\\\n| keyfob-station | FreeBSD server `~/Development/Repositories/keyfob-station.git` | **none — PRIVATE policy** (work-related; Hetzner mirror only) |\\\n| rusty_emu | FreeBSD server | Codeberg (manual dual-push) |\\\n| top_drives | FreeBSD server | Codeberg (manual dual-push) |\\\n| super-marvin (poker line) | FreeBSD server (to confirm on import) | **none — PRIVATE policy** (commercial edge; no public mirror) |\\\n\\\n**Target architecture (DECIDED direction 2026-08-29):**\\\n\\\n```\\\ndev machines --push--> FreeBSD Forgejo (canonical, jail, native binary)\\\n                          |--push-mirror--> Codeberg (public, per-repo opt-in ONLY)\\\n                          |--push-mirror--> Hetzner Forgejo (private backup + remote access + CI)\\\nJenkins (FreeBSD) --------+-- keeps working; re-point repo URLs after migration\\\nForgejo Actions runners --+-- on Hetzner only (Linux + Docker there; FreeBSD has no Docker)\\\n```\\\n\\\n- **Forgejo on FreeBSD = CANONICAL, not a mirror**: import the bare repos\\\n  into it (create repo → push the bare repo in → set push mirrors out).\\\n  Web UI + auth for what is already the origin; push mirrors AUTOMATE the\\\n  current manual Codeberg dual-push\\\n- **Hetzner = private pull-side/backup + Linux CI**: mirror target and the\\\n  only place Actions runners with containers can live\\\n- **Jenkins stays on FreeBSD** (native, already working); migrate jobs to\\\n  Actions only if/when it earns it — re-point existing jobs to Forgejo URLs\\\n  after the repo import\\\n\\\n**Private-repo mechanics (confirmed 2026-08-29):** per-repo visibility in\\\nForgejo (private/public at creation, toggleable in Settings or API\\\n`private: true`); set `DEFAULT_PRIVATE = true` in app.ini so public becomes\\\nthe explicit choice; deploy keys/tokens cover Jenkins, mirrors, agents.\\\nPush mirrors from private sources are fine — visibility is per instance, so\\\nthe private repos mirror to Hetzner only.\\\n\\\n## FreeBSD corrections (to earlier advice — important)\\\n\\\n- **No Docker on FreeBSD**: the container platform lives on Hetzner only.\\\n  FreeBSD containment = jails; Forgejo runs as the native Go binary (in a\\\n  jail), no containers needed\\\n- **Joplin desktop on FreeBSD: unverified** (Electron — ports/Linuxulator\\\n  unclear). If it doesn't run cleanly, the MCP host moves to Hetzner (Linux)\\\n  or stays on Windows — decide when wiring the server agents\\\n- Kilo CLI (Node) and Java (PD) should run on FreeBSD, but both unverified —\\\n  test before relying on them there\\\n\\\n## Phase 0 — Access & agent placement\\\n\\\n- [ ] Hetzner: Kilo CLI directly on the box (recommended for the audit);\\\n      SSH keys only\\\n- [ ] Joplin access for agents: tunnel to whichever host ends up running\\\n      the MCP server (see above — FreeBSD feasibility open)\\\n- [ ] FreeBSD box: agent access via SSH (already proven — git pushes)\\\n\\\n## Phase 1 — Audit (evidence-first, like the keyfob gate)\\\n\\\n- [ ] System inventory: OS, kernel, uptime, CPU/RAM/disk, virtualization\\\n- [ ] Service inventory: enabled units, listeners, timers (+ FreeBSD side:\\\n      Jenkins, sshd, anything else on 192.168.1.2)\\\n- [ ] Security posture: SSH config, firewall state, fail2ban,\\\n      unattended-upgrades, users/keys, Docker daemon exposure\\\n- [ ] Performance: top consumers, disk usage + I/O, journal size, swap\\\n- [ ] Docker hygiene: containers/images/volumes, prune candidates\\\n- [ ] Backups: what exists, what's missing — **including the bare repos on\\\n      FreeBSD (currently the single point of failure for ALL active repos!)**\\\n- [ ] Deliverable: audit report committed to the infra repo\\\n\\\n## Phase 2 — Harden + tune (per audit findings)\\\n\\\n- [ ] Firewall (default deny; SSH/proxy ports only), SSH hardening,\\\n      unattended-upgrades, fail2ban (Hetzner)\\\n- [ ] Performance fixes from findings\\\n- [ ] Repo backup closure: Forgejo import + Hetzner mirror removes the\\\n      single-copy risk for the repos\\\n\\\n## Phase 3 — Container platform (Hetzner) + Forgejo (both)\\\n\\\n- [ ] Hetzner: reverse proxy with TLS (Caddy/Traefik) first\\\n- [ ] FreeBSD: Forgejo native binary in a jail; import bare repos; set\\\n      push mirrors (Codeberg opt-in per repo; keyfob + super-marvin private\\\n      → Hetzner mirror only)\\\n- [ ] Hetzner: Forgejo as mirror target (private); Actions runners\\\n      (container-capable) — Jenkins vs Actions decision per repo, not global\\\n- [ ] Non-public services bound to localhost/WireGuard only\\\n\\\n## Phase 4 — Operate as a process-project\\\n\\\n- [ ] Infra repo: compose + jail configs in git; tagged releases = deployable\\\n- [ ] Status note in Joplin; link from the Development Projects Index\\\n- [ ] PSP logging optional for infra work (agent-captured if desired)\\\n\\\n## Security invariants (public server!)\\\n\\\n- Joplin MCP: never exposed — tunnel only\\\n- No database/admin UIs on public ports; proxy + auth everywhere\\\n- Agent credentials = SSH keys, stored nowhere in repos\\\n- **Private repos: keyfob-station and super-marvin (whole poker line) —\\\n  LAN + private Hetzner mirror only, never public forges, no Codeberg\\\n  mirrors; DEFAULT_PRIVATE=true on both Forgejo instances**\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":5611}]"
metadata_diff: {"new":{"id":"a69d84030b1742ffb63ff3248a02cb92","parent_id":"cd0501fe1cc24c93bc6bc3e783fb324fd","latitude":"0.00000000","longitude":"0.00000000","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":1787985230147,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","deleted_time":0,"is_locked":0,"extracted_resource_ids":""},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-08-29T06:49:34.502Z
created_time: 2026-08-29T06:49:34.502Z
is_locked: 0
type_: 13