Skip to content

Commit 814e41f

Browse files
committed
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
0 parents  commit 814e41f

16 files changed

Lines changed: 902 additions & 0 deletions

.github/workflows/deploy.yml

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: Deploy Authentik Configuration
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
env:
11+
TF_VERSION: "1.7.0"
12+
13+
jobs:
14+
plan:
15+
name: Terraform Plan
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Terraform
23+
uses: hashicorp/setup-terraform@v3
24+
with:
25+
terraform_version: ${{ env.TF_VERSION }}
26+
27+
- name: Create secrets.auto.tfvars
28+
run: |
29+
cat > secrets.auto.tfvars << EOF
30+
authentik_url = "${{ secrets.AUTHENTIK_URL }}"
31+
authentik_token = "${{ secrets.AUTHENTIK_TOKEN }}"
32+
33+
# Google OAuth (optional)
34+
google_client_id = "${{ secrets.GOOGLE_CLIENT_ID }}"
35+
google_client_secret = "${{ secrets.GOOGLE_CLIENT_SECRET }}"
36+
37+
# Application URLs
38+
argocd_url = "${{ secrets.ARGOCD_URL }}"
39+
grafana_url = "${{ secrets.GRAFANA_URL }}"
40+
home_assistant_url = "${{ secrets.HOME_ASSISTANT_URL }}"
41+
immich_url = "${{ secrets.IMMICH_URL }}"
42+
uptime_kuma_url = "${{ secrets.UPTIME_KUMA_URL }}"
43+
sonarr_url = "${{ secrets.SONARR_URL }}"
44+
radarr_url = "${{ secrets.RADARR_URL }}"
45+
prowlarr_url = "${{ secrets.PROWLARR_URL }}"
46+
EOF
47+
48+
- name: Terraform Init
49+
run: terraform init
50+
51+
- name: Terraform Validate
52+
run: terraform validate
53+
54+
- name: Terraform Plan
55+
run: terraform plan -out=tfplan
56+
57+
- name: Upload Plan
58+
uses: actions/upload-artifact@v4
59+
if: github.event_name == 'pull_request'
60+
with:
61+
name: tfplan
62+
path: tfplan
63+
64+
apply:
65+
name: Terraform Apply
66+
runs-on: ubuntu-latest
67+
needs: plan
68+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
69+
environment: production
70+
71+
steps:
72+
- name: Checkout
73+
uses: actions/checkout@v4
74+
75+
- name: Setup Terraform
76+
uses: hashicorp/setup-terraform@v3
77+
with:
78+
terraform_version: ${{ env.TF_VERSION }}
79+
80+
- name: Create secrets.auto.tfvars
81+
run: |
82+
cat > secrets.auto.tfvars << EOF
83+
authentik_url = "${{ secrets.AUTHENTIK_URL }}"
84+
authentik_token = "${{ secrets.AUTHENTIK_TOKEN }}"
85+
86+
# Google OAuth (optional)
87+
google_client_id = "${{ secrets.GOOGLE_CLIENT_ID }}"
88+
google_client_secret = "${{ secrets.GOOGLE_CLIENT_SECRET }}"
89+
90+
# Application URLs
91+
argocd_url = "${{ secrets.ARGOCD_URL }}"
92+
grafana_url = "${{ secrets.GRAFANA_URL }}"
93+
home_assistant_url = "${{ secrets.HOME_ASSISTANT_URL }}"
94+
immich_url = "${{ secrets.IMMICH_URL }}"
95+
uptime_kuma_url = "${{ secrets.UPTIME_KUMA_URL }}"
96+
sonarr_url = "${{ secrets.SONARR_URL }}"
97+
radarr_url = "${{ secrets.RADARR_URL }}"
98+
prowlarr_url = "${{ secrets.PROWLARR_URL }}"
99+
EOF
100+
101+
- name: Terraform Init
102+
run: terraform init
103+
104+
- name: Terraform Apply
105+
run: terraform apply -auto-approve

.gitignore

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Terraform
2+
.terraform/
3+
.terraform.lock.hcl
4+
*.tfstate
5+
*.tfstate.*
6+
*.tfplan
7+
crash.log
8+
override.tf
9+
override.tf.json
10+
*_override.tf
11+
*_override.tf.json
12+
13+
# Secrets - NEVER commit these
14+
*.tfvars
15+
!*.tfvars.example
16+
secrets.yaml
17+
secrets*.yaml
18+
*.pem
19+
*.key
20+
21+
# IDE
22+
.idea/
23+
.vscode/
24+
*.swp
25+
*.swo
26+
*~
27+
28+
# OS
29+
.DS_Store
30+
Thumbs.db

README.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Authentik Terraform Configuration
2+
3+
Infrastructure as Code for Authentik identity provider - manage applications, providers, and SSO via Terraform.
4+
5+
## Features
6+
7+
- **OAuth2/OIDC Applications**: ArgoCD, Grafana
8+
- **Proxy Authentication**: Home Assistant, Immich, Uptime Kuma, *arr stack
9+
- **LDAP Outpost**: For legacy application support
10+
- **Google OAuth Source**: Social login integration
11+
12+
## Quick Start
13+
14+
### 1. Fork/Clone This Repo
15+
16+
```bash
17+
git clone https://github.com/ghndrx/authentik-terraform.git
18+
cd authentik-terraform
19+
```
20+
21+
### 2. Configure GitHub Secrets
22+
23+
Go to **Settings > Secrets and variables > Actions** and add:
24+
25+
| Secret | Description | Example |
26+
|--------|-------------|---------|
27+
| `AUTHENTIK_URL` | Your Authentik server URL | `https://auth.example.com` |
28+
| `AUTHENTIK_TOKEN` | API token from Authentik | `ak-...` |
29+
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | `xxx.apps.googleusercontent.com` |
30+
| `GOOGLE_CLIENT_SECRET` | Google OAuth secret | `GOCSPX-...` |
31+
| `ARGOCD_URL` | ArgoCD URL | `https://argocd.example.com` |
32+
| `GRAFANA_URL` | Grafana URL | `https://grafana.example.com` |
33+
| `HOME_ASSISTANT_URL` | Home Assistant URL | `https://home.example.com` |
34+
| `IMMICH_URL` | Immich URL | `https://photos.example.com` |
35+
| `UPTIME_KUMA_URL` | Uptime Kuma URL | `https://status.example.com` |
36+
| `SONARR_URL` | Sonarr URL | `https://sonarr.example.com` |
37+
| `RADARR_URL` | Radarr URL | `https://radarr.example.com` |
38+
| `PROWLARR_URL` | Prowlarr URL | `https://prowlarr.example.com` |
39+
40+
### 3. Create Authentik API Token
41+
42+
1. Log into Authentik as admin
43+
2. Go to **Directory > Tokens and App passwords**
44+
3. Create a new token with **API Access** intent
45+
4. Copy the token value
46+
47+
### 4. (Optional) Set Up Google OAuth
48+
49+
1. Go to [Google Cloud Console](https://console.cloud.google.com)
50+
2. Create OAuth 2.0 credentials
51+
3. Add authorized redirect URI: `https://auth.example.com/source/oauth/callback/google/`
52+
53+
### 5. Deploy
54+
55+
Push to `main` branch to trigger deployment, or run manually:
56+
57+
```bash
58+
# Local development
59+
cp terraform.tfvars.example terraform.tfvars
60+
# Edit terraform.tfvars with your values
61+
62+
terraform init
63+
terraform plan
64+
terraform apply
65+
```
66+
67+
## GitHub Actions Workflow
68+
69+
- **On PR**: Runs `terraform plan` for review
70+
- **On Push to main**: Runs `terraform apply` automatically
71+
- **Manual**: Can trigger via Actions tab
72+
73+
## File Structure
74+
75+
```
76+
├── .github/workflows/deploy.yml # CI/CD pipeline
77+
├── main.tf # Authentik provider & brand config
78+
├── variables.tf # All configurable variables
79+
├── app-*.tf # Application configurations
80+
├── ldap-outpost.tf # LDAP outpost config
81+
├── source-google.tf # Google OAuth source
82+
└── outputs.tf # Useful outputs
83+
```
84+
85+
## Adding New Applications
86+
87+
### OAuth2/OIDC Application
88+
89+
```hcl
90+
# app-myapp.tf
91+
resource "authentik_provider_oauth2" "myapp" {
92+
name = "MyApp"
93+
authorization_flow = data.authentik_flow.default_authorization.id
94+
client_id = "myapp"
95+
client_type = "confidential"
96+
97+
redirect_uris = [
98+
"${var.myapp_url}/oauth/callback"
99+
]
100+
101+
property_mappings = data.authentik_property_mapping_provider_scope.oauth2.ids
102+
}
103+
104+
resource "authentik_application" "myapp" {
105+
name = "MyApp"
106+
slug = "myapp"
107+
protocol_provider = authentik_provider_oauth2.myapp.id
108+
109+
meta_launch_url = var.myapp_url
110+
meta_icon = "https://example.com/icon.png"
111+
}
112+
```
113+
114+
### Proxy Authentication
115+
116+
```hcl
117+
resource "authentik_provider_proxy" "myapp" {
118+
name = "MyApp Proxy"
119+
authorization_flow = data.authentik_flow.default_authorization.id
120+
external_host = var.myapp_url
121+
mode = "forward_single"
122+
}
123+
124+
resource "authentik_application" "myapp" {
125+
name = "MyApp"
126+
slug = "myapp"
127+
protocol_provider = authentik_provider_proxy.myapp.id
128+
}
129+
```
130+
131+
## Terraform State
132+
133+
By default, state is stored locally. For production, configure remote backend:
134+
135+
```hcl
136+
# backend.tf
137+
terraform {
138+
backend "s3" {
139+
bucket = "your-terraform-state"
140+
key = "authentik/terraform.tfstate"
141+
region = "us-east-1"
142+
}
143+
}
144+
```
145+
146+
## Security Notes
147+
148+
- Never commit `terraform.tfvars` or any file with secrets
149+
- Use GitHub Actions secrets for CI/CD
150+
- API tokens should have minimal required permissions
151+
- Rotate tokens periodically
152+
153+
## Requirements
154+
155+
| Name | Version |
156+
|------|---------|
157+
| terraform | >= 1.5.0 |
158+
| authentik | >= 2024.0 |
159+
160+
## License
161+
162+
MIT

app-argocd.tf

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# =============================================================================
2+
# ArgoCD - GitOps Continuous Delivery
3+
# =============================================================================
4+
5+
data "authentik_property_mapping_provider_scope" "argocd" {
6+
managed_list = [
7+
"goauthentik.io/providers/oauth2/scope-openid",
8+
"goauthentik.io/providers/oauth2/scope-email",
9+
"goauthentik.io/providers/oauth2/scope-profile",
10+
]
11+
}
12+
13+
resource "authentik_provider_oauth2" "argocd" {
14+
name = "ArgoCD"
15+
client_id = "argocd"
16+
client_type = "confidential"
17+
authorization_flow = data.authentik_flow.default_authorization.id
18+
invalidation_flow = data.authentik_flow.default_invalidation.id
19+
20+
access_token_validity = "hours=1"
21+
refresh_token_validity = "days=30"
22+
23+
property_mappings = data.authentik_property_mapping_provider_scope.argocd.ids
24+
25+
# ArgoCD callback URLs - TODO: Update to your domains
26+
allowed_redirect_uris = [
27+
{ matching_mode = "strict", url = "https://argo.your-tailnet.ts.net/auth/callback" },
28+
{ matching_mode = "strict", url = "https://argocd.example.com/auth/callback" },
29+
]
30+
31+
signing_key = data.authentik_certificate_key_pair.generated.id
32+
}
33+
34+
resource "authentik_application" "argocd" {
35+
name = "ArgoCD"
36+
slug = "argocd"
37+
protocol_provider = authentik_provider_oauth2.argocd.id
38+
39+
meta_description = "GitOps Continuous Delivery"
40+
meta_launch_url = "https://argocd.your-tailnet.ts.net" # TODO: Update
41+
42+
group = "DevOps"
43+
}
44+
45+
output "argocd_client_id" {
46+
value = authentik_provider_oauth2.argocd.client_id
47+
}
48+
49+
output "argocd_client_secret" {
50+
value = authentik_provider_oauth2.argocd.client_secret
51+
sensitive = true
52+
}

0 commit comments

Comments
 (0)