Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Migrating LocalSky to a public GitHub repo

This document walks through the steps to take the internal aperturelabs/aperturelabs-localsky Gitea repo and publish a sanitized version at silenthooligan/localsky on GitHub. Follow in order; do not skip the rotation step.

Step 0: Secret rotation (do this first)

The internal repo has .env tracked with live tokens. Before publishing anything, treat the existing token set as leaked and rotate:

  1. In Home Assistant: revoke HA_LONG_LIVED_TOKEN and mint a fresh one. Update the internal .env.
  2. Regenerate the VAPID keypair:
    openssl ecparam -name prime256v1 -genkey -noout -out vapid-private.pem
    openssl ec -in vapid-private.pem -pubout -outform DER 2>/dev/null \
      | tail -c 65 | base64 -w0 | tr '+/' '-_' | tr -d '='
    
    Update VAPID_PUBLIC_KEY in .env and replace the file at _shared/keys/vapid-private.pem. Re-subscribe any active devices.
  3. Mint a new fine-grained GitHub PAT scoped to silenthooligan/localsky only with contents: write, packages: write, actions: write. Stash in the private overlay’s .env as GHCR_PAT. Do NOT reuse the existing PAT documented in aperturelabs-core-manager/secrets.md.

Step 1: Create the public repo

On GitHub, create silenthooligan/localsky empty + private. We flip to public only after the sanitization checks pass.

Step 2: Snapshot the working tree

mkdir -p /tmp/localsky-public-seed
git -C /home/erik/Development/aperturelabs/aperturelabs-localsky archive HEAD \
  | tar -x -C /tmp/localsky-public-seed
cd /tmp/localsky-public-seed

Remove tracking artifacts that should not be in the public repo:

rm -rf .git .gitea data _shared keys
rm -f .env *.pem

Step 3: Sanitize

TL;DR: run the bundled script.

cd /tmp/localsky-public-seed
./scripts/sanitize-for-public.sh

The script handles steps 3a-3d below automatically. The manual notes remain here for operators who want to understand or extend what’s happening.

Manual sanitize (if you’d rather)

Run these greps to find anything that needs replacing:

grep -rEi '192\.168\.|skean\.net|aperturelabs|LXC|VLAN' .

For each hit, decide:

  • Source code defaults (e.g. src/ha/rest.rs, src/llm/client.rs): replace internal IPs with empty strings; rely on env vars
  • docker-compose.yml: replace hardcoded IPs with ${VAR} references; the .env.example documents the variables
  • Comments: replace any internal-context comments (LXC names, VLAN refs, internal hostnames) with generic equivalents
  • Test fixtures: synthetic IPs like 192.168.1.5 in unit tests are fine; they don’t expose your deployment

Adopt the new public README + CONTRIBUTING + SECURITY + CHANGELOG + CODE_OF_CONDUCT files:

mv README.public.md README.md

The original README.md becomes docs/INTERNAL_NOTES.md (or just delete it; the new docs supersede it).

Step 4: Final verification

Re-run the sanitization grep. It must return zero hits:

grep -rEi '192\.168\.|skean\.net|aperturelabs|LXC|VLAN' .

Check git log does not include credential commits. Since we’re starting fresh, the new repo has one commit; no history scrubbing required.

Step 5: Initial commit + push

git init -b main
git add .
git commit -m "Initial public release of LocalSky"
# Author: silenthooligan <[email protected]>; no Co-Authored-By trailer
git remote add origin https://github.com/silenthooligan/localsky.git
git push -u origin main

Step 6: Re-verify externally

Clone the published repo fresh to a different directory and repeat the grep. Zero hits required before flipping the repo public.

Step 7: Set repo public

In repo settings on GitHub, change visibility to public.

Step 8: Configure the private overlay

Create aperturelabs/aperturelabs-localsky-deploy on the internal Gitea. Contents:

  • docker-compose.yml that pulls ghcr.io/silenthooligan/localsky:latest, mounts _shared/keys, references the internal HA URL and tokens via .env
  • .env (gitignored on public side; tracked here per internal convention)
  • .gitea/workflows/deploy-komodo.yml (copied from the original internal repo)
  • One-line README pointing to the public canonical repo

Komodo continues to deploy from this private overlay. When a new image is published to GHCR, a Gitea webhook bumps the image tag in the overlay and Komodo redeploys.

Step 9: Verify continuity

  • The owner’s homelab on LXC 281 now pulls from GHCR instead of the internal registry.
  • The dashboard at http://192.168.20.81:8090 still shows the same data.
  • Zone runs continue to fire on schedule.
  • Push notifications still arrive on subscribed devices.

If any of these break, the rotation step probably left a stale value somewhere. Check the internal .env against the public .env.example for every required key.

Step 10: Announce

Post on the homelab forum or similar that you’d like feedback from. The repo is ready for stars.