This guide covers deploying IntuneGet on your own infrastructure.
IntuneGet supports two self-hosting modes:
| Mode | Packaging Pipeline | Best For |
|---|---|---|
| GitHub Actions (default) | GitHub Actions Windows runners | Simpler setup, no Windows server needed |
| Local Packager | Self-hosted Windows machine | True self-hosting, air-gapped environments |
Before you begin, ensure you have:
- Supabase Account - supabase.com (required only when
DATABASE_MODE=supabase) - Microsoft Entra ID - Access to create app registrations
- GitHub Account - For the packaging pipeline (GitHub Actions mode only)
- Docker (optional) - For containerized deployment
- Windows Machine - For local packager mode only
The simplest way to self-host IntuneGet.
# Clone the repository
git clone https://github.com/ugurkocde/IntuneGet.git
cd IntuneGet
# Copy environment template
cp .env.example .env.local
# Edit .env.local with your configuration (see Configuration section below)
# Start the application
docker-compose up -dThe application will be available at http://localhost:3000.
Note on environment variables and Docker: The Docker image is built without any
NEXT_PUBLIC_*environment variables baked in. Instead, these values are injected at runtime when the container starts. This means you only need to set your variables in theenvironmentsection ofdocker-compose.yml(or in a.envfile that Docker Compose loads). No build arguments or custom image builds are required. See How Runtime Environment Injection Works for technical details.
Deploy directly to Vercel for a managed hosting experience.
- Fork the repository
- Create a new project in Vercel
- Connect your forked repository
- Add environment variables in Vercel dashboard
- Deploy
For other hosting providers or bare metal.
# Clone and install
git clone https://github.com/ugurkocde/IntuneGet.git
cd IntuneGet
npm install
# Build for production
npm run build
# Start production server
npm startFor process management, use PM2:
npm install -g pm2
pm2 start npm --name "intuneget" -- start
pm2 save| Variable | Description |
|---|---|
DATABASE_MODE |
supabase (default) or sqlite |
NEXT_PUBLIC_AZURE_AD_CLIENT_ID |
Azure AD application ID |
AZURE_AD_CLIENT_SECRET |
Azure AD client secret (AZURE_CLIENT_SECRET also supported) |
NEXT_PUBLIC_URL |
Your application's public URL |
If DATABASE_MODE=supabase, also set:
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anonymous key |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key |
If DATABASE_MODE=sqlite, also set:
| Variable | Description |
|---|---|
PACKAGER_API_KEY |
Shared key between web app and local packager API mode |
| Variable | Description |
|---|---|
PACKAGER_MODE |
github (default) or local |
GITHUB_PAT |
GitHub PAT (required for github mode) |
GITHUB_OWNER |
GitHub username/org (required for github mode) |
GITHUB_WORKFLOWS_REPO |
Private repository containing packaging workflow (required for github mode) |
GITHUB_REPO |
Public repository name (optional, for reference) |
CALLBACK_SECRET |
Secret for webhook verification (github mode) |
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_PLAUSIBLE_DOMAIN |
Plausible analytics domain | (disabled) |
BEEHIIV_API_KEY |
Newsletter integration | (disabled) |
See DATABASE_SETUP.md for detailed Supabase configuration.
Quick start:
- Create a Supabase project at supabase.com
- Run the SQL migrations from the
supabase/migrationsfolder - Copy the project URL and keys to your
.env.local
See AZURE_AD_SETUP.md for detailed instructions.
Quick start:
- Create a multi-tenant app registration
- Add required API permissions
- Create a client secret
- Copy the client ID and secret to your
.env.local
See GITHUB_ACTIONS_SETUP.md for detailed instructions.
Quick start:
- Fork the IntuneGet repository
- Create a Personal Access Token with
repoandworkflowscopes - Add secrets to your private workflows repository (
GITHUB_WORKFLOWS_REPO) - Update
.env.localto point to your fork
After deployment, update:
NEXT_PUBLIC_URLin your environment variables- Redirect URIs in your Azure AD app registration
For true self-hosting without GitHub Actions dependency, use the local packager.
Set in your web app's environment:
PACKAGER_MODE=localOn a Windows machine with Node.js 18+:
# Install globally
npm install -g @ugurkocde/intuneget-packager
# Or use npx
npx @ugurkocde/intuneget-packagerCreate a .env file in your packager working directory:
# Recommended API mode (for sqlite web mode)
INTUNEGET_API_URL=https://your-intuneget-instance.com
PACKAGER_API_KEY=your-packager-api-key
# Azure AD (same credentials as web app)
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
# Optional Supabase mode (for supabase web mode)
# SUPABASE_URL=https://your-project.supabase.co
# SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Optional
PACKAGER_ID=packager-01
POLL_INTERVAL=5000# Start with verbose logging
intuneget-packager --verbose
# Or run as a Windows service (see packager README)Check the packager health endpoint:
curl https://your-intuneget-instance.com/api/packager/healthExpected response:
{
"status": "healthy",
"mode": "local",
"stats": {
"activePackagers": 1,
"queuedJobs": 0
}
}For more details, see the Packager README.
Next.js normally inlines NEXT_PUBLIC_* environment variables into the client
JavaScript bundle at build time. In a Docker deployment the image is built
once (without tenant-specific values), so those variables would be empty in the
browser.
IntuneGet solves this with a runtime injection mechanism:
- The root
layout.tsx(a server component) readsprocess.envat request time and renders a<script>tag that setswindow.__RUNTIME_CONFIG__with the current value ofNEXT_PUBLIC_AZURE_AD_CLIENT_ID. - Client-side code (
lib/runtime-config.ts) callsgetPublicClientId(), which checkswindow.__RUNTIME_CONFIG__first and falls back toprocess.envfor Vercel and local development builds where the value is already inlined.
This means:
- Docker / self-hosted: Pass
NEXT_PUBLIC_AZURE_AD_CLIENT_IDin the container'senvironmentsection. It will be read from the server process at runtime and forwarded to the browser automatically. No build arguments or custom Dockerfile changes are needed. - Vercel / local development: The standard
NEXT_PUBLIC_*build-time behavior works as usual. The runtime config layer is a transparent no-op.
server {
listen 80;
server_name intuneget.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}intuneget.yourdomain.com {
reverse_proxy localhost:3000
}
For production deployments, always use HTTPS:
- Vercel: Automatic SSL
- Docker + Caddy: Automatic Let's Encrypt
- Docker + Nginx: Use certbot or similar
The application exposes a health endpoint:
curl http://localhost:3000/api/healthResponse:
{
"status": "degraded",
"mode": "self-hosted",
"services": {
"database": true,
"auth": true,
"pipeline": false
}
}To update your self-hosted instance:
# Pull latest changes
git pull origin main
# Rebuild and restart
docker-compose down
docker-compose build --no-cache
docker-compose up -d- Check environment variables are set correctly
- Verify Supabase connection:
curl $NEXT_PUBLIC_SUPABASE_URL/rest/v1/ - Check logs:
docker-compose logs -f
- Verify Azure AD app registration is multi-tenant
- Check redirect URIs match your deployment URL
- Ensure admin consent was granted
- If MSAL login redirects fail or the
client_idparameter is missing from authentication URLs, confirm thatNEXT_PUBLIC_AZURE_AD_CLIENT_IDis set in the Docker container's environment (see How Runtime Environment Injection Works)
- Verify GitHub PAT has correct scopes
- Verify
GITHUB_WORKFLOWS_REPOis configured and contains the packaging workflow - Verify
CALLBACK_SECRETmatches in both places
- GitHub Issues: github.com/ugurkocde/IntuneGet/issues
- Documentation: github.com/ugurkocde/IntuneGet/docs