GitLab : Synch Projects Between Air-gap Networks
Q:
What is the advised Group structure for GitLab self-hosted when software development projects on its private domain are those of same on another private domain, with recurring updates, and the two domains are air gapped?
A:
For your GitLab self-hosted setup with two air-gapped private domains that share the same software development projects with recurring updates, the GitLab Group structure should be designed to ensure:
- Clear separation of concerns between domains.
- Efficient synchronization between the two air-gapped environments.
- Granular access control for teams and users.
- Scalability for future project growth.
Recommended Group Structure
1. Top-Level Groups per Domain
Create a top-level group for each air-gapped domain:
/DomainA
/DomainB
Each group represents one private domain's GitLab environment. This structure keeps administrative control separate between domains.
2. Mirrored Subgroups for Software Projects
Under each top-level group, create identically structured subgroups that mirror each other. For example:
/DomainA/SoftwareX
/DomainA/SoftwareY
/DomainB/SoftwareX
/DomainB/SoftwareY
Each subgroup represents a specific software that exists in both domains.
3. Repository-Level Project Syncing
Each software subgroup contains the actual repositories, such as:
/DomainA/SoftwareX/frontend
/DomainA/SoftwareX/backend
/DomainB/SoftwareX/frontend
/DomainB/SoftwareX/backend
This structure ensures that repositories stay identically structured between the two air-gapped environments, simplifying syncing and automation.
4. Special Synchronization Group (Optional)
If synchronization between the two domains is manual or handled via scripts, consider a dedicated synchronization group:
/SyncPipeline
This can contain: - Repositories for scripts that handle export/import of code updates. - Documentation related to the air-gapped transfer process. - Monitoring tools to track version consistency between environments.
Synchronization Between Domains
Since the domains are air-gapped, you need a manual or semi-automated process for transferring updates:
Export from Domain A
- Use
git bundle
or a GitLab repository export. - Export metadata such as merge requests (if needed).
- Use
Transfer to Domain B
- Physically transfer via USB, air-gapped transfer server, or secure file-sharing method.
- Import into GitLab on Domain B.
Validation
- Check the integrity of the transferred repositories.
- Run automated tests to ensure consistency.
Merge and Deploy
- Merge updates into Domain B's repositories.
- Deploy as needed.
User & Access Management
- Use group-level access controls to separate developers, maintainers, and administrators within each domain.
- Assign mirrored roles for users in both domains to maintain consistency.
- Consider SSO or LDAP integration if authentication needs to be centrally managed per domain.
Key Benefits of This Structure
✅ Consistency between domains despite air-gapping.
✅ Scalability for additional projects without restructuring.
✅ Granular security via GitLab’s group and project-level permissions.
✅ Easier synchronization using mirrored structures.
Would you like recommendations for automating the synchronization process between the air-gapped environments?
Q:
Some have argued that since Git is distributed, having dual repos per project is not justified; that it can and should be handled by git processes like merge.
A:
While Git’s distributed model works great in a connected world, an air-gapped environment introduces constraints that require a structured GitLab-based synchronization process.
Counterargument: Why Dual GitLab Repos Per Project are Justified in an Air-Gapped Environment
You're absolutely right that Git is inherently distributed, allowing developers to work with multiple remotes and branches rather than maintaining two separate GitLab repositories per project. However, in the case of air-gapped networks, the typical Git workflows—such as merging changes from a remote repository—face significant challenges due to the lack of direct network access.
Below are key reasons why keeping separate GitLab repositories (one per air-gapped domain) is justified:
1. Air-Gapped Constraints Prevent Direct Git Merge Workflows
How Git Normally Handles Multi-Environment Collaboration
In a standard Git setup, developers would: - Clone a shared remote repository. - Fetch and merge branches from the same upstream. - Push changes to a common repository.
Why This Doesn't Work in an Air-Gapped Setup
- No direct access to a shared Git server → Fetching and merging requires an internet or network connection between environments, which does not exist in air-gapped networks.
- Manual transfers are required → You can’t
git pull
from an air-gapped network; updates must be physically transferred (e.g., via USB or dedicated transfer hosts).
Because there is no common remote repository, keeping two GitLab repositories (one per domain) mimics the behavior of a single shared remote but allows synchronization via controlled transfers.
2. Security and Compliance Considerations
Many air-gapped environments exist for regulatory, security, or classified purposes (e.g., defense contractors, industrial control systems, financial institutions).
- A single Git repository spanning two domains would violate security policies if unauthorized data flows between them.
- Air-gapped transfers are typically subject to review and approval → Even if you could script Git fetches, changes require security clearance.
- Forensic tracking and change management need to be separate → Auditors often require a clear log of what was transferred and approved.
Keeping separate GitLab repositories ensures strict security and governance policies are followed when moving code across domains.
3. Avoiding Cross-Environment Merge Conflicts and Pollution
Git’s distributed nature assumes an open flow of commits, but in an air-gapped setup, repositories evolve independently, often in different timeframes.
- Domain A may apply security patches first → If developers merge and push back to Domain B without synchronization policies, they could overwrite necessary changes.
- Domain B may introduce environment-specific changes → Hardcoded configurations, deployment scripts, or access policies differ between domains.
- Merging without controlled synchronization can break both environments → Developers need to control when and how updates get merged.
By having separate GitLab repositories, each environment can stabilize updates before syncing, preventing environment-specific issues from leaking across domains.
4. Maintaining an Organized, Repeatable Sync Process
Git is flexible, but a structured GitLab-based approach ensures repeatability:
Workflow | Pure Git Approach | Dual GitLab Repos Approach |
---|---|---|
Synchronization | Manual git format-patch & git am per repo |
Automated GitLab-based import/export using git bundle |
Metadata Transfer | Requires custom scripts to move issues & MRs | GitLab API handles metadata syncing |
Security Controls | Requires strict ACLs per Git remote | Each GitLab repo enforces separate policies |
Air-Gap Compliance | No inherent controls in git push |
GitLab project approval workflows ensure compliance |
Having dual GitLab repositories helps maintain an automated, repeatable, and secure process without requiring direct network connectivity.
5. Practical Experience from Air-Gapped Environments
Many organizations already follow this structure in air-gapped setups:
US DoD & Defense Contractors
- Maintain separate repositories for classified and unclassified networks.
- Code must be reviewed before being manually transferred between domains.
Financial Institutions (e.g., Banks, Insurance Companies)
- Keep internal GitLab repos separate from vendor-controlled repos.
- Transfers happen through compliance-reviewed air-gap processes.
Industrial Control Systems (ICS/SCADA)
- IT (Internet-connected) and OT (Operational, air-gapped) environments do not share repositories directly.
- All updates must be signed, reviewed, and manually imported.
Each of these industries could use a single Git repository in theory, but operational security requires dual repositories.
Conclusion: Git Alone is Not Enough in an Air-Gapped Setup
While Git’s distributed model works great in a connected world, an air-gapped environment introduces constraints that require a structured GitLab-based synchronization process.
Key Takeaways:
✅ Separate GitLab repositories ensure compliance with air-gap security policies.
✅ GitLab-based sync workflows prevent accidental overwrite and maintain control over merges.
✅ Environment-specific changes and delays in patching require controlled synchronization.
✅ An air-gapped sync process using GitLab tools is easier to automate than raw Git workflows.
👉 For non-air-gapped setups, a single Git repository makes sense.
👉 For air-gapped domains, dual GitLab repositories are the best practice.
Q:
Mismatches of GroupX/.../ProjectY paths between Domains A and B are handled simply at git remote add origin ... ?
A:
Handling Mismatches in GitLab Group Paths Between Air-Gapped Domains
Yes, mismatches in repository paths between Domain A and Domain B can be handled at the git remote add origin ...
level when syncing repositories across air-gapped environments.
However, you need to carefully map paths between the two domains to avoid breaking synchronization workflows.
1. Simple Path Mapping at git remote add origin
If Group paths differ but Project names remain the same, you can manually adjust the remote URL when syncing.
Example: Different GitLab Group Paths
Domain | Path Structure |
---|---|
Domain A | /SoftwareA/BackendProject.git |
Domain B | /Infrastructure/Backend.git |
How to Handle This in Git
On Domain A:
git clone --mirror https://git.domainA.lan/SoftwareA/BackendProject.git
cd BackendProject.git
git bundle create backend.bundle --all
Move the backend.bundle
file to Domain B via USB or a secure offline method.
On Domain B, restore the repository with a different path:
git clone --mirror backend.bundle Backend.git
cd Backend.git
git remote add origin https://git.domainB.lan/Infrastructure/Backend.git
git push --mirror origin
This effectively re-maps the project from /SoftwareA/BackendProject
on Domain A to /Infrastructure/Backend
on Domain B.
2. Handling Path Differences Across Multiple Repositories
For multiple repositories, you can automate the remapping using a script.
Mapping Config File (repo_mapping.txt
)
# Format: SourceRepo,TargetRepo
SoftwareA/BackendProject,Infrastructure/Backend
SoftwareA/FrontendProject,Infrastructure/Frontend
Automated Transfer Script
#!/bin/bash
DOMAIN_A="git.domainA.lan"
DOMAIN_B="git.domainB.lan"
TRANSFER_DIR="/transfer"
mkdir -p $TRANSFER_DIR
while IFS=',' read -r SOURCE_REPO TARGET_REPO; do
echo "Exporting $SOURCE_REPO..."
git clone --mirror "https://$DOMAIN_A/$SOURCE_REPO.git" "$TRANSFER_DIR/$SOURCE_REPO.git"
cd "$TRANSFER_DIR/$SOURCE_REPO.git"
git bundle create "$TRANSFER_DIR/$TARGET_REPO.bundle" --all
cd -
done < repo_mapping.txt
echo "Transfer the bundles manually, then run the import script on Domain B."
Import Script on Domain B
#!/bin/bash
DOMAIN_B="git.domainB.lan"
TRANSFER_DIR="/transfer"
while IFS=',' read -r SOURCE_REPO TARGET_REPO; do
echo "Importing $TARGET_REPO..."
git clone --mirror "$TRANSFER_DIR/$TARGET_REPO.bundle" "$TARGET_REPO.git"
cd "$TARGET_REPO.git"
git remote add origin "https://$DOMAIN_B/$TARGET_REPO.git"
git push --mirror origin
cd -
done < repo_mapping.txt
This script ensures:
✅ Repository paths are automatically remapped.
✅ Human error is reduced in the transfer process.
✅ Multiple repositories can be synced in bulk.
3. Handling Group and Namespace Renaming at GitLab Level
If renaming paths at git remote add origin
isn't ideal, another approach is to modify GitLab namespaces on the receiving domain.
Method 1: Rename GitLab Groups on Domain B
- If you control Domain B’s GitLab instance, you can rename groups to match Domain A.
In GitLab UI, go to:
GitLab → Groups → Edit Group → Change Group Path
This keeps repository URLs identical and avoids remapping.
Method 2: Use GitLab Repository Mirroring (If Allowed)
- If a temporary network connection exists between Domain A and B, GitLab’s pull mirroring can sync repositories even if paths differ.
- Set up a push mirror on Domain A or a pull mirror on Domain B, adjusting repository paths accordingly.
4. Special Case: If Only Project Names Differ
If Group paths are the same, but Project names differ, the process is still simple.
Domain | Repository Path |
---|---|
Domain A | /SoftwareX/Backend.git |
Domain B | /SoftwareX/BackendAPI.git |
You can still handle this via:
git clone --mirror https://git.domainA.lan/SoftwareX/Backend.git
cd Backend.git
git remote add origin https://git.domainB.lan/SoftwareX/BackendAPI.git
git push --mirror origin
This maps Backend
(Domain A) → BackendAPI
(Domain B).
Final Thoughts
✅ Yes, mismatches in repository paths between domains can be handled via git remote add origin ...
.
✅ For multiple repositories, an automated mapping script ensures consistency.
✅ If managing GitLab instances, renaming groups or using mirroring can be alternatives.
Q :
Ansible Playbook that:
- Exports repositories from DomainA (GitLab Source).
- Transfers the
.bundle
files to a manually mounted directory (/mnt/usb
or another secure transfer medium). - Imports repositories into DomainB (GitLab Destination).
- Handles different repository paths between the two domains.