Files
vps/docs/sso-integration-plan.md
service 1e1a528a5e Initial commit: VPS setup documentation
Add comprehensive documentation for VPS setup and configuration including:
- Project instructions
- VPS1 starting point configuration
- VPS1 current state documentation
- VPS1 todo list

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 07:43:24 +01:00

20 KiB

SSO Integration Plan: Gitea & Immich with Netbird Zitadel

Date: 2026-01-25 Status: Planning Phase Identity Provider: Netbird Zitadel (https://nb.phiiiil.de)

Executive Summary

This plan details the integration of Gitea and Immich with the existing Netbird Zitadel Identity Provider for centralized Single Sign-On (SSO) authentication.

Benefits:

  • Unified authentication across all services
  • Centralized user management via Netbird dashboard
  • No need to remember multiple passwords
  • Secure OAuth2/OIDC flow with PKCE
  • Easy user provisioning and deprovisioning

Prerequisites

Infrastructure

Access Required

  • Netbird admin credentials (to access Zitadel console)
  • Gitea admin credentials (user: phil, password: j8bKvIl3AtIp5aTG)
  • Immich admin credentials

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                     User Browser                             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     │ 1. Click "Login with SSO"
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│   Gitea/Immich (Application)                                 │
│   - Redirects to Zitadel                                     │
│   - Client ID & Client Secret                                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     │ 2. OAuth2 Authorization Request
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│   Netbird Zitadel (Identity Provider)                        │
│   - Authenticates user                                       │
│   - Issues authorization code                                │
│   - Returns to application with code                         │
└────────────────────┬────────────────────────────────────────┘
                     │
                     │ 3. Exchange code for tokens
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│   Application validates tokens & creates user session        │
└─────────────────────────────────────────────────────────────┘

Phase 1: Zitadel Configuration

Step 1.1: Access Zitadel Console

  1. Navigate to https://nb.phiiiil.de
  2. Login with Netbird admin credentials
  3. Access Zitadel console via https://nb.phiiiil.de/ui

Note: The first access may require setting up the Zitadel admin account if not already done.

Step 1.2: Create Gitea OIDC Application

1.2.1 Create Project

  1. Go to ProjectsNew Project
  2. Configure:
    • Name: Gitea
    • Project Role: Select/create appropriate role
  3. Click Create
  4. Note the Project ID for reference

1.2.2 Create Application

  1. Navigate to the new Gitea project
  2. Go to ApplicationsNew
  3. Configure:
    • Application Name: gitea
    • Application Type: Web Application
    • Redirect URIs:
      • https://git.phiiiil.de/user/oauth2/zitadel/callback
    • Post Logout URIs:
      • https://git.phiiiil.de/
    • Authentication Method: PKCE (recommended)
    • Scopes: openid profile email
  4. Click Continue

1.2.3 Save Credentials

After creating, save the following in a secure location:

  • Client ID: (will be displayed)
  • Client Secret: (click "Reveal" to copy)

Store these securely - they will be needed for Gitea configuration.

Step 1.3: Create Immich OIDC Application

1.3.1 Create Project

  1. Go to ProjectsNew Project
  2. Configure:
    • Name: Immich
    • Project Role: Select/create appropriate role
  3. Click Create
  4. Note the Project ID for reference

1.3.2 Create Application

  1. Navigate to the new Immich project
  2. Go to ApplicationsNew
  3. Configure:
    • Application Name: immich
    • Application Type: Web Application
    • Redirect URIs:
      • https://immich.phiiiil.de/auth/login
      • https://immich.phiiiil.de/user-settings
    • Post Logout URIs:
      • https://immich.phiiiil.de/
    • Authentication Method: PKCE
    • Scopes: openid profile email
  4. Click Continue

1.3.3 Save Credentials

  • Client ID: (will be displayed)
  • Client Secret: (click "Reveal" to copy)

Phase 2: Gitea Configuration

Step 2.1: Access Gitea Admin Panel

  1. Navigate to https://git.phiiiil.de
  2. Login with admin credentials:
    • Username: phil
    • Password: j8bKvIl3AtIp5aTG

Step 2.2: Configure OAuth2 Authentication

Via Web UI:

  1. Go to Administration (gear icon → Authentication Sources)
  2. Click Add Authentication SourceOAuth2
  3. Configure:
    Authentication Name:          Netbird Zitadel
    OAuth2 Provider:              OpenID Connect
    Client ID:                    [from Zitadel Step 1.2.3]
    Client Secret:                [from Zitadel Step 1.2.3]
    OpenID Connect Discovery Endpoint:
                                 https://nb.phiiiil.de/.well-known/openid-configuration
    Auto-discover Email Address:  ✅ Enabled
    Scopes:                       openid profile email
    Email Authentication Field:   Email
    Update Avatar:                ✅ Enabled
    Group Claims:                 (optional, leave empty)
    
  4. Click Create Authentication Source

Step 2.3: Configure User Settings

Via Web UI:

  1. Go to Site AdministrationAuthentication
  2. Enable:
    • Show "Sign In" button on login page
    • Automatically create users for OAuth2
    • Hide login form if only OAuth2 is available (optional)
  3. Click Save

Verify Configuration:

# Check Gitea logs for any OAuth errors
docker logs gitea | grep -i oauth

Step 2.4: Test Gitea SSO

  1. Logout of Gitea
  2. Go to https://git.phiiiil.de
  3. Click Sign In with Netbird Zitadel
  4. You should be redirected to Zitadel login
  5. Authenticate with Netbird credentials
  6. Should be redirected back to Gitea, logged in

Expected Result:

  • User is created automatically in Gitea
  • Email address synced from Zitadel
  • Avatar updated (if available in Zitadel)

Phase 3: Immich Configuration

Step 3.1: Access Immich Admin Panel

  1. Navigate to https://immich.phiiiil.de
  2. Login with admin credentials

Step 3.2: Configure OAuth2

Via Web UI:

  1. Go to AdministrationSettingsAuthentication
  2. Under OAuth, click Enable or Add OAuth
  3. Configure:
    OAuth Button Display Name:   Login with Netbird
    OAuth Button Link URL:       [auto-generated]
    Client ID:                   [from Zitadel Step 1.3.3]
    Client Secret:               [from Zitadel Step 1.3.3]
    Issuer URL:                  https://nb.phiiiil.de
    Authorization Endpoint:      https://nb.phiiiil.de/oauth/v2/authorize
    Token Endpoint:              https://nb.phiiiil.de/oauth/v2/token
    User Info Endpoint:          https://nb.phiiiil.de/oidc/v1/userinfo
    Scope:                       openid profile email
    Auto Registering:            ✅ Enabled
    Auto Linking:                ✅ Enabled
    Storage Label Claim:         email
    
  4. Click Save

Alternative: Via Environment Variables

Edit /home/phil/docker/immich-app/.env and add:

# OAuth2/OIDC Configuration
IMMICH_OAUTH_ENABLED=true
IMMICH_OAUTH_BUTTON_TEXT="Login with Netbird"
IMMICH_OAUTH_ISSUER_URL=https://nb.phiiiil.de
IMMICH_OAUTH_CLIENT_ID=[from Zitadel]
IMMICH_OAUTH_CLIENT_SECRET=[from Zitadel]
IMMICH_OAUTH_AUTO_REGISTER=true
IMMICH_OAUTH_STORAGE_LABEL_CLAIM=email
IMMICH_OAUTH_SCOPE=openid profile email

Then restart Immich:

cd /home/phil/docker/immich-app
docker compose restart immich-server

Step 3.3: Test Immich SSO

  1. Logout of Immich
  2. Go to https://immich.phiiiil.de
  3. Click Login with Netbird
  4. Authenticate with Netbird credentials
  5. Should be redirected back to Immich, logged in

Expected Result:

  • User is created automatically in Immich
  • Email address synced from Zitadel
  • User can access their photo library

Phase 4: Testing & Verification

Step 4.1: Gitea Verification

Test Checklist:

  • Login page shows "Sign In with Netbird Zitadel" button
  • Clicking button redirects to Zitadel login
  • After authentication, user is logged into Gitea
  • User profile shows correct email from Zitadel
  • User avatar is imported (if available)
  • Logout works correctly
  • Can login again with SSO

Verify User Sync:

# Check Gitea database for new user
docker exec -it gitea-db psql -U gitea -d gitea -c "SELECT * FROM user WHERE login_name LIKE '%@%';"

Step 4.2: Immich Verification

Test Checklist:

  • Login page shows "Login with Netbird" button
  • Clicking button redirects to Zitadel login
  • After authentication, user is logged into Immich
  • User can access photos
  • User settings show correct email from Zitadel
  • Logout works correctly
  • Can login again with SSO

Verify User Creation:

# Check Immich database for OAuth user
docker exec -it immich_postgres psql -U postgres -d immich -c "SELECT id, email, oauthId FROM \"user\" WHERE email LIKE '%@%';"

Step 4.3: Cross-Service Testing

Test that:

  • Logging into Zitadel automatically logs into both Gitea and Immich (single sign-on)
  • Logout from one service doesn't affect other services
  • New users created in Zitadel can access both applications

Phase 5: Security Configuration

Step 5.1: Enable HTTPS Only

Gitea:

  • Already enforced via Caddy reverse proxy
  • Ensure GITEA__server__PROTOCOL=https is set (should be)

Immich:

  • Already enforced via Caddy reverse proxy

Step 5.2: Configure Token Expiration

In Zitadel:

  1. Go to SettingsToken Configuration
  2. Set reasonable token lifetimes:
    • Access Token: 1 hour
    • Refresh Token: 30 days
    • ID Token: 1 hour

Step 5.3: Enable PKCE

Verify both applications are using PKCE:

  • Gitea: Already configured in Zitadel
  • Immich: Supported via OAuth2 flow

Step 5.4: Review Scopes

Minimal recommended scopes:

  • openid - Required for OIDC
  • profile - User name and basic info
  • email - Email address for user identification

Optional scopes:

  • groups - Group membership (not currently used)
  • address - Physical address (not needed)
  • phone - Phone number (not needed)

Phase 6: Backup & Rollback

Pre-Integration Backup

Before starting, run a full backup:

/home/phil/docker/backup/backup.sh

Verify backup completed:

ls -lah /mnt/backup/latest/

Rollback Procedures

If Gitea SSO fails:

  1. Login with local admin account (phil / j8bKvIl3AtIp5aTG)
  2. Go to AdministrationAuthentication Sources
  3. Delete the Netbird Zitadel OAuth source
  4. Users can still login with local passwords

If Immich SSO fails:

  1. Login with local admin account
  2. Go to AdministrationSettingsAuthentication
  3. Disable OAuth or remove the configuration
  4. Restart Immich:
    cd /home/phil/docker/immich-app
    docker compose restart immich-server
    

Complete rollback:

# Restore Gitea database
gunzip < /mnt/backup/latest/gitea-db.sql.gz | docker exec -i gitea-db psql -U gitea gitea

# Restore Immich database
gunzip < /mnt/backup/latest/immich-db.sql.gz | docker exec -i immich_postgres psql -U postgres immich

Phase 7: User Migration

  1. Create user accounts in Zitadel with same email addresses
  2. Users login via SSO
  3. Applications automatically create user accounts
  4. Manual data association may be needed (repositories, photos, etc.)

Option B: Automated Mapping

For Gitea:

  • Set up email matching between Git local users and Zitadel users
  • Enable Automatically create users for OAuth2
  • First OAuth login will create new Gitea account
  • Manual migration of repositories may be needed

For Immich:

  • Enable Auto Registering and Auto Linking
  • First OAuth login will create new Immich account
  • WARNING: Photos are tied to user accounts - migration may be complex
  • Consider testing with a test user first

Phase 8: Documentation & Maintenance

Step 8.1: Update Documentation

Update /home/phil/Schreibtisch/Privat/vps/vps1-state-25012026.md:

  • Add SSO configuration section
  • Document Client IDs (encrypted) and where they're stored
  • Add troubleshooting section

Update /home/phil/Schreibtisch/Privat/vps/docs/deployment-summary.md:

  • Mark OIDC SSO as completed
  • Add SSO URLs to quick reference

Step 8.2: Maintenance Tasks

Monthly:

  • Review OAuth2 token usage in Zitadel
  • Check for failed authentication attempts
  • Review user access

Quarterly:

  • Rotate client secrets (recommended)
  • Review and update scopes
  • Audit user access

Implementation Checklist

Pre-Implementation

  • Create full backup of all databases
  • Verify backup integrity
  • Document current authentication state
  • Prepare rollback procedures

Zitadel Configuration

  • Access Zitadel console
  • Create Gitea project
  • Create Gitea application
  • Save Gitea Client ID and Secret
  • Create Immich project
  • Create Immich application
  • Save Immich Client ID and Secret

Gitea Integration

  • Configure OAuth2 in Gitea admin
  • Enable auto-user creation
  • Test Gitea SSO login
  • Verify user creation
  • Test Gitea logout

Immich Integration

  • Configure OAuth2 in Immich admin
  • Enable auto-user registration
  • Test Immich SSO login
  • Verify user creation
  • Test Immich logout

Testing & Verification

  • Test Gitea SSO full flow
  • Test Immich SSO full flow
  • Test cross-service SSO
  • Verify user data sync
  • Test logout functionality

Documentation

  • Update vps1-state-25012026.md
  • Update deployment-summary.md
  • Document Client IDs securely
  • Create user guide for SSO login

Troubleshooting

Issue: "Invalid redirect URI"

Symptoms:

  • Error in Zitadel logs about redirect URI mismatch
  • OAuth flow fails during redirect

Solution:

  1. Check exact redirect URI in application logs
  2. Compare with Zitadel application configuration
  3. Ensure protocol (http vs https) matches
  4. Ensure no trailing slashes

Gitea correct URI: https://git.phiiiil.de/user/oauth2/zitadel/callback Immich correct URI: https://immich.phiiiil.de/auth/login

Issue: "Client authentication failed"

Symptoms:

  • Token endpoint returns 401 Unauthorized
  • Error about invalid client_secret

Solution:

  1. Verify Client ID matches exactly
  2. Reveal and copy Client Secret again from Zitadel
  3. Check for extra spaces or characters
  4. Regenerate Client Secret in Zitadel if needed

Issue: "User not created automatically"

Symptoms:

  • OAuth login succeeds but no user created
  • User sees "Access denied" or similar

Solution:

Gitea:

  • Go to AuthenticationEnable "Automatically create users"
  • Check for email conflicts with existing users

Immich:

  • Enable Auto Registering in OAuth settings
  • Enable Auto Linking to match existing users by email

Issue: "Discovery endpoint not accessible"

Symptoms:

  • Application cannot fetch OIDC configuration
  • Error connecting to https://nb.phiiiil.de/.well-known/openid-configuration

Solution:

  1. Check Caddy is running: docker ps | grep caddy
  2. Test endpoint manually: curl https://nb.phiiiil.de/.well-known/openid-configuration
  3. Check Caddy logs: docker logs netbird-caddy-1 | grep openid
  4. Verify firewall allows connection to port 443

Issue: "Avatar not syncing"

Symptoms:

  • User logs in successfully but avatar not updated

Solution:

Gitea:

  • Enable Update Avatar in OAuth configuration
  • Ensure Zitadel profile includes avatar URL
  • Check Gitea logs for avatar fetch errors

Immich:

  • Avatar may need manual upload after first login
  • Immich doesn't always fetch avatar from IdP

Success Criteria

The integration will be considered successful when:

  1. Gitea:

    • Users can login via "Sign In with Netbird Zitadel"
    • User accounts are created automatically
    • Email addresses are synced from Zitadel
    • Existing functionality (repositories, SSH) still works
  2. Immich:

    • Users can login via "Login with Netbird"
    • User accounts are created automatically
    • Email addresses are synced from Zitadel
    • Photo access and functionality preserved
  3. Security:

    • All authentication uses OAuth2/OIDC with PKCE
    • HTTPS enforced for all communications
    • Token lifetimes are reasonable
    • No security warnings in browser console
  4. Usability:

    • Login process takes < 10 seconds
    • Single sign-on works across services
    • Logout works correctly
    • User experience is intuitive

Timeline Estimate

  • Phase 1 (Zitadel Config): 30 minutes
  • Phase 2 (Gitea Config): 20 minutes
  • Phase 3 (Immich Config): 20 minutes
  • Phase 4 (Testing): 30 minutes
  • Phase 5 (Security Config): 15 minutes
  • Phase 6 (Backups): 10 minutes
  • Phase 7 (User Migration): Variable (depends on users)
  • Phase 8 (Documentation): 30 minutes

Total: ~2.5 hours (excluding user migration)

Post-Implementation Tasks

  1. Monitor logs for first 24-48 hours:

    # Gitea OAuth logs
    docker logs gitea | grep -i oauth
    
    # Immich OAuth logs
    docker logs immich_server | grep -i oauth
    
    # Caddy/OAuth routing logs
    docker logs netbird-caddy-1 | grep -i oauth
    
  2. Check Zitadel dashboard regularly:

    • Active sessions
    • Failed login attempts
    • Token issuance
  3. User feedback:

    • Gather user experience feedback
    • Document any issues or improvements needed

Appendix: OAuth2 Endpoints Reference

Zitadel (Netbird):

  • Issuer: https://nb.phiiiil.de
  • Discovery: https://nb.phiiiil.de/.well-known/openid-configuration
  • Authorization: https://nb.phiiiil.de/oauth/v2/authorize
  • Token: https://nb.phiiiil.de/oauth/v2/token
  • UserInfo: https://nb.phiiiil.de/oidc/v1/userinfo
  • JWKS: https://nb.phiiiil.de/oauth/v2/keys
  • End Session: https://nb.phiiiil.de/oidc/v1/end_session

Application Redirect URIs:

  • Gitea: https://git.phiiiil.de/user/oauth2/zitadel/callback
  • Immich: https://immich.phiiiil.de/auth/login

Notes

  • This plan assumes Netbird admin access is available
  • Client secrets should be stored securely (consider using a password manager)
  • Test with a test user first before migrating all users
  • Immich user migration may require additional consideration for photo ownership
  • Gitea SSH key access is independent of OAuth and continues to work

Document Version: 1.0 Last Updated: 2026-01-25 Status: Ready for Implementation