Sharing Production Code with a Private Fork

This guide explains how to keep the public LUStores codebase as an upstream source while maintaining a private repository for your institution’s configuration, secrets, and customisations.

Overview

The strategy is a standard upstream/private git workflow:

[public: st7ma784/LUStores]  ←pull fixes── [private: your-org/lustores-private]
                                                      │
                                              your .env.prod, SAML keys,
                                              licence token, branding

Your private repo:

  • Tracks the public repo as a remote called upstream

  • Contains your .env.prod, SAML certificates, licence key, and any institution-specific patches on top

  • Is never pushed to the public repo — no secrets can leak

Note

The public main / deploy branches contain no secrets. All sensitive values live in .env.prod (git-ignored) and Helm values.yaml overrides (private repo only).

Step 1 — Create Your Private Repository

On GitHub, create a new private repository (e.g. your-org/lustores-private).

Important

Do not fork via the GitHub “Fork” button — that creates a public fork linked to the upstream. Instead, create a fresh private repo and push to it.

# Clone the public repo locally
git clone https://github.com/st7ma784/LUStores.git lustores-private
cd lustores-private

# Rename origin to upstream so the naming is clear
git remote rename origin upstream

# Add your private repo as origin
git remote add origin https://github.com/your-org/lustores-private.git

# Push all branches to your private repo
git push origin --all
git push origin --tags

Step 2 — Create a Private Config Branch

Keep your institution’s config on a dedicated branch so it rebases cleanly onto new upstream releases.

git checkout deploy          # start from the production branch
git checkout -b private/config

Now add your private files:

# Copy the example env file and fill in real values
cp .env.prod.example .env.prod
# edit .env.prod with your domain, DB password, secrets, SAML paths, licence key

# Make sure .env.prod stays private (it is already in .gitignore)
# Add any institutional patches, custom CSS, or SAML certificates here

git add .                    # .env.prod will NOT be added (gitignored)
git commit -m "chore: add institutional config"
git push origin private/config

Warning

Double-check that .env.prod is listed in .gitignore before committing. Run git status and confirm it shows as untracked, not staged.

Step 3 — Pull Upstream Fixes

When the public repo receives bug fixes or new features:

# Fetch latest public code (no secrets come from here)
git fetch upstream

# Update your local deploy branch
git checkout deploy
git merge upstream/deploy --ff-only   # fast-forward if no local commits

# Rebase your private config on top
git checkout private/config
git rebase deploy

# Push both branches to your private repo
git push origin deploy private/config

If there are rebase conflicts (rare, usually only in init.sql seed data):

# Resolve conflicts in your editor, then:
git add <conflicted-file>
git rebase --continue

Step 4 — Deploy from Your Private Branch

Your CI/CD pipeline should deploy from private/config, not deploy.

GitHub Actions — add a secret DEPLOY_TOKEN (a personal access token or deploy key with read access to your private repo), then set the checkout branch to private/config in your workflow:

- uses: actions/checkout@v4
  with:
    ref: private/config

Rancher / Fleet — point fleet.yaml at your private repo:

# helm/lustores/fleet.yaml
helm:
  repo: https://github.com/your-org/lustores-private
  branch: private/config

Docker Compose (manual) — SSH into your server and pull from your private repo, then deploy normally:

git clone --branch private/config \
    https://<token>@github.com/your-org/lustores-private.git /data/LUStores
cd /data/LUStores
docker compose -f docker-compose.prod.yml up -d

What Stays Private

File / Directory

Contains

Where it lives

.env.prod

DB password, JWT secret, session secret, domain

Private repo only (gitignored in public)

helm/lustores/values.yaml

Image tags, ingress config, resource limits

Override in private repo

SAML certificates / SP keys

IdP metadata, signing keys

Private repo only

Licence token

LICENCE_KEY env var value

.env.prod in private repo

Institution branding

Logo, colours, email templates

Custom commits on private/config

What Stays Public

  • All application source code (client/, server/, shared/)

  • Database schema (init.sql, migrations/)

  • Documentation

  • Docker / Helm templates (without values)

  • CI/CD workflow templates

Keeping Branches in Sync — Quick Reference

# Weekly: pull upstream fixes
git fetch upstream
git checkout deploy && git merge upstream/deploy --ff-only
git checkout private/config && git rebase deploy
git push origin deploy private/config

# Check nothing sensitive is staged
git diff --cached --name-only

# Verify .env.prod is NOT tracked
git ls-files .env.prod   # should return nothing