commit 814e41f3f22cb91103f3c0c4f1c3b639459c99ef Author: Greg Hendrickson Date: Sun Feb 1 20:03:45 2026 +0000 feat: Authentik Terraform configuration for homelab SSO Infrastructure as Code for Authentik identity provider managing: OAuth2/OIDC Applications: - Grafana, Home Assistant, Immich - Uptime Kuma (proxy auth) - Sonarr, Radarr, Prowlarr (*arr stack proxy auth) - ArgoCD Identity Sources: - Google Workspace federation LDAP: - TrueNAS LDAP provider and outpost CI/CD: - GitHub Actions workflow for plan/apply - Secrets managed via GitHub Actions secrets Provider: beryju/authentik v2025.2 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..63763ee --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,105 @@ +name: Deploy Authentik Configuration + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +env: + TF_VERSION: "1.7.0" + +jobs: + plan: + name: Terraform Plan + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Create secrets.auto.tfvars + run: | + cat > secrets.auto.tfvars << EOF + authentik_url = "${{ secrets.AUTHENTIK_URL }}" + authentik_token = "${{ secrets.AUTHENTIK_TOKEN }}" + + # Google OAuth (optional) + google_client_id = "${{ secrets.GOOGLE_CLIENT_ID }}" + google_client_secret = "${{ secrets.GOOGLE_CLIENT_SECRET }}" + + # Application URLs + argocd_url = "${{ secrets.ARGOCD_URL }}" + grafana_url = "${{ secrets.GRAFANA_URL }}" + home_assistant_url = "${{ secrets.HOME_ASSISTANT_URL }}" + immich_url = "${{ secrets.IMMICH_URL }}" + uptime_kuma_url = "${{ secrets.UPTIME_KUMA_URL }}" + sonarr_url = "${{ secrets.SONARR_URL }}" + radarr_url = "${{ secrets.RADARR_URL }}" + prowlarr_url = "${{ secrets.PROWLARR_URL }}" + EOF + + - name: Terraform Init + run: terraform init + + - name: Terraform Validate + run: terraform validate + + - name: Terraform Plan + run: terraform plan -out=tfplan + + - name: Upload Plan + uses: actions/upload-artifact@v4 + if: github.event_name == 'pull_request' + with: + name: tfplan + path: tfplan + + apply: + name: Terraform Apply + runs-on: ubuntu-latest + needs: plan + if: github.ref == 'refs/heads/main' && github.event_name == 'push' + environment: production + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Create secrets.auto.tfvars + run: | + cat > secrets.auto.tfvars << EOF + authentik_url = "${{ secrets.AUTHENTIK_URL }}" + authentik_token = "${{ secrets.AUTHENTIK_TOKEN }}" + + # Google OAuth (optional) + google_client_id = "${{ secrets.GOOGLE_CLIENT_ID }}" + google_client_secret = "${{ secrets.GOOGLE_CLIENT_SECRET }}" + + # Application URLs + argocd_url = "${{ secrets.ARGOCD_URL }}" + grafana_url = "${{ secrets.GRAFANA_URL }}" + home_assistant_url = "${{ secrets.HOME_ASSISTANT_URL }}" + immich_url = "${{ secrets.IMMICH_URL }}" + uptime_kuma_url = "${{ secrets.UPTIME_KUMA_URL }}" + sonarr_url = "${{ secrets.SONARR_URL }}" + radarr_url = "${{ secrets.RADARR_URL }}" + prowlarr_url = "${{ secrets.PROWLARR_URL }}" + EOF + + - name: Terraform Init + run: terraform init + + - name: Terraform Apply + run: terraform apply -auto-approve diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81b874b --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Terraform +.terraform/ +.terraform.lock.hcl +*.tfstate +*.tfstate.* +*.tfplan +crash.log +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Secrets - NEVER commit these +*.tfvars +!*.tfvars.example +secrets.yaml +secrets*.yaml +*.pem +*.key + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e36977 --- /dev/null +++ b/README.md @@ -0,0 +1,162 @@ +# Authentik Terraform Configuration + +Infrastructure as Code for Authentik identity provider - manage applications, providers, and SSO via Terraform. + +## Features + +- **OAuth2/OIDC Applications**: ArgoCD, Grafana +- **Proxy Authentication**: Home Assistant, Immich, Uptime Kuma, *arr stack +- **LDAP Outpost**: For legacy application support +- **Google OAuth Source**: Social login integration + +## Quick Start + +### 1. Fork/Clone This Repo + +```bash +git clone https://github.com/ghndrx/authentik-terraform.git +cd authentik-terraform +``` + +### 2. Configure GitHub Secrets + +Go to **Settings > Secrets and variables > Actions** and add: + +| Secret | Description | Example | +|--------|-------------|---------| +| `AUTHENTIK_URL` | Your Authentik server URL | `https://auth.example.com` | +| `AUTHENTIK_TOKEN` | API token from Authentik | `ak-...` | +| `GOOGLE_CLIENT_ID` | Google OAuth client ID | `xxx.apps.googleusercontent.com` | +| `GOOGLE_CLIENT_SECRET` | Google OAuth secret | `GOCSPX-...` | +| `ARGOCD_URL` | ArgoCD URL | `https://argocd.example.com` | +| `GRAFANA_URL` | Grafana URL | `https://grafana.example.com` | +| `HOME_ASSISTANT_URL` | Home Assistant URL | `https://home.example.com` | +| `IMMICH_URL` | Immich URL | `https://photos.example.com` | +| `UPTIME_KUMA_URL` | Uptime Kuma URL | `https://status.example.com` | +| `SONARR_URL` | Sonarr URL | `https://sonarr.example.com` | +| `RADARR_URL` | Radarr URL | `https://radarr.example.com` | +| `PROWLARR_URL` | Prowlarr URL | `https://prowlarr.example.com` | + +### 3. Create Authentik API Token + +1. Log into Authentik as admin +2. Go to **Directory > Tokens and App passwords** +3. Create a new token with **API Access** intent +4. Copy the token value + +### 4. (Optional) Set Up Google OAuth + +1. Go to [Google Cloud Console](https://console.cloud.google.com) +2. Create OAuth 2.0 credentials +3. Add authorized redirect URI: `https://auth.example.com/source/oauth/callback/google/` + +### 5. Deploy + +Push to `main` branch to trigger deployment, or run manually: + +```bash +# Local development +cp terraform.tfvars.example terraform.tfvars +# Edit terraform.tfvars with your values + +terraform init +terraform plan +terraform apply +``` + +## GitHub Actions Workflow + +- **On PR**: Runs `terraform plan` for review +- **On Push to main**: Runs `terraform apply` automatically +- **Manual**: Can trigger via Actions tab + +## File Structure + +``` +├── .github/workflows/deploy.yml # CI/CD pipeline +├── main.tf # Authentik provider & brand config +├── variables.tf # All configurable variables +├── app-*.tf # Application configurations +├── ldap-outpost.tf # LDAP outpost config +├── source-google.tf # Google OAuth source +└── outputs.tf # Useful outputs +``` + +## Adding New Applications + +### OAuth2/OIDC Application + +```hcl +# app-myapp.tf +resource "authentik_provider_oauth2" "myapp" { + name = "MyApp" + authorization_flow = data.authentik_flow.default_authorization.id + client_id = "myapp" + client_type = "confidential" + + redirect_uris = [ + "${var.myapp_url}/oauth/callback" + ] + + property_mappings = data.authentik_property_mapping_provider_scope.oauth2.ids +} + +resource "authentik_application" "myapp" { + name = "MyApp" + slug = "myapp" + protocol_provider = authentik_provider_oauth2.myapp.id + + meta_launch_url = var.myapp_url + meta_icon = "https://example.com/icon.png" +} +``` + +### Proxy Authentication + +```hcl +resource "authentik_provider_proxy" "myapp" { + name = "MyApp Proxy" + authorization_flow = data.authentik_flow.default_authorization.id + external_host = var.myapp_url + mode = "forward_single" +} + +resource "authentik_application" "myapp" { + name = "MyApp" + slug = "myapp" + protocol_provider = authentik_provider_proxy.myapp.id +} +``` + +## Terraform State + +By default, state is stored locally. For production, configure remote backend: + +```hcl +# backend.tf +terraform { + backend "s3" { + bucket = "your-terraform-state" + key = "authentik/terraform.tfstate" + region = "us-east-1" + } +} +``` + +## Security Notes + +- Never commit `terraform.tfvars` or any file with secrets +- Use GitHub Actions secrets for CI/CD +- API tokens should have minimal required permissions +- Rotate tokens periodically + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.5.0 | +| authentik | >= 2024.0 | + +## License + +MIT diff --git a/app-argocd.tf b/app-argocd.tf new file mode 100644 index 0000000..846faa6 --- /dev/null +++ b/app-argocd.tf @@ -0,0 +1,52 @@ +# ============================================================================= +# ArgoCD - GitOps Continuous Delivery +# ============================================================================= + +data "authentik_property_mapping_provider_scope" "argocd" { + managed_list = [ + "goauthentik.io/providers/oauth2/scope-openid", + "goauthentik.io/providers/oauth2/scope-email", + "goauthentik.io/providers/oauth2/scope-profile", + ] +} + +resource "authentik_provider_oauth2" "argocd" { + name = "ArgoCD" + client_id = "argocd" + client_type = "confidential" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + + access_token_validity = "hours=1" + refresh_token_validity = "days=30" + + property_mappings = data.authentik_property_mapping_provider_scope.argocd.ids + + # ArgoCD callback URLs - TODO: Update to your domains + allowed_redirect_uris = [ + { matching_mode = "strict", url = "https://argo.your-tailnet.ts.net/auth/callback" }, + { matching_mode = "strict", url = "https://argocd.example.com/auth/callback" }, + ] + + signing_key = data.authentik_certificate_key_pair.generated.id +} + +resource "authentik_application" "argocd" { + name = "ArgoCD" + slug = "argocd" + protocol_provider = authentik_provider_oauth2.argocd.id + + meta_description = "GitOps Continuous Delivery" + meta_launch_url = "https://argocd.your-tailnet.ts.net" # TODO: Update + + group = "DevOps" +} + +output "argocd_client_id" { + value = authentik_provider_oauth2.argocd.client_id +} + +output "argocd_client_secret" { + value = authentik_provider_oauth2.argocd.client_secret + sensitive = true +} diff --git a/app-grafana.tf b/app-grafana.tf new file mode 100644 index 0000000..fe1695c --- /dev/null +++ b/app-grafana.tf @@ -0,0 +1,52 @@ +# ============================================================================= +# Grafana - Monitoring Dashboards +# ============================================================================= + +data "authentik_property_mapping_provider_scope" "grafana" { + managed_list = [ + "goauthentik.io/providers/oauth2/scope-openid", + "goauthentik.io/providers/oauth2/scope-email", + "goauthentik.io/providers/oauth2/scope-profile", + ] +} + +resource "authentik_provider_oauth2" "grafana" { + name = "Grafana" + client_id = "grafana" + client_type = "confidential" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + + access_token_validity = "hours=1" + refresh_token_validity = "days=30" + + property_mappings = data.authentik_property_mapping_provider_scope.grafana.ids + + # TODO: Update to your domains + allowed_redirect_uris = [ + { matching_mode = "strict", url = "https://grafana.your-tailnet.ts.net/login/generic_oauth" }, + { matching_mode = "strict", url = "https://grafana.example.com/login/generic_oauth" }, + ] + + signing_key = data.authentik_certificate_key_pair.generated.id +} + +resource "authentik_application" "grafana" { + name = "Grafana" + slug = "grafana" + protocol_provider = authentik_provider_oauth2.grafana.id + + meta_description = "Monitoring & Observability Dashboards" + meta_launch_url = "https://grafana.your-tailnet.ts.net" # TODO: Update + + group = "Monitoring" +} + +output "grafana_client_id" { + value = authentik_provider_oauth2.grafana.client_id +} + +output "grafana_client_secret" { + value = authentik_provider_oauth2.grafana.client_secret + sensitive = true +} diff --git a/app-home-assistant.tf b/app-home-assistant.tf new file mode 100644 index 0000000..639e4c5 --- /dev/null +++ b/app-home-assistant.tf @@ -0,0 +1,51 @@ +# ============================================================================= +# Home Assistant - Smart Home +# ============================================================================= + +data "authentik_property_mapping_provider_scope" "home_assistant" { + managed_list = [ + "goauthentik.io/providers/oauth2/scope-openid", + "goauthentik.io/providers/oauth2/scope-email", + "goauthentik.io/providers/oauth2/scope-profile", + ] +} + +resource "authentik_provider_oauth2" "home_assistant" { + name = "Home Assistant" + client_id = "home-assistant" + client_type = "confidential" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + + access_token_validity = "hours=1" + refresh_token_validity = "days=30" + + property_mappings = data.authentik_property_mapping_provider_scope.home_assistant.ids + + # TODO: Update to your domain + allowed_redirect_uris = [ + { matching_mode = "strict", url = "https://home.your-tailnet.ts.net/auth/external/callback" }, + ] + + signing_key = data.authentik_certificate_key_pair.generated.id +} + +resource "authentik_application" "home_assistant" { + name = "Home Assistant" + slug = "home-assistant" + protocol_provider = authentik_provider_oauth2.home_assistant.id + + meta_description = "Smart Home Control" + meta_launch_url = "https://home.your-tailnet.ts.net" # TODO: Update + + group = "Home" +} + +output "home_assistant_client_id" { + value = authentik_provider_oauth2.home_assistant.client_id +} + +output "home_assistant_client_secret" { + value = authentik_provider_oauth2.home_assistant.client_secret + sensitive = true +} diff --git a/app-immich.tf b/app-immich.tf new file mode 100644 index 0000000..b44aff3 --- /dev/null +++ b/app-immich.tf @@ -0,0 +1,53 @@ +# ============================================================================= +# Immich - Photo Management +# ============================================================================= + +data "authentik_property_mapping_provider_scope" "immich" { + managed_list = [ + "goauthentik.io/providers/oauth2/scope-openid", + "goauthentik.io/providers/oauth2/scope-email", + "goauthentik.io/providers/oauth2/scope-profile", + ] +} + +resource "authentik_provider_oauth2" "immich" { + name = "Immich" + client_id = "immich" + client_type = "confidential" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + + access_token_validity = "hours=1" + refresh_token_validity = "days=30" + + property_mappings = data.authentik_property_mapping_provider_scope.immich.ids + + # TODO: Update to your domain + allowed_redirect_uris = [ + { matching_mode = "strict", url = "https://immich.your-tailnet.ts.net/auth/login" }, + { matching_mode = "strict", url = "https://immich.your-tailnet.ts.net/user-settings" }, + { matching_mode = "strict", url = "app.immich:///oauth-callback" }, + ] + + signing_key = data.authentik_certificate_key_pair.generated.id +} + +resource "authentik_application" "immich" { + name = "Immich" + slug = "immich" + protocol_provider = authentik_provider_oauth2.immich.id + + meta_description = "Photo & Video Backup" + meta_launch_url = "https://immich.your-tailnet.ts.net" # TODO: Update + + group = "Media" +} + +output "immich_client_id" { + value = authentik_provider_oauth2.immich.client_id +} + +output "immich_client_secret" { + value = authentik_provider_oauth2.immich.client_secret + sensitive = true +} diff --git a/app-proxy-arr-stack.tf b/app-proxy-arr-stack.tf new file mode 100644 index 0000000..9c3c41e --- /dev/null +++ b/app-proxy-arr-stack.tf @@ -0,0 +1,66 @@ +# ============================================================================= +# Proxy Provider for Arr Stack (Sonarr, Radarr, Prowlarr) +# These apps don't support OIDC natively, use Authentik proxy auth +# +# Note: Each app needs its own provider in Authentik due to 1:1 mapping +# ============================================================================= + +# Forward auth provider - Sonarr +resource "authentik_provider_proxy" "sonarr" { + name = "Sonarr Proxy" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + mode = "forward_single" + external_host = "https://sonarr.your-tailnet.ts.net" # TODO: Update + access_token_validity = "hours=24" +} + +resource "authentik_application" "sonarr" { + name = "Sonarr" + slug = "sonarr" + protocol_provider = authentik_provider_proxy.sonarr.id + meta_description = "TV Show Automation" + meta_launch_url = "https://sonarr.your-tailnet.ts.net" # TODO: Update + group = "Media" +} + +# Forward auth provider - Radarr +resource "authentik_provider_proxy" "radarr" { + name = "Radarr Proxy" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + mode = "forward_single" + external_host = "https://radarr.your-tailnet.ts.net" # TODO: Update + access_token_validity = "hours=24" +} + +resource "authentik_application" "radarr" { + name = "Radarr" + slug = "radarr" + protocol_provider = authentik_provider_proxy.radarr.id + meta_description = "Movie Automation" + meta_launch_url = "https://radarr.your-tailnet.ts.net" # TODO: Update + group = "Media" +} + +# Forward auth provider - Prowlarr +resource "authentik_provider_proxy" "prowlarr" { + name = "Prowlarr Proxy" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + mode = "forward_single" + external_host = "https://prowlarr.your-tailnet.ts.net" # TODO: Update + access_token_validity = "hours=24" +} + +resource "authentik_application" "prowlarr" { + name = "Prowlarr" + slug = "prowlarr" + protocol_provider = authentik_provider_proxy.prowlarr.id + meta_description = "Indexer Manager" + meta_launch_url = "https://prowlarr.your-tailnet.ts.net" # TODO: Update + group = "Media" +} + +# Note: To use forward auth with Traefik/nginx, configure the embedded outpost +# and add middleware to forward auth requests to Authentik diff --git a/app-uptime-kuma.tf b/app-uptime-kuma.tf new file mode 100644 index 0000000..3d62bb5 --- /dev/null +++ b/app-uptime-kuma.tf @@ -0,0 +1,30 @@ +# ============================================================================= +# Uptime Kuma - Status Monitoring +# Uses proxy authentication (UK doesn't support native OIDC login) +# ============================================================================= + +resource "authentik_provider_proxy" "uptime_kuma" { + name = "Uptime Kuma Proxy" + authorization_flow = data.authentik_flow.default_authorization.id + invalidation_flow = data.authentik_flow.default_invalidation.id + mode = "forward_single" + + external_host = "https://uptime.example.com" # TODO: Update + access_token_validity = "hours=24" +} + +resource "authentik_application" "uptime_kuma" { + name = "Uptime Kuma" + slug = "uptime-kuma" + protocol_provider = authentik_provider_proxy.uptime_kuma.id + + meta_description = "Service Status Monitoring" + meta_launch_url = "https://uptime.example.com" # TODO: Update + + group = "Monitoring" +} + +# Note: Configure your reverse proxy (nginx/traefik/cloudflare) +# to use Authentik forward auth before proxying to Uptime Kuma +# +# With disableAuth=true in UK, Authentik handles all authentication diff --git a/ldap-outpost.tf b/ldap-outpost.tf new file mode 100644 index 0000000..79bf842 --- /dev/null +++ b/ldap-outpost.tf @@ -0,0 +1,49 @@ +# ============================================================================= +# LDAP Provider and Outpost for TrueNAS +# Allows LDAP-based authentication against Authentik +# ============================================================================= + +# LDAP Provider +resource "authentik_provider_ldap" "truenas" { + name = "TrueNAS LDAP" + base_dn = "dc=ldap,dc=example,dc=com" # TODO: Update to your domain + bind_flow = data.authentik_flow.default_authentication.id + unbind_flow = data.authentik_flow.default_invalidation.id + + # Bind mode - direct means users bind with their own credentials + bind_mode = "direct" + + # Search mode + search_mode = "direct" + + # MFA support (optional) + mfa_support = false +} + +# Application for LDAP +resource "authentik_application" "truenas_ldap" { + name = "TrueNAS LDAP" + slug = "truenas-ldap" + protocol_provider = authentik_provider_ldap.truenas.id + + meta_description = "LDAP authentication for TrueNAS" + + group = "Infrastructure" +} + +# LDAP Outpost (standalone container needed for LDAP) +resource "authentik_outpost" "ldap" { + name = "LDAP Outpost" + type = "ldap" + protocol_providers = [authentik_provider_ldap.truenas.id] + + config = jsonencode({ + authentik_host = "https://authentik.example.com" # TODO: Update + authentik_host_insecure = false + log_level = "info" + }) +} + +output "ldap_base_dn" { + value = "dc=ldap,dc=example,dc=com" # TODO: Update to match above +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..96112cf --- /dev/null +++ b/main.tf @@ -0,0 +1,80 @@ +# ============================================================================= +# Authentik Terraform Configuration +# Update the domain below to match your Authentik instance +# ============================================================================= + +# Decrypt secrets with SOPS +data "sops_file" "secrets" { + source_file = "secrets.enc.yaml" +} + +provider "authentik" { + url = var.authentik_url + token = data.sops_file.secrets.data["authentik_token"] +} + +# ============================================================================= +# Data Sources - Existing Resources +# ============================================================================= + +# Default authentication flow +data "authentik_flow" "default_authentication" { + slug = "default-authentication-flow" +} + +# Default authorization flow (implicit consent) +data "authentik_flow" "default_authorization" { + slug = "default-provider-authorization-implicit-consent" +} + +# Default invalidation flow +data "authentik_flow" "default_invalidation" { + slug = "default-invalidation-flow" +} + +# Default enrollment flow (for social login) +data "authentik_flow" "default_enrollment" { + slug = "default-source-enrollment" +} + +# Get certificate for signing +data "authentik_certificate_key_pair" "generated" { + name = "authentik Self-signed Certificate" +} + +# ============================================================================= +# Brand Configuration +# ============================================================================= + +data "authentik_brand" "default" { + domain = "authentik-default" +} + +# Update brand with proper domain +resource "authentik_brand" "main" { + domain = "authentik.example.com" # TODO: Update to your domain + default = false + branding_title = "My Lab" # TODO: Update to your org name + branding_logo = "/static/dist/assets/icons/icon_left_brand.svg" + branding_favicon = "/static/dist/assets/icons/icon.png" + + flow_authentication = data.authentik_flow.default_authentication.id + flow_invalidation = data.authentik_flow.default_invalidation.id +} + +# ============================================================================= +# Groups +# ============================================================================= + +resource "authentik_group" "admins" { + name = "Admins" + is_superuser = true +} + +resource "authentik_group" "users" { + name = "Users" +} + +# ============================================================================= +# Applications are defined in applications/*.tf +# ============================================================================= diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..a07e0b7 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,14 @@ +output "authentik_url" { + description = "Authentik instance URL" + value = var.authentik_url +} + +output "admin_group_id" { + description = "Admin group ID for RBAC" + value = authentik_group.admins.id +} + +output "users_group_id" { + description = "Users group ID" + value = authentik_group.users.id +} diff --git a/source-google.tf b/source-google.tf new file mode 100644 index 0000000..d4be0f9 --- /dev/null +++ b/source-google.tf @@ -0,0 +1,31 @@ +# ============================================================================= +# Google Workspace Federation +# Allow users to sign in with their Google Workspace accounts +# ============================================================================= + +# Google OAuth Source +resource "authentik_source_oauth" "google" { + name = "Google Workspace" + slug = "google" + authentication_flow = data.authentik_flow.default_authentication.id + enrollment_flow = data.authentik_flow.default_enrollment.id + + provider_type = "google" + consumer_key = data.sops_file.secrets.data["google_client_id"] + consumer_secret = data.sops_file.secrets.data["google_client_secret"] + + # PKCE method - S256 is recommended + pkce = "S256" + + # User matching - link by email + user_matching_mode = "email_link" + + # Policy engine + policy_engine_mode = "any" + + # Enable for login page + enabled = true +} + +# Note: After applying, the Google login button will appear on the Authentik login page. +# Users with matching emails will be linked; new users will be enrolled. diff --git a/terraform.tfvars.example b/terraform.tfvars.example new file mode 100644 index 0000000..c4ba057 --- /dev/null +++ b/terraform.tfvars.example @@ -0,0 +1,23 @@ +# Example terraform.tfvars - Copy to terraform.tfvars and fill in your values +# NEVER commit terraform.tfvars to git! + +# Authentik Connection (required) +authentik_url = "https://auth.example.com" +authentik_token = "your-api-token-here" + +# Google OAuth (optional - leave empty to skip) +google_client_id = "" +google_client_secret = "" + +# Application URLs (set the ones you want to configure) +argocd_url = "https://argocd.example.com" +grafana_url = "https://grafana.example.com" +home_assistant_url = "https://home.example.com" +immich_url = "https://photos.example.com" +uptime_kuma_url = "https://status.example.com" +sonarr_url = "https://sonarr.example.com" +radarr_url = "https://radarr.example.com" +prowlarr_url = "https://prowlarr.example.com" + +# LDAP Configuration +ldap_base_dn = "dc=ldap,dc=example,dc=com" diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..89d58e5 --- /dev/null +++ b/variables.tf @@ -0,0 +1,90 @@ +################################################################################ +# Authentik Terraform Variables +# +# Set these via: +# - GitHub Actions secrets (recommended) +# - terraform.tfvars (local dev only - never commit!) +# - Environment variables (TF_VAR_*) +################################################################################ + +# Authentik Connection +variable "authentik_url" { + type = string + description = "Authentik server URL (e.g., https://auth.example.com)" +} + +variable "authentik_token" { + type = string + sensitive = true + description = "Authentik API token" +} + +# Google OAuth (optional) +variable "google_client_id" { + type = string + default = "" + description = "Google OAuth client ID" +} + +variable "google_client_secret" { + type = string + sensitive = true + default = "" + description = "Google OAuth client secret" +} + +# Application URLs +variable "argocd_url" { + type = string + default = "" + description = "ArgoCD URL for SSO" +} + +variable "grafana_url" { + type = string + default = "" + description = "Grafana URL for SSO" +} + +variable "home_assistant_url" { + type = string + default = "" + description = "Home Assistant URL for proxy auth" +} + +variable "immich_url" { + type = string + default = "" + description = "Immich URL for proxy auth" +} + +variable "uptime_kuma_url" { + type = string + default = "" + description = "Uptime Kuma URL for proxy auth" +} + +variable "sonarr_url" { + type = string + default = "" + description = "Sonarr URL for proxy auth" +} + +variable "radarr_url" { + type = string + default = "" + description = "Radarr URL for proxy auth" +} + +variable "prowlarr_url" { + type = string + default = "" + description = "Prowlarr URL for proxy auth" +} + +# LDAP Configuration +variable "ldap_base_dn" { + type = string + default = "dc=ldap,dc=example,dc=com" + description = "LDAP base DN" +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..0a31553 --- /dev/null +++ b/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + authentik = { + source = "goauthentik/authentik" + version = "~> 2025.2" + } + sops = { + source = "carlpett/sops" + version = "~> 1.0" + } + } +}