Architecture

Repository Structure

CONFIG365 uses four repository types in your self-hosted Gitea instance. Understanding how they relate to each other is essential for operating and extending the platform.

4 min read Updated March 22, 2026

At a Glance

Repository Type
CONFIG365 Scripts + pipeline templates
Tenant-template Template for new tenants
baseline Config-only (JSON files)
Tenant-{name} Per-tenant repository

Total repos after setup: 1 main + 1 template + 1 baseline + N tenants = 3 + N

Repositories

orchestrator Platform repository (config365 org)

PowerShell scripts and reusable Gitea Actions workflow templates. Seeded automatically on first boot. Central reference for all MSP pipelines.

  • – .gitea/workflows/ — deploy-pipeline.yml, backup-pipeline.yml, maintenance-pipeline.yml
  • – scripts/graph-configs/ — deployment PowerShell scripts
  • – scripts/backup/ — backup PowerShell scripts
  • – scripts/common/ — shared utilities (auth, token handling)
tenant-template Template repository (MSP org)

Copy this repo to onboard a new tenant. Pre-configured Gitea Actions workflows that automatically load baseline configs.

  • – .gitea/workflows/ — pre-configured Gitea Actions workflows
  • – .baseline-ignore — optional: exclude specific baseline policies
baseline Configuration-only repository (MSP org)

Contains JSON policy files deployed to ALL tenants. No pipeline execution — purely configuration storage.

  • – baseline/ — configurations to CREATE or UPDATE
  • – baseline-remove/ — configurations to DELETE from tenants
  • – Subfolders: groups/, conditional-access/, intune/, exchange/, etc.
tenant-{slug} Tenant repository (one per tenant, MSP org)

Created automatically by the CONFIG365 portal when onboarding a tenant. Each tenant gets its own repo with isolated workflows and backups.

  • – .gitea/workflows/ — tenant Gitea Actions workflows (calls orchestrator templates)
  • – .baseline-ignore — optional: exclude specific baseline policies
  • – backups/ — daily backups auto-committed here

How It All Works Together

1

Pipeline triggers on the Tenant-{name} repository

2

Pipeline checks out the baseline repository — reads all JSON policy files

3

Pipeline checks out the CONFIG365 repository — loads PowerShell scripts

4

PowerShell scripts read JSON files from baseline/baseline/

5

Scripts deploy configurations to the tenant via Microsoft Graph API

6

Scripts process baseline/baseline-remove/ to delete stale resources

Baseline Repository Structure

baseline/
├── baseline/                    # Configurations to CREATE/UPDATE
│   ├── apps/
│   │   ├── chocolatey/          # Choco Win32 LOB app definitions
│   │   └── winget/              # WinGet Win32 LOB app definitions
│   ├── authentication-policies/
│   ├── conditional-access/
│   │   ├── named-locations/     # Named location JSON files
│   │   └── policies/            # CA policy JSON files
│   ├── custom-attributes/
│   │   ├── attribute-definitions/
│   │   └── attribute-sets/
│   ├── enterprise-apps/         # Entra ID service principal definitions
│   ├── entra-id-consentpermissions/
│   │   ├── permissionClassifications/
│   │   └── policies/
│   ├── entra-id-device-settings/
│   │   ├── device-registration-policy.json
│   │   └── entra-id-settings.json
│   ├── exchange/
│   │   ├── irm-configuration/
│   │   ├── ome-configuration/
│   │   └── transport-rules/
│   ├── groups/                  # Security group JSON definitions
│   ├── information-protection/
│   │   ├── sensitivity-labels/
│   │   ├── label-policies/
│   │   ├── label-policy-rules/
│   │   ├── auto-label-policies/
│   │   ├── auto-label-rules/
│   │   ├── dlp-policies/
│   │   └── dlp-rules/
│   ├── intune/
│   │   ├── app-protection/
│   │   ├── autopilot/
│   │   ├── compliance-policies/
│   │   ├── device-configurations/
│   │   ├── endpoint-security/
│   │   ├── filters/
│   │   ├── mobile-apps/
│   │   ├── platform-scripts-powershell/  # Windows PowerShell scripts
│   │   │   ├── *.json              # policy metadata (no base64)
│   │   │   ├── *.assignment.json   # assignment data
│   │   │   └── *.ps1               # plain-text script (companion)
│   │   ├── platform-scripts-bash/        # macOS Shell scripts
│   │   │   ├── *.json              # policy metadata (no base64)
│   │   │   ├── *.assignment.json   # assignment data
│   │   │   └── *.sh                # plain-text script (companion)
│   │   ├── settings-catalog/
│   │   ├── windows-feature-updates/
│   │   ├── windows-quality-updates/
│   │   └── windows-updates/
│   └── sharepoint-settings/
│       ├── sharepoint-tenant.json   # Graph API tenant settings
│       └── tenant-configuration/    # One JSON per Set-SpoTenant property
│
└── baseline-remove/             # Configurations to DELETE
    ├── conditional-access/
    ├── groups/
    ├── intune/
    └── custom-attributes/

Tenant Repository Structure

tenant-contoso/
├── .gitea/workflows/            # Gitea Actions workflow files
│   ├── deploy-pipeline.yml      # Deploy workflow (calls orchestrator templates)
│   ├── backup-pipeline.yml      # Backup workflow
│   └── maintenance-pipeline.yml # Maintenance workflow
├── .baseline-ignore             # Optional: exclude specific baseline policies
└── backups/                     # Daily backups (auto-committed by runner)
    ├── backup-manifest.json
    ├── authentication-policies/
    ├── conditional-access/
    ├── enterprise-apps/
    ├── entra-id-consentpermissions/
    ├── entra-id-device-settings/
    ├── exchange/
    ├── groups/
    ├── information-protection/
    ├── intune/
    └── sharepoint-settings/
        ├── sharepoint-tenant.json
        └── tenant-configuration/

Key Concepts

JSON configuration files

All M365 policies stored as individual JSON files in the baseline repo

Plain-text script files

Intune platform scripts stored as readable .ps1/.sh companion files alongside their JSON — base64 encoding happens at deploy time, never manually

PowerShell + Graph API

All deployments go through Microsoft Graph API via PowerShell scripts in the orchestrator repo

Automatic baseline loading

Tenant Gitea Actions workflows clone the baseline repo at runtime via act_runner — no manual sync needed

Per-tenant exclusions

Add a .baseline-ignore file in any tenant repo to exclude specific policies

Protection marker

Add CONFIG365:IGNORE to a resource description to prevent the automation from updating it