This document describes how to migrate dependencies from GitHub (github.com/synrc)
to a locally managed Gitea instance for local development and build reproducibility
on macOS/Windows/Linux. This Gitea instance is also used as source of truth for
ArgoCD cluster controller.
Run these commands in order after every macOS reboot or fresh cluster setup:
./gitops.sh all # 1. Start local Gitea and mirror GitHub repos
./kind.sh create synrc # 2. Create the KinD cluster (auto-generates kind-config.yaml for current user)
./kind.sh kind # 3. Switch kubectl to the KinD context
kubectl config current-context # Verify: kind-synrc
kubectl get nodes # Verify: synrc-control-plane Ready
./rebuild.sh # 5. Build all custom ERP images from local Dockerfiles and load into KinD (pulls source from local Gitea via host.docker.internal:3000)
./deploy.sh # 4. Deploy base layer (namespaces, RBAC, storage, infra services)
./values.rb --force # 6. Generate unified Helm values
./argocd.sh # 7. Deploy ArgoCD + push CD repo to Gitea + set up port-forwardNOTE: M1/ARM64.
./kind.sh createautomatically regenerateskind-config.yamlusing your current$HOME, so thehostPathfor local storage is always correct regardless of which user is running the script.
NOTE: COLD PULL. On the first run, ArgoCD pulls ~186 MB of ARM64 images. The rollout timeout is set to 300 s. If it still times out, all pods will be Running shortly after — just re-run
./argocd.sh(it is idempotent).
./delete.sh
./gitops.sh all
./kind.sh create synrc
./kind.sh kind
./rebuild.sh
./deploy.sh
./values.rb --force
./argocd.sh-
Lightweight & Fast: SQLite-backed Gitea starts in under 5 seconds and uses minimal resources (less than 100MB of RAM), making it ideal for local MacBook environments.
-
Local Reproducibility: Pulling from in-cluster or local resources avoids rate limits, network failures, or dependency drift due to deleted external repositories.
-
No Web Install Wizard Required: Custom configuration variables pre-seed Gitea and bypass the installation screen completely.
The problem it solves:
- kubectl apply from CI/CD is fragile
- No source of truth for what's running
- Manual syncing between Git and cluster
- Can't audit who deployed what
Key concepts:
- GitOps: Git is source of truth for cluster state
- Continuous sync: ArgoCD keeps cluster matching Git
- Rollback: Revert to any previous commit
When to use it:
- Want declarative deployments
- Need visibility into what's deployed
- Multiple environments to manage
When to skip it:
- CI/CD pipeline works fine
- Team isn't ready for GitOps
All steps (startup, user creation, org/repo creation, and mirroring) are automated by the gitops.sh script.
Run the script with the all command: ./gitops.sh all, This performs the following actions:
- Starts the Gitea container via compose/gitea.yaml.
- Provisions the admin user (
rootwith passwordErpUnoGitea2026). - Creates the
synrcorganization. - Initializes repositories for
ca,ns, andldap. - Performs a bare-clone from GitHub and mirrors all branches/tags directly to Gitea.
You can verify Gitea is running and populated by visiting: http://localhost:3000/synrc
The Dockerfiles for ca-pki, ns-dns, and ldap-directory have been updated to accept a build argument GIT_SOURCE.
By default, the Dockerfiles assume Gitea is running on the host machine and use host.docker.internal:3000 to access it:
ARG GIT_SOURCE=http://host.docker.internal:3000
RUN git clone ${GIT_SOURCE}/synrc/ca.git .Docker Desktop automatically resolves host.docker.internal to the host machine during docker build.
Use ./rebuild.sh to build every service that has a build.sh in lib/ and load the
resulting image directly into the KinD cluster:
./rebuild.shThis script:
- Resets and re-creates the in-cluster
docker-registry - Finds every
lib/**/build.shand runsdocker build+kind load docker-image - Re-runs
./deploy.shto bring updated pods online
If Gitea is running on a different server or IP, you can override the source URL during build using --build-arg:
docker build --build-arg GIT_SOURCE=http://192.168.1.50:3000 -t erpuno/ca-pki:latest .- Check Status:
./gitops.sh statusCheck container and migrated repository health - Stop Gitea:
./gitops.sh stopShutdown the container - Start Gitea:
./gitops.sh setup - Force Re-Migration:
./gitops.sh migratePull fresh updates from GitHub and overwrite Gitea contents - Rebuild all images:
./rebuild.sh - Inspect registry:
./images.shor./images.sh --local(also shows KinD-loaded images)
To verify and execute GitOps deployments inside the Kind cluster using ArgoCD:
-
Publish the CD repository to Gitea:
The
cdrepository containing your deployment manifests and Helm chart must be hosted in Gitea. Running the./argocd.shscript automatically handles Gitea repository creation and pushes the current local repository state. -
Deploy ArgoCD and application:
Initialize ArgoCD by running the setup script:
./argocd.sh
This script installs ArgoCD into the
argocdnamespace, configures an Ingress resource (using the cluster's Traefik ingress controller) for access, and deploys theerp-unoroot Application pointing to thehelm/directory. -
Accessing the ArgoCD Console:
Add the domain name resolution to your host machine's
/etc/hostsfile:127.0.0.1 argocd.erp-uno.localNavigate to http://argocd.erp-uno.local.
To obtain the auto-generated ArgoCD admin password:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
If the UI domain is not accessible (or you cannot edit /etc/hosts), you can port-forward the server port directly to your host:
kubectl port-forward -n argocd svc/argocd-server 8080:80The console will then be accessible at http://localhost:8080. To make this port forwarding tunnel permanent on macOS (surviving restarts and running automatically in the background), install the provided LaunchAgent configuration:
cp argocd/uno.erp.argocd-portforward.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/uno.erp.argocd-portforward.plistTo use the ArgoCD command-line tool (CLI) on macOS:
brew install argocdWith the port forwarding tunnel running, retrieve the credentials and authenticate the client:
PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d)
argocd login localhost:8080 --insecure --username admin --password "$PASSWORD"Once logged in, the context is stored locally and you can manage the sync state of the application directly:
# Check the application status
argocd app get erp-uno
# Trigger manual synchronization
argocd app sync erp-unoNote: If you run these commands without first logging in (or if the config file context is not found),
you will receive a fatal "Argo CD server address unspecified" error. You can bypass this by explicitly
providing the server address and security flags on every execution:
# Get application status directly
argocd --server localhost:8080 --insecure app get erp-uno
# Trigger manual synchronization directly
argocd --server localhost:8080 --insecure app sync erp-uno