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:
- In Home Assistant: revoke
HA_LONG_LIVED_TOKENand mint a fresh one. Update the internal.env. - Regenerate the VAPID keypair:
Updateopenssl 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 '='VAPID_PUBLIC_KEYin.envand replace the file at_shared/keys/vapid-private.pem. Re-subscribe any active devices. - Mint a new fine-grained GitHub PAT scoped to
silenthooligan/localskyonly withcontents: write,packages: write,actions: write. Stash in the private overlay’s.envasGHCR_PAT. Do NOT reuse the existing PAT documented inaperturelabs-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.shThe 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.exampledocuments 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.5in 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.ymlthat pullsghcr.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:8090still 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.