Switch to terraform
This commit is contained in:
80
ansible/gitea/cleanup-full.yml
Normal file
80
ansible/gitea/cleanup-full.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea - Full Cleanup
|
||||
# =============================================================================
|
||||
# Removes containers and optionally all data
|
||||
#
|
||||
# Usage (containers only):
|
||||
# ansible-playbook -i inventory.yml cleanup-full.yml
|
||||
#
|
||||
# Usage (including data - DESTRUCTIVE):
|
||||
# ansible-playbook -i inventory.yml cleanup-full.yml -e "remove_data=true"
|
||||
# =============================================================================
|
||||
|
||||
- name: Gitea - Full Cleanup
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
vars:
|
||||
remove_data: false
|
||||
|
||||
tasks:
|
||||
- name: Display warning
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
WARNING: Full Cleanup
|
||||
============================================
|
||||
remove_data: {{ remove_data }}
|
||||
Data directory: {{ gitea_data_dir }}
|
||||
============================================
|
||||
|
||||
- name: Check if docker-compose.yml exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
register: compose_file
|
||||
|
||||
- name: Stop and remove containers with volumes
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose down -v --remove-orphans
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
when: compose_file.stat.exists
|
||||
ignore_errors: true
|
||||
changed_when: true
|
||||
|
||||
- name: Remove OAuth setup script
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_base_dir }}/setup-gitea-oauth.sh"
|
||||
state: absent
|
||||
|
||||
- name: Remove Gitea data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_data_dir }}"
|
||||
state: absent
|
||||
when: remove_data | bool
|
||||
|
||||
- name: Remove base directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_base_dir }}"
|
||||
state: absent
|
||||
when: remove_data | bool
|
||||
|
||||
- name: Display cleanup status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea - Full Cleanup Complete
|
||||
============================================
|
||||
|
||||
Containers: Removed
|
||||
Data: {{ 'REMOVED' if remove_data else 'Preserved at ' + gitea_data_dir }}
|
||||
|
||||
Note: Authentik OAuth application still exists.
|
||||
To remove, go to Authentik admin panel:
|
||||
https://{{ authentik_domain }}/if/admin/#/core/applications
|
||||
|
||||
To redeploy:
|
||||
ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
|
||||
============================================
|
||||
47
ansible/gitea/cleanup-soft.yml
Normal file
47
ansible/gitea/cleanup-soft.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea - Soft Cleanup
|
||||
# =============================================================================
|
||||
# Stops containers but preserves configuration and data
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.yml cleanup-soft.yml
|
||||
# =============================================================================
|
||||
|
||||
- name: Gitea - Soft Cleanup
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
|
||||
tasks:
|
||||
- name: Check if docker-compose.yml exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
register: compose_file
|
||||
|
||||
- name: Stop containers (preserve data)
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose down
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
when: compose_file.stat.exists
|
||||
ignore_errors: true
|
||||
changed_when: true
|
||||
|
||||
- name: Display cleanup status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea - Soft Cleanup Complete
|
||||
============================================
|
||||
|
||||
Containers stopped. Data preserved at:
|
||||
{{ gitea_data_dir }}
|
||||
|
||||
To restart:
|
||||
ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
|
||||
To fully remove:
|
||||
ansible-playbook -i inventory.yml cleanup-full.yml
|
||||
|
||||
============================================
|
||||
30
ansible/gitea/group_vars/gitea_servers.yml
Normal file
30
ansible/gitea/group_vars/gitea_servers.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea GitOps PoC Configuration
|
||||
# =============================================================================
|
||||
# Standalone Gitea installation without external OAuth.
|
||||
# Used for hosting Terraform/Pulumi repos and CI/CD pipelines.
|
||||
|
||||
# =============================================================================
|
||||
# Domain Configuration
|
||||
# =============================================================================
|
||||
gitea_domain: "gitea-poc.networkmonitor.cc"
|
||||
gitea_ssh_domain: "gitea-poc.networkmonitor.cc"
|
||||
|
||||
# =============================================================================
|
||||
# Let's Encrypt Configuration
|
||||
# =============================================================================
|
||||
letsencrypt_email: "vlad.stus@gmail.com"
|
||||
|
||||
# =============================================================================
|
||||
# Paths
|
||||
# =============================================================================
|
||||
gitea_base_dir: "/opt/gitea"
|
||||
gitea_data_dir: "{{ gitea_base_dir }}/gitea_data"
|
||||
|
||||
# =============================================================================
|
||||
# Docker Configuration
|
||||
# =============================================================================
|
||||
gitea_image: "gitea/gitea:latest"
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
20
ansible/gitea/group_vars/vault.yml
Normal file
20
ansible/gitea/group_vars/vault.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea Deployment Vault Secrets
|
||||
# =============================================================================
|
||||
# Copy to vault.yml and encrypt:
|
||||
# cp vault.yml.example vault.yml
|
||||
# # Edit vault.yml with your values
|
||||
# ansible-vault encrypt vault.yml
|
||||
#
|
||||
# Run playbook with:
|
||||
# ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# Authentik API Access
|
||||
# =============================================================================
|
||||
# Bootstrap token from Authentik deployment
|
||||
# Get from VPS:
|
||||
# ssh root@auth.stuslab.cc "grep AUTHENTIK_BOOTSTRAP_TOKEN /opt/authentik/authentik.env"
|
||||
#vault_authentik_bootstrap_token: "PASTE_AUTHENTIK_BOOTSTRAP_TOKEN_HERE"
|
||||
14
ansible/gitea/group_vars/vault.yml.example
Normal file
14
ansible/gitea/group_vars/vault.yml.example
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea PoC Vault Secrets
|
||||
# =============================================================================
|
||||
# This PoC deployment doesn't use external OAuth, so no secrets are required.
|
||||
# This file exists for consistency with the deployment pattern.
|
||||
#
|
||||
# If you add secrets later:
|
||||
# cp vault.yml.example vault.yml
|
||||
# # Edit vault.yml
|
||||
# ansible-vault encrypt vault.yml
|
||||
|
||||
# Placeholder - no secrets needed for standalone Gitea
|
||||
# vault_example_secret: "changeme"
|
||||
9
ansible/gitea/inventory.yml
Normal file
9
ansible/gitea/inventory.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
all:
|
||||
children:
|
||||
gitea_servers:
|
||||
hosts:
|
||||
gitea-homelab:
|
||||
ansible_host: 94.130.181.201
|
||||
ansible_user: root
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
89
ansible/gitea/migration/cleanup-full.yml
Normal file
89
ansible/gitea/migration/cleanup-full.yml
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea - Full Cleanup
|
||||
# =============================================================================
|
||||
# Removes containers and optionally all data
|
||||
#
|
||||
# Usage (containers only):
|
||||
# ansible-playbook -i inventory.yml cleanup-full.yml
|
||||
#
|
||||
# Usage (including data - DESTRUCTIVE):
|
||||
# ansible-playbook -i inventory.yml cleanup-full.yml -e "remove_data=true"
|
||||
#
|
||||
# Usage (including backups - VERY DESTRUCTIVE):
|
||||
# ansible-playbook -i inventory.yml cleanup-full.yml -e "remove_data=true" -e "remove_backups=true"
|
||||
# =============================================================================
|
||||
|
||||
- name: Gitea - Full Cleanup
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
vars:
|
||||
# Safety flags - must be explicitly enabled
|
||||
remove_data: false
|
||||
remove_backups: false
|
||||
|
||||
tasks:
|
||||
- name: Display warning
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
WARNING: Full Cleanup
|
||||
============================================
|
||||
remove_data: {{ remove_data }}
|
||||
remove_backups: {{ remove_backups }}
|
||||
|
||||
Data directory: {{ gitea_data_dir }}
|
||||
Backup directory: {{ gitea_backup_dir }}
|
||||
============================================
|
||||
|
||||
- name: Check if docker-compose.yml exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
register: compose_file
|
||||
|
||||
- name: Stop and remove containers with volumes
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose down -v --remove-orphans
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
when: compose_file.stat.exists
|
||||
ignore_errors: true
|
||||
changed_when: true
|
||||
|
||||
- name: Remove OAuth setup script
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_base_dir }}/setup-gitea-oauth.sh"
|
||||
state: absent
|
||||
|
||||
- name: Remove Gitea data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_data_dir }}"
|
||||
state: absent
|
||||
when: remove_data | bool
|
||||
|
||||
- name: Remove backup directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_backup_dir }}"
|
||||
state: absent
|
||||
when: remove_backups | bool
|
||||
|
||||
- name: Display cleanup status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea - Full Cleanup Complete
|
||||
============================================
|
||||
|
||||
Containers: Removed
|
||||
Data: {{ 'REMOVED' if remove_data else 'Preserved at ' + gitea_data_dir }}
|
||||
Backups: {{ 'REMOVED' if remove_backups else 'Preserved at ' + gitea_backup_dir }}
|
||||
|
||||
Note: Authentik OAuth application still exists.
|
||||
To remove, go to Authentik admin panel:
|
||||
https://{{ authentik_domain }}/if/admin/#/core/applications
|
||||
|
||||
To redeploy:
|
||||
ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
|
||||
============================================
|
||||
50
ansible/gitea/migration/cleanup-soft.yml
Normal file
50
ansible/gitea/migration/cleanup-soft.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea - Soft Cleanup
|
||||
# =============================================================================
|
||||
# Stops containers but preserves configuration and data
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.yml cleanup-soft.yml
|
||||
# =============================================================================
|
||||
|
||||
- name: Gitea - Soft Cleanup
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
|
||||
tasks:
|
||||
- name: Check if docker-compose.yml exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
register: compose_file
|
||||
|
||||
- name: Stop containers (preserve data)
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose down
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
when: compose_file.stat.exists
|
||||
ignore_errors: true
|
||||
changed_when: true
|
||||
|
||||
- name: Display cleanup status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea - Soft Cleanup Complete
|
||||
============================================
|
||||
|
||||
Containers stopped. Data preserved at:
|
||||
{{ gitea_data_dir }}
|
||||
|
||||
Backups at:
|
||||
{{ gitea_backup_dir }}
|
||||
|
||||
To restart:
|
||||
ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
|
||||
To fully remove:
|
||||
ansible-playbook -i inventory.yml cleanup-full.yml
|
||||
|
||||
============================================
|
||||
69
ansible/gitea/migration/group_vars/gitea_servers.yml
Normal file
69
ansible/gitea/migration/group_vars/gitea_servers.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea Migration Configuration
|
||||
# =============================================================================
|
||||
# Migrating from stuslab.cc to code.stuslab.cc with Authentik OAuth
|
||||
#
|
||||
# Before running:
|
||||
# 1. Ensure Authentik is deployed at auth.stuslab.cc
|
||||
# 2. Create group_vars/vault.yml from vault.yml.example
|
||||
# 3. Add DNS record: code.stuslab.cc -> 94.130.181.201
|
||||
# 4. Run: ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# Domain Configuration
|
||||
# =============================================================================
|
||||
# Old domain (will redirect to new)
|
||||
gitea_old_domain: "stuslab.cc"
|
||||
|
||||
# New domain for Gitea
|
||||
gitea_domain: "code.stuslab.cc"
|
||||
|
||||
# SSH domain (for git clone URLs)
|
||||
gitea_ssh_domain: "code.stuslab.cc"
|
||||
|
||||
# =============================================================================
|
||||
# Let's Encrypt Configuration
|
||||
# =============================================================================
|
||||
letsencrypt_email: "vlad.stus@gmail.com"
|
||||
|
||||
# =============================================================================
|
||||
# Paths
|
||||
# =============================================================================
|
||||
# Existing Gitea installation path on VPS
|
||||
gitea_base_dir: "/root/gitea"
|
||||
|
||||
# Data directory (contains repos, database, config)
|
||||
gitea_data_dir: "{{ gitea_base_dir }}/gitea_data"
|
||||
|
||||
# Backup directory on VPS
|
||||
gitea_backup_dir: "/root/gitea-backups"
|
||||
|
||||
# =============================================================================
|
||||
# Authentik Configuration
|
||||
# =============================================================================
|
||||
# Domain where Authentik is deployed
|
||||
authentik_domain: "auth.stuslab.cc"
|
||||
|
||||
# OAuth provider name (must match exactly in Gitea UI)
|
||||
gitea_oauth_provider_name: "Authentik"
|
||||
|
||||
# OAuth client ID (used in Authentik and Gitea)
|
||||
gitea_oauth_client_id: "gitea"
|
||||
|
||||
# =============================================================================
|
||||
# Docker Configuration
|
||||
# =============================================================================
|
||||
gitea_image: "gitea/gitea:latest"
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
|
||||
# =============================================================================
|
||||
# Migration Flags
|
||||
# =============================================================================
|
||||
# Create backup before migration (recommended)
|
||||
gitea_create_backup: true
|
||||
|
||||
# Upload backup to GDrive via rclone (requires rclone configured on VPS)
|
||||
gitea_backup_to_gdrive: false
|
||||
51
ansible/gitea/migration/group_vars/vault.yml
Normal file
51
ansible/gitea/migration/group_vars/vault.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
66313066626635366538383531303838363335366332373763343030373535343935343463363037
|
||||
3661653331333337613763316135653338636265656238300a343233383237316565306161326435
|
||||
62616533386336333932393230383332383839363366373566306165383936366361663864393231
|
||||
3536343039663639650a643539323937623334616230363337306661616463313239306438326238
|
||||
31663535333137323831303266336161353232626564613436613732626461343733623963376565
|
||||
61303663326633616263613461383263353734303462363634393562663064663332363738303832
|
||||
66636663653762343636323936656362646236383539666464373862336461363864373963313039
|
||||
31313166656665663035353130643761616161353837313839636631373236343666343838653837
|
||||
36366266636339323931383362646634343164666138633364623538383466363662656635636366
|
||||
33326637303363353961633434376330623836666434383237346430373739333333396539636366
|
||||
32396339663930353131323032343433656332373635643638623862363164636661313735626639
|
||||
36613838366231636636623439393137353138613562646664336366663864306664316130656237
|
||||
33643235646334306336613662303532653033343034643737326230653161326136313132666231
|
||||
64323734623231623933353763383564353438343236323333613461363031363530356431393461
|
||||
38636532636532633532613862636635353532666330373034353164326662656638356233306633
|
||||
37653532306530633135393232316635333863626564666231623961366237366161656437623665
|
||||
39643134623835316139623236633166636364313866343636326466393035653365626130363533
|
||||
31633137653463333561653132636234633230373030376633623166383364646536646261633731
|
||||
37626538623831613431353766656661346565643633353034343533316134616166316136306339
|
||||
35323666306439393865626465396336623662353161396366653532326633346436336566646336
|
||||
38373539353334386134646237653534343430343439366533383738653938336530666266636563
|
||||
66313130313438363830386538306662393264643838656136623136386565303366636362306564
|
||||
62343030616361616661393063313938663433323662373531333435333032353831663537636461
|
||||
62666665646566656562303666333830363337663436633435653934656137626664616163303461
|
||||
32376363353534366235383635333538316431313736663237623966363431343434386263376132
|
||||
37353764313136323335633133343466343830343366363536303237333835303165333337636230
|
||||
37643132643866616633376566623264633534343334306537316461616132336265626537333666
|
||||
61353933366532363363613465313861333362383531306230343238313633633934626264366530
|
||||
64316335623637363537336162303933393935613734326535613738333262323033373935313632
|
||||
63393332346132353735356161393438643264343264326634353562613536303566623464646363
|
||||
61663639336466666364353838323931323134333461303831383265626139303135303566376433
|
||||
64383339373961303137616530616632366562326662646131363534613065623363633731313639
|
||||
36353363633836316436666564396438353161623765356230333166346436346662373032336263
|
||||
34613135623138306331626264316132363838376363373462616338613432343737646231333563
|
||||
33633062613030643832663263376231316431616239373639646532623639646362393234656364
|
||||
61393462346631633365613463323361626664316563656461646137386332366565366135623364
|
||||
36343664333039343538353663346532623733386464306265396565363966363535353837366238
|
||||
36643635623131313636393237643737343565656166653337656666636231343066383962306539
|
||||
64303666613437353039353630353633353630336336636539333166373561626634353363623765
|
||||
62626464386130646536323933653464656332373632366535633436346336306337313063356466
|
||||
66663233616434383230316564343132663132373431396137623334333636363231336334333535
|
||||
63336464623736306531653039333833316631393636363861613938386563613136636561626663
|
||||
66323638653337333732326335376630633065623437386330323136623766313334306663613866
|
||||
38383636353934386662633232303239656134633162396432393363336138366239323330643161
|
||||
39666333393032373363633435316136366663643931366561643735633262323236373465323363
|
||||
34323163353461616433613464646435326335336464333962646361666662656566636339646335
|
||||
31633266663761666432656464323135343534346663383862306461323762306461626161356265
|
||||
64653965643563643263386430653933613566303537636563636536366133383838336335316363
|
||||
31653666323965346535646439316163346166343261656432343465386634313037323736376464
|
||||
3562623165376161663466356130613064366433323662346430
|
||||
20
ansible/gitea/migration/group_vars/vault.yml.example
Normal file
20
ansible/gitea/migration/group_vars/vault.yml.example
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea Migration Vault Secrets
|
||||
# =============================================================================
|
||||
# Copy to vault.yml and encrypt:
|
||||
# cp vault.yml.example vault.yml
|
||||
# # Edit vault.yml with your values
|
||||
# ansible-vault encrypt vault.yml
|
||||
#
|
||||
# Run playbook with:
|
||||
# ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# Authentik API Access
|
||||
# =============================================================================
|
||||
# Bootstrap token from Authentik deployment
|
||||
# Get from VPS:
|
||||
# ssh root@auth.stuslab.cc "grep AUTHENTIK_BOOTSTRAP_TOKEN /opt/authentik/authentik.env"
|
||||
vault_authentik_bootstrap_token: "PASTE_AUTHENTIK_BOOTSTRAP_TOKEN_HERE"
|
||||
9
ansible/gitea/migration/inventory.yml
Normal file
9
ansible/gitea/migration/inventory.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
all:
|
||||
children:
|
||||
gitea_servers:
|
||||
hosts:
|
||||
gitea-homelab:
|
||||
ansible_host: 94.130.181.201
|
||||
ansible_user: root
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
308
ansible/gitea/migration/playbook.yml
Normal file
308
ansible/gitea/migration/playbook.yml
Normal file
@@ -0,0 +1,308 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea Migration Playbook
|
||||
# =============================================================================
|
||||
# Migrates Gitea from stuslab.cc to code.stuslab.cc with Authentik OAuth
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. Authentik deployed at auth.stuslab.cc
|
||||
# 2. DNS record: code.stuslab.cc -> 94.130.181.201
|
||||
# 3. group_vars/vault.yml with authentik bootstrap token
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory.yml playbook.yml --ask-vault-pass
|
||||
#
|
||||
# What this playbook does:
|
||||
# 1. Validates existing Gitea installation
|
||||
# 2. Creates backup of gitea_data/
|
||||
# 3. Updates app.ini with new domain settings
|
||||
# 4. Deploys updated Caddyfile with redirect
|
||||
# 5. Creates OAuth application in Authentik
|
||||
# 6. Verifies migration success
|
||||
# =============================================================================
|
||||
|
||||
- name: Migrate Gitea to code.stuslab.cc
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
- group_vars/vault.yml
|
||||
|
||||
# ===========================================================================
|
||||
# Pre-flight Validation
|
||||
# ===========================================================================
|
||||
pre_tasks:
|
||||
- name: Validate required variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- gitea_domain is defined
|
||||
- gitea_old_domain is defined
|
||||
- authentik_domain is defined
|
||||
- vault_authentik_bootstrap_token is defined
|
||||
- vault_authentik_bootstrap_token != "PASTE_AUTHENTIK_BOOTSTRAP_TOKEN_HERE"
|
||||
fail_msg: |
|
||||
Required variables not configured!
|
||||
1. Copy vault.yml.example to vault.yml
|
||||
2. Add your Authentik bootstrap token
|
||||
3. Encrypt with: ansible-vault encrypt group_vars/vault.yml
|
||||
|
||||
- name: Check existing Gitea installation
|
||||
ansible.builtin.stat:
|
||||
path: "{{ gitea_base_dir }}/gitea_data/gitea/conf/app.ini"
|
||||
register: existing_gitea
|
||||
|
||||
- name: Fail if no existing Gitea found
|
||||
ansible.builtin.fail:
|
||||
msg: |
|
||||
No existing Gitea installation found at {{ gitea_base_dir }}
|
||||
Expected app.ini at: {{ gitea_base_dir }}/gitea_data/gitea/conf/app.ini
|
||||
when: not existing_gitea.stat.exists
|
||||
|
||||
- name: Display pre-flight status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea Migration Pre-flight Check
|
||||
============================================
|
||||
Current domain: {{ gitea_old_domain }}
|
||||
Target domain: {{ gitea_domain }}
|
||||
Authentik: {{ authentik_domain }}
|
||||
Base dir: {{ gitea_base_dir }}
|
||||
============================================
|
||||
|
||||
- name: Verify Authentik is reachable
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ authentik_domain }}/api/v3/core/brands/"
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer {{ vault_authentik_bootstrap_token }}"
|
||||
status_code: 200
|
||||
timeout: 30
|
||||
register: authentik_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Warn if Authentik not reachable
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
WARNING: Authentik not reachable at https://{{ authentik_domain }}
|
||||
OAuth setup will be skipped. You can run it manually later.
|
||||
when: authentik_check.failed
|
||||
|
||||
tasks:
|
||||
# =========================================================================
|
||||
# Stage 1: Backup (skip if recent backup exists)
|
||||
# =========================================================================
|
||||
- name: Create backup directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_backup_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
when: gitea_create_backup
|
||||
|
||||
- name: Check for existing backup from today
|
||||
ansible.builtin.find:
|
||||
paths: "{{ gitea_backup_dir }}"
|
||||
patterns: "gitea-backup-{{ ansible_date_time.date | replace('-', '') }}*.tar.gz"
|
||||
register: existing_backups
|
||||
when: gitea_create_backup
|
||||
|
||||
- name: Set backup needed flag
|
||||
ansible.builtin.set_fact:
|
||||
backup_needed: "{{ gitea_create_backup and (existing_backups.files | length == 0) }}"
|
||||
|
||||
- name: Skip backup message
|
||||
ansible.builtin.debug:
|
||||
msg: "Backup already exists from today: {{ existing_backups.files[0].path | basename }}. Skipping backup."
|
||||
when:
|
||||
- gitea_create_backup
|
||||
- existing_backups.files | length > 0
|
||||
|
||||
- name: Stop Gitea container for consistent backup
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose stop gitea
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
when: backup_needed
|
||||
changed_when: true
|
||||
|
||||
- name: Generate backup timestamp
|
||||
ansible.builtin.set_fact:
|
||||
backup_timestamp: "{{ ansible_date_time.iso8601_basic_short }}"
|
||||
when: backup_needed
|
||||
|
||||
- name: Create backup archive
|
||||
ansible.builtin.archive:
|
||||
path: "{{ gitea_data_dir }}"
|
||||
dest: "{{ gitea_backup_dir }}/gitea-backup-{{ backup_timestamp }}.tar.gz"
|
||||
format: gz
|
||||
when: backup_needed
|
||||
|
||||
- name: Display backup status
|
||||
ansible.builtin.debug:
|
||||
msg: "Backup created: {{ gitea_backup_dir }}/gitea-backup-{{ backup_timestamp }}.tar.gz"
|
||||
when: backup_needed
|
||||
|
||||
- name: Upload backup to GDrive (if configured)
|
||||
ansible.builtin.command:
|
||||
cmd: "rclone copy {{ gitea_backup_dir }}/gitea-backup-{{ backup_timestamp }}.tar.gz GDrive:backups/gitea/"
|
||||
when:
|
||||
- backup_needed
|
||||
- gitea_backup_to_gdrive
|
||||
ignore_errors: true
|
||||
register: gdrive_upload
|
||||
changed_when: gdrive_upload.rc == 0
|
||||
|
||||
# =========================================================================
|
||||
# Stage 2: Domain Migration (app.ini)
|
||||
# =========================================================================
|
||||
- name: Update app.ini ROOT_URL
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ gitea_data_dir }}/gitea/conf/app.ini"
|
||||
regexp: '^ROOT_URL\s*='
|
||||
line: "ROOT_URL = https://{{ gitea_domain }}/"
|
||||
backup: true
|
||||
|
||||
- name: Update app.ini SSH_DOMAIN
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ gitea_data_dir }}/gitea/conf/app.ini"
|
||||
regexp: '^SSH_DOMAIN\s*='
|
||||
line: "SSH_DOMAIN = {{ gitea_ssh_domain }}"
|
||||
|
||||
- name: Update app.ini DOMAIN
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ gitea_data_dir }}/gitea/conf/app.ini"
|
||||
regexp: '^DOMAIN\s*='
|
||||
line: "DOMAIN = {{ gitea_domain }}"
|
||||
|
||||
# =========================================================================
|
||||
# Stage 3: Deploy Updated Configuration
|
||||
# =========================================================================
|
||||
- name: Deploy docker-compose.yml
|
||||
ansible.builtin.template:
|
||||
src: templates/docker-compose.yml.j2
|
||||
dest: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
mode: "0644"
|
||||
backup: true
|
||||
|
||||
- name: Deploy Caddyfile with domain redirect
|
||||
ansible.builtin.template:
|
||||
src: templates/Caddyfile.j2
|
||||
dest: "{{ gitea_base_dir }}/Caddyfile"
|
||||
mode: "0644"
|
||||
backup: true
|
||||
|
||||
- name: Start services
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
changed_when: true
|
||||
|
||||
- name: Wait for Caddy to start (port 443)
|
||||
ansible.builtin.wait_for:
|
||||
port: 443
|
||||
host: 127.0.0.1
|
||||
delay: 5
|
||||
timeout: 60
|
||||
|
||||
- name: Wait for Gitea container to be healthy
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose ps gitea --format json
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
register: gitea_container
|
||||
until: "'running' in gitea_container.stdout"
|
||||
retries: 12
|
||||
delay: 5
|
||||
changed_when: false
|
||||
|
||||
# =========================================================================
|
||||
# Stage 4: Authentik OAuth Setup
|
||||
# =========================================================================
|
||||
- name: Install jq for OAuth setup script
|
||||
ansible.builtin.apt:
|
||||
name: jq
|
||||
state: present
|
||||
update_cache: true
|
||||
when: not authentik_check.failed
|
||||
|
||||
- name: Deploy Gitea OAuth setup script
|
||||
ansible.builtin.template:
|
||||
src: templates/setup-gitea-oauth.sh.j2
|
||||
dest: "{{ gitea_base_dir }}/setup-gitea-oauth.sh"
|
||||
mode: "0755"
|
||||
when: not authentik_check.failed
|
||||
|
||||
- name: Run Gitea OAuth setup on Authentik
|
||||
ansible.builtin.command:
|
||||
cmd: "{{ gitea_base_dir }}/setup-gitea-oauth.sh"
|
||||
register: oauth_setup
|
||||
when: not authentik_check.failed
|
||||
changed_when: true
|
||||
|
||||
- name: Display OAuth setup output
|
||||
ansible.builtin.debug:
|
||||
var: oauth_setup.stdout_lines
|
||||
when:
|
||||
- not authentik_check.failed
|
||||
- oauth_setup is defined
|
||||
|
||||
# =========================================================================
|
||||
# Stage 5: Verification
|
||||
# =========================================================================
|
||||
- name: Wait for Gitea to be healthy on new domain
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ gitea_domain }}/api/v1/version"
|
||||
method: GET
|
||||
status_code: 200
|
||||
timeout: 30
|
||||
validate_certs: true
|
||||
register: gitea_health
|
||||
until: gitea_health.status == 200
|
||||
retries: 12
|
||||
delay: 10
|
||||
ignore_errors: true
|
||||
|
||||
- name: Check old domain redirect
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ gitea_old_domain }}/"
|
||||
method: GET
|
||||
follow_redirects: none
|
||||
status_code: [301, 302, 308]
|
||||
validate_certs: true
|
||||
register: redirect_check
|
||||
ignore_errors: true
|
||||
|
||||
- name: Display migration status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea Migration Complete!
|
||||
============================================
|
||||
|
||||
New URL: https://{{ gitea_domain }}
|
||||
Old URL: https://{{ gitea_old_domain }} (redirects)
|
||||
|
||||
Health check: {{ 'PASSED' if gitea_health.status == 200 else 'PENDING - may need DNS propagation' }}
|
||||
Redirect check: {{ 'PASSED' if redirect_check.status in [301, 302, 308] else 'PENDING' }}
|
||||
|
||||
Backup: {{ gitea_backup_dir }}/gitea-backup-{{ backup_timestamp | default('N/A') }}.tar.gz
|
||||
|
||||
============================================
|
||||
MANUAL STEPS REQUIRED:
|
||||
============================================
|
||||
|
||||
1. DNS (if not done):
|
||||
Add A record: code.stuslab.cc -> 94.130.181.201
|
||||
|
||||
2. OAuth Configuration in Gitea UI:
|
||||
- Go to: https://{{ gitea_domain }}/admin/auths/new
|
||||
- See credentials: cat /tmp/gitea-oauth-credentials.json
|
||||
|
||||
3. Test git operations:
|
||||
ssh -T git@{{ gitea_ssh_domain }} -p {{ gitea_ssh_port }}
|
||||
git clone git@{{ gitea_ssh_domain }}:user/repo.git
|
||||
|
||||
============================================
|
||||
|
||||
View logs:
|
||||
ssh root@{{ ansible_host }} "cd {{ gitea_base_dir }} && docker compose logs -f"
|
||||
|
||||
============================================
|
||||
17
ansible/gitea/migration/templates/Caddyfile.j2
Normal file
17
ansible/gitea/migration/templates/Caddyfile.j2
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
email {{ letsencrypt_email }}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Primary Domain - Gitea
|
||||
# =============================================================================
|
||||
{{ gitea_domain }} {
|
||||
reverse_proxy gitea:{{ gitea_http_port }}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Old Domain - Permanent Redirect
|
||||
# =============================================================================
|
||||
{{ gitea_old_domain }} {
|
||||
redir https://{{ gitea_domain }}{uri} permanent
|
||||
}
|
||||
49
ansible/gitea/migration/templates/docker-compose.yml.j2
Normal file
49
ansible/gitea/migration/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,49 @@
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
|
||||
services:
|
||||
gitea:
|
||||
image: {{ gitea_image }}
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
volumes:
|
||||
- {{ gitea_data_dir }}:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "{{ gitea_ssh_port }}:22"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "2"
|
||||
|
||||
caddy:
|
||||
image: caddy:alpine
|
||||
container_name: caddy
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gitea
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "443:443/udp"
|
||||
volumes:
|
||||
- {{ gitea_base_dir }}/Caddyfile:/etc/caddy/Caddyfile
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "2"
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
252
ansible/gitea/migration/templates/setup-gitea-oauth.sh.j2
Normal file
252
ansible/gitea/migration/templates/setup-gitea-oauth.sh.j2
Normal file
@@ -0,0 +1,252 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Gitea OAuth Application Setup for Authentik
|
||||
# =============================================================================
|
||||
# Creates OAuth2 provider and application in Authentik for Gitea
|
||||
# Outputs credentials for manual Gitea UI configuration
|
||||
#
|
||||
# Generated by ansible - do not edit manually
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
AUTHENTIK_DOMAIN="{{ authentik_domain }}"
|
||||
GITEA_DOMAIN="{{ gitea_domain }}"
|
||||
CLIENT_ID="{{ gitea_oauth_client_id }}"
|
||||
PROVIDER_NAME="{{ gitea_oauth_provider_name }}"
|
||||
OUTPUT_FILE="/tmp/gitea-oauth-credentials.json"
|
||||
|
||||
# Bootstrap token from Authentik
|
||||
API_TOKEN="{{ vault_authentik_bootstrap_token }}"
|
||||
|
||||
echo "============================================"
|
||||
echo "Gitea OAuth Application Setup"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Authentik: https://${AUTHENTIK_DOMAIN}"
|
||||
echo "Gitea: https://${GITEA_DOMAIN}"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Test API access
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Testing Authentik API access..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/brands/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
echo "ERROR: API authentication failed (HTTP $HTTP_CODE)"
|
||||
echo "Check that vault_authentik_bootstrap_token is correct"
|
||||
exit 1
|
||||
fi
|
||||
echo "Authentik API ready!"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get authorization flow PK
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding authorization flow..."
|
||||
AUTH_FLOW_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/flows/instances/?designation=authorization" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
AUTH_FLOW_PK=$(echo "$AUTH_FLOW_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Authorization flow: $AUTH_FLOW_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get invalidation flow PK
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding invalidation flow..."
|
||||
INVALID_FLOW_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/flows/instances/?designation=invalidation" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
INVALID_FLOW_PK=$(echo "$INVALID_FLOW_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Invalidation flow: $INVALID_FLOW_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get signing certificate
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding signing certificate..."
|
||||
CERT_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/crypto/certificatekeypairs/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
SIGNING_KEY_PK=$(echo "$CERT_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Signing key: $SIGNING_KEY_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get scope mappings
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Getting scope mappings..."
|
||||
SCOPE_MAPPINGS=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/propertymappings/provider/scope/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
|
||||
OPENID_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="openid") | .pk')
|
||||
PROFILE_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="profile") | .pk')
|
||||
EMAIL_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="email") | .pk')
|
||||
|
||||
echo "Scopes: openid=$OPENID_PK, profile=$PROFILE_PK, email=$EMAIL_PK"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Check if provider already exists
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Checking for existing Gitea provider..."
|
||||
EXISTING_PROVIDER=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/?name=Gitea" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
EXISTING_PK=$(echo "$EXISTING_PROVIDER" | jq -r '.results[0].pk // empty')
|
||||
|
||||
if [ -n "$EXISTING_PK" ] && [ "$EXISTING_PK" != "null" ]; then
|
||||
echo "Provider already exists (PK: $EXISTING_PK), updating..."
|
||||
|
||||
# Update existing provider
|
||||
PROVIDER_RESPONSE=$(curl -s -X PATCH \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/${EXISTING_PK}/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"redirect_uris\": [
|
||||
{\"matching_mode\": \"strict\", \"url\": \"https://${GITEA_DOMAIN}/user/oauth2/${PROVIDER_NAME}/callback\"}
|
||||
]
|
||||
}")
|
||||
|
||||
PROVIDER_PK="$EXISTING_PK"
|
||||
CLIENT_SECRET=$(echo "$EXISTING_PROVIDER" | jq -r '.results[0].client_secret // empty')
|
||||
else
|
||||
# -----------------------------------------------------------------------------
|
||||
# Create OAuth2 Provider (confidential client for Gitea)
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Creating Gitea OAuth2 Provider..."
|
||||
PROVIDER_RESPONSE=$(curl -s -X POST \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"Gitea\",
|
||||
\"authorization_flow\": \"${AUTH_FLOW_PK}\",
|
||||
\"invalidation_flow\": \"${INVALID_FLOW_PK}\",
|
||||
\"signing_key\": \"${SIGNING_KEY_PK}\",
|
||||
\"client_type\": \"confidential\",
|
||||
\"client_id\": \"${CLIENT_ID}\",
|
||||
\"redirect_uris\": [
|
||||
{\"matching_mode\": \"strict\", \"url\": \"https://${GITEA_DOMAIN}/user/oauth2/${PROVIDER_NAME}/callback\"}
|
||||
],
|
||||
\"access_code_validity\": \"minutes=10\",
|
||||
\"access_token_validity\": \"hours=1\",
|
||||
\"refresh_token_validity\": \"days=30\",
|
||||
\"property_mappings\": [\"${OPENID_PK}\", \"${PROFILE_PK}\", \"${EMAIL_PK}\"],
|
||||
\"sub_mode\": \"user_email\",
|
||||
\"include_claims_in_id_token\": true,
|
||||
\"issuer_mode\": \"per_provider\"
|
||||
}")
|
||||
|
||||
PROVIDER_PK=$(echo "$PROVIDER_RESPONSE" | jq -r '.pk // empty')
|
||||
CLIENT_SECRET=$(echo "$PROVIDER_RESPONSE" | jq -r '.client_secret // empty')
|
||||
|
||||
if [ -z "$PROVIDER_PK" ] || [ "$PROVIDER_PK" = "null" ]; then
|
||||
echo "ERROR: Failed to create provider"
|
||||
echo "$PROVIDER_RESPONSE" | jq .
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Provider PK: $PROVIDER_PK"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Check if application already exists
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Checking for existing Gitea application..."
|
||||
EXISTING_APP=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/applications/?slug=gitea" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
EXISTING_APP_SLUG=$(echo "$EXISTING_APP" | jq -r '.results[0].slug // empty')
|
||||
|
||||
if [ -z "$EXISTING_APP_SLUG" ] || [ "$EXISTING_APP_SLUG" = "null" ]; then
|
||||
# -----------------------------------------------------------------------------
|
||||
# Create Application
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Creating Gitea Application..."
|
||||
APP_RESPONSE=$(curl -s -X POST \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/applications/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"Gitea\",
|
||||
\"slug\": \"gitea\",
|
||||
\"provider\": ${PROVIDER_PK},
|
||||
\"meta_launch_url\": \"https://${GITEA_DOMAIN}\",
|
||||
\"open_in_new_tab\": false
|
||||
}")
|
||||
|
||||
APP_SLUG=$(echo "$APP_RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -z "$APP_SLUG" ] || [ "$APP_SLUG" = "null" ]; then
|
||||
echo "WARNING: Failed to create application (may already exist)"
|
||||
else
|
||||
echo "Application created: $APP_SLUG"
|
||||
fi
|
||||
else
|
||||
echo "Application already exists: $EXISTING_APP_SLUG"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Output credentials
|
||||
# -----------------------------------------------------------------------------
|
||||
cat > "$OUTPUT_FILE" << EOF
|
||||
{
|
||||
"client_id": "${CLIENT_ID}",
|
||||
"client_secret": "${CLIENT_SECRET}",
|
||||
"auto_discover_url": "https://${AUTHENTIK_DOMAIN}/application/o/gitea/.well-known/openid-configuration",
|
||||
"scopes": "email profile",
|
||||
"provider_name": "${PROVIDER_NAME}"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "============================================"
|
||||
echo "OAuth Setup Complete!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Credentials saved to: ${OUTPUT_FILE}"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo "MANUAL CONFIGURATION REQUIRED IN GITEA"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "1. Log into Gitea as admin:"
|
||||
echo " https://${GITEA_DOMAIN}/user/login"
|
||||
echo ""
|
||||
echo "2. Navigate to:"
|
||||
echo " Site Administration -> Authentication Sources -> Add"
|
||||
echo ""
|
||||
echo "3. Fill in the form:"
|
||||
echo " Authentication Type: OAuth2"
|
||||
echo " Authentication Name: ${PROVIDER_NAME}"
|
||||
echo " OAuth2 Provider: OpenID Connect"
|
||||
echo " Client ID: ${CLIENT_ID}"
|
||||
echo " Client Secret: ${CLIENT_SECRET}"
|
||||
echo " OpenID Connect Auto Discovery URL:"
|
||||
echo " https://${AUTHENTIK_DOMAIN}/application/o/gitea/.well-known/openid-configuration"
|
||||
echo " Additional Scopes: email profile"
|
||||
echo ""
|
||||
echo "4. Click 'Add Authentication Source'"
|
||||
echo ""
|
||||
echo "5. Test by logging out and clicking 'Sign in with ${PROVIDER_NAME}'"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Credentials JSON:"
|
||||
cat "$OUTPUT_FILE"
|
||||
echo ""
|
||||
209
ansible/gitea/playbook.yml
Normal file
209
ansible/gitea/playbook.yml
Normal file
@@ -0,0 +1,209 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Gitea PoC Deployment Playbook (Standalone)
|
||||
# =============================================================================
|
||||
# Deploys standalone Gitea without external OAuth.
|
||||
# Used for hosting Terraform/Pulumi repos and CI/CD pipelines.
|
||||
#
|
||||
# Prerequisites:
|
||||
# 1. DNS record: gitea-poc.networkmonitor.cc -> VPS IP
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i poc-inventory.yml playbook.yml
|
||||
# =============================================================================
|
||||
|
||||
- name: Deploy Gitea Code Hosting
|
||||
hosts: gitea_servers
|
||||
become: true
|
||||
vars_files:
|
||||
- group_vars/gitea_servers.yml
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate required variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- gitea_domain is defined
|
||||
fail_msg: "gitea_domain must be defined in group_vars/gitea_servers.yml"
|
||||
|
||||
tasks:
|
||||
# =========================================================================
|
||||
# Prerequisites
|
||||
# =========================================================================
|
||||
- name: Update apt cache
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Install prerequisites
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
- jq
|
||||
state: present
|
||||
|
||||
# =========================================================================
|
||||
# Docker Installation
|
||||
# =========================================================================
|
||||
- name: Create keyrings directory
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Add Docker GPG key
|
||||
ansible.builtin.shell: |
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
args:
|
||||
creates: /etc/apt/keyrings/docker.gpg
|
||||
|
||||
- name: Add Docker repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
|
||||
state: present
|
||||
filename: docker
|
||||
|
||||
- name: Install Docker packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Start and enable Docker
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
# =========================================================================
|
||||
# Gitea Directory Structure
|
||||
# =========================================================================
|
||||
- name: Create Gitea directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_base_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Create Gitea data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ gitea_data_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
# =========================================================================
|
||||
# Deploy Configuration Files
|
||||
# =========================================================================
|
||||
- name: Deploy docker-compose.yml
|
||||
ansible.builtin.template:
|
||||
src: templates/docker-compose.yml.j2
|
||||
dest: "{{ gitea_base_dir }}/docker-compose.yml"
|
||||
mode: "0644"
|
||||
|
||||
- name: Deploy Caddyfile
|
||||
ansible.builtin.template:
|
||||
src: templates/Caddyfile.j2
|
||||
dest: "{{ gitea_base_dir }}/Caddyfile"
|
||||
mode: "0644"
|
||||
|
||||
# =========================================================================
|
||||
# Firewall (UFW)
|
||||
# =========================================================================
|
||||
- name: Install UFW
|
||||
ansible.builtin.apt:
|
||||
name: ufw
|
||||
state: present
|
||||
|
||||
- name: Allow SSH
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "22"
|
||||
proto: tcp
|
||||
|
||||
- name: Allow HTTP
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "80"
|
||||
proto: tcp
|
||||
|
||||
- name: Allow HTTPS
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "443"
|
||||
proto: tcp
|
||||
|
||||
- name: Allow Gitea SSH
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ gitea_ssh_port }}"
|
||||
proto: tcp
|
||||
|
||||
- name: Enable UFW
|
||||
community.general.ufw:
|
||||
state: enabled
|
||||
policy: deny
|
||||
|
||||
# =========================================================================
|
||||
# Start Services
|
||||
# =========================================================================
|
||||
- name: Pull Docker images
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
changed_when: true
|
||||
|
||||
- name: Start Gitea services
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
changed_when: true
|
||||
|
||||
# =========================================================================
|
||||
# Wait for Gitea to be ready
|
||||
# =========================================================================
|
||||
- name: Wait for Gitea container to be healthy
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose ps gitea --format json
|
||||
chdir: "{{ gitea_base_dir }}"
|
||||
register: gitea_container
|
||||
until: "'running' in gitea_container.stdout"
|
||||
retries: 12
|
||||
delay: 5
|
||||
changed_when: false
|
||||
|
||||
# =========================================================================
|
||||
# Deployment Summary
|
||||
# =========================================================================
|
||||
- name: Display deployment status
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
============================================
|
||||
Gitea Container Deployed!
|
||||
============================================
|
||||
|
||||
Container: gitea (port {{ gitea_http_port }} internal)
|
||||
SSH: port {{ gitea_ssh_port }} exposed
|
||||
|
||||
============================================
|
||||
NEXT STEPS:
|
||||
============================================
|
||||
|
||||
1. Deploy shared Caddy:
|
||||
cd ../caddy && ansible-playbook -i poc-inventory.yml playbook.yml
|
||||
|
||||
2. Then access https://{{ gitea_domain }}
|
||||
|
||||
============================================
|
||||
|
||||
View logs:
|
||||
ssh root@{{ ansible_host }} "cd {{ gitea_base_dir }} && docker compose logs -f"
|
||||
|
||||
============================================
|
||||
8
ansible/gitea/poc-inventory.yml
Normal file
8
ansible/gitea/poc-inventory.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
all:
|
||||
children:
|
||||
gitea_servers:
|
||||
hosts:
|
||||
gitea-poc:
|
||||
ansible_host: observability-poc.networkmonitor.cc
|
||||
ansible_user: root
|
||||
7
ansible/gitea/templates/Caddyfile.j2
Normal file
7
ansible/gitea/templates/Caddyfile.j2
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
email {{ letsencrypt_email }}
|
||||
}
|
||||
|
||||
{{ gitea_domain }} {
|
||||
reverse_proxy gitea:{{ gitea_http_port }}
|
||||
}
|
||||
25
ansible/gitea/templates/docker-compose.yml.j2
Normal file
25
ansible/gitea/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,25 @@
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
|
||||
services:
|
||||
gitea:
|
||||
image: {{ gitea_image }}
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
volumes:
|
||||
- {{ gitea_data_dir }}:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "{{ gitea_ssh_port }}:22"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "2"
|
||||
246
ansible/gitea/templates/setup-gitea-oauth.sh.j2
Normal file
246
ansible/gitea/templates/setup-gitea-oauth.sh.j2
Normal file
@@ -0,0 +1,246 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# Gitea OAuth Application Setup for Authentik
|
||||
# =============================================================================
|
||||
# Creates OAuth2 provider and application in Authentik for Gitea
|
||||
# Outputs credentials for manual Gitea UI configuration
|
||||
#
|
||||
# Generated by ansible - do not edit manually
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
AUTHENTIK_DOMAIN="{{ authentik_domain }}"
|
||||
GITEA_DOMAIN="{{ gitea_domain }}"
|
||||
CLIENT_ID="{{ gitea_oauth_client_id }}"
|
||||
PROVIDER_NAME="{{ gitea_oauth_provider_name }}"
|
||||
OUTPUT_FILE="/tmp/gitea-oauth-credentials.json"
|
||||
|
||||
# Bootstrap token from Authentik
|
||||
API_TOKEN="{{ vault_authentik_bootstrap_token }}"
|
||||
|
||||
echo "============================================"
|
||||
echo "Gitea OAuth Application Setup"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Authentik: https://${AUTHENTIK_DOMAIN}"
|
||||
echo "Gitea: https://${GITEA_DOMAIN}"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Test API access
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Testing Authentik API access..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/brands/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
echo "ERROR: API authentication failed (HTTP $HTTP_CODE)"
|
||||
echo "Check that vault_authentik_bootstrap_token is correct"
|
||||
exit 1
|
||||
fi
|
||||
echo "Authentik API ready!"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get authorization flow PK
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding authorization flow..."
|
||||
AUTH_FLOW_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/flows/instances/?designation=authorization" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
AUTH_FLOW_PK=$(echo "$AUTH_FLOW_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Authorization flow: $AUTH_FLOW_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get invalidation flow PK
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding invalidation flow..."
|
||||
INVALID_FLOW_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/flows/instances/?designation=invalidation" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
INVALID_FLOW_PK=$(echo "$INVALID_FLOW_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Invalidation flow: $INVALID_FLOW_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get signing certificate
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Finding signing certificate..."
|
||||
CERT_RESPONSE=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/crypto/certificatekeypairs/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
SIGNING_KEY_PK=$(echo "$CERT_RESPONSE" | jq -r '.results[0].pk')
|
||||
echo "Signing key: $SIGNING_KEY_PK"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Get scope mappings
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Getting scope mappings..."
|
||||
SCOPE_MAPPINGS=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/propertymappings/provider/scope/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
|
||||
OPENID_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="openid") | .pk')
|
||||
PROFILE_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="profile") | .pk')
|
||||
EMAIL_PK=$(echo "$SCOPE_MAPPINGS" | jq -r '.results[] | select(.scope_name=="email") | .pk')
|
||||
|
||||
echo "Scopes: openid=$OPENID_PK, profile=$PROFILE_PK, email=$EMAIL_PK"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Check if provider already exists
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Checking for existing Gitea provider..."
|
||||
EXISTING_PROVIDER=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/?name=Gitea" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
EXISTING_PK=$(echo "$EXISTING_PROVIDER" | jq -r '.results[0].pk // empty')
|
||||
|
||||
if [ -n "$EXISTING_PK" ] && [ "$EXISTING_PK" != "null" ]; then
|
||||
echo "Provider already exists (PK: $EXISTING_PK), updating..."
|
||||
|
||||
PROVIDER_RESPONSE=$(curl -s -X PATCH \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/${EXISTING_PK}/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"redirect_uris\": [
|
||||
{\"matching_mode\": \"strict\", \"url\": \"https://${GITEA_DOMAIN}/user/oauth2/${PROVIDER_NAME}/callback\"}
|
||||
]
|
||||
}")
|
||||
|
||||
PROVIDER_PK="$EXISTING_PK"
|
||||
CLIENT_SECRET=$(echo "$EXISTING_PROVIDER" | jq -r '.results[0].client_secret // empty')
|
||||
else
|
||||
# Create OAuth2 Provider
|
||||
echo "Creating Gitea OAuth2 Provider..."
|
||||
PROVIDER_RESPONSE=$(curl -s -X POST \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/providers/oauth2/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"Gitea\",
|
||||
\"authorization_flow\": \"${AUTH_FLOW_PK}\",
|
||||
\"invalidation_flow\": \"${INVALID_FLOW_PK}\",
|
||||
\"signing_key\": \"${SIGNING_KEY_PK}\",
|
||||
\"client_type\": \"confidential\",
|
||||
\"client_id\": \"${CLIENT_ID}\",
|
||||
\"redirect_uris\": [
|
||||
{\"matching_mode\": \"strict\", \"url\": \"https://${GITEA_DOMAIN}/user/oauth2/${PROVIDER_NAME}/callback\"}
|
||||
],
|
||||
\"access_code_validity\": \"minutes=10\",
|
||||
\"access_token_validity\": \"hours=1\",
|
||||
\"refresh_token_validity\": \"days=30\",
|
||||
\"property_mappings\": [\"${OPENID_PK}\", \"${PROFILE_PK}\", \"${EMAIL_PK}\"],
|
||||
\"sub_mode\": \"user_email\",
|
||||
\"include_claims_in_id_token\": true,
|
||||
\"issuer_mode\": \"per_provider\"
|
||||
}")
|
||||
|
||||
PROVIDER_PK=$(echo "$PROVIDER_RESPONSE" | jq -r '.pk // empty')
|
||||
CLIENT_SECRET=$(echo "$PROVIDER_RESPONSE" | jq -r '.client_secret // empty')
|
||||
|
||||
if [ -z "$PROVIDER_PK" ] || [ "$PROVIDER_PK" = "null" ]; then
|
||||
echo "ERROR: Failed to create provider"
|
||||
echo "$PROVIDER_RESPONSE" | jq .
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Provider PK: $PROVIDER_PK"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Check if application already exists
|
||||
# -----------------------------------------------------------------------------
|
||||
echo "Checking for existing Gitea application..."
|
||||
EXISTING_APP=$(curl -s \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/applications/?slug=gitea" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json")
|
||||
EXISTING_APP_SLUG=$(echo "$EXISTING_APP" | jq -r '.results[0].slug // empty')
|
||||
|
||||
if [ -z "$EXISTING_APP_SLUG" ] || [ "$EXISTING_APP_SLUG" = "null" ]; then
|
||||
echo "Creating Gitea Application..."
|
||||
APP_RESPONSE=$(curl -s -X POST \
|
||||
"https://${AUTHENTIK_DOMAIN}/api/v3/core/applications/" \
|
||||
-H "Authorization: Bearer ${API_TOKEN}" \
|
||||
-H "Accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"Gitea\",
|
||||
\"slug\": \"gitea\",
|
||||
\"provider\": ${PROVIDER_PK},
|
||||
\"meta_launch_url\": \"https://${GITEA_DOMAIN}\",
|
||||
\"open_in_new_tab\": false
|
||||
}")
|
||||
|
||||
APP_SLUG=$(echo "$APP_RESPONSE" | jq -r '.slug // empty')
|
||||
if [ -z "$APP_SLUG" ] || [ "$APP_SLUG" = "null" ]; then
|
||||
echo "WARNING: Failed to create application (may already exist)"
|
||||
else
|
||||
echo "Application created: $APP_SLUG"
|
||||
fi
|
||||
else
|
||||
echo "Application already exists: $EXISTING_APP_SLUG"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Output credentials
|
||||
# -----------------------------------------------------------------------------
|
||||
cat > "$OUTPUT_FILE" << EOF
|
||||
{
|
||||
"client_id": "${CLIENT_ID}",
|
||||
"client_secret": "${CLIENT_SECRET}",
|
||||
"auto_discover_url": "https://${AUTHENTIK_DOMAIN}/application/o/gitea/.well-known/openid-configuration",
|
||||
"scopes": "email profile",
|
||||
"provider_name": "${PROVIDER_NAME}"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "============================================"
|
||||
echo "OAuth Setup Complete!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo "Credentials saved to: ${OUTPUT_FILE}"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo "MANUAL CONFIGURATION REQUIRED IN GITEA"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "1. Log into Gitea as admin:"
|
||||
echo " https://${GITEA_DOMAIN}/user/login"
|
||||
echo ""
|
||||
echo "2. Navigate to:"
|
||||
echo " Site Administration -> Authentication Sources -> Add"
|
||||
echo ""
|
||||
echo "3. Fill in the form:"
|
||||
echo " Authentication Type: OAuth2"
|
||||
echo " Authentication Name: ${PROVIDER_NAME}"
|
||||
echo " OAuth2 Provider: OpenID Connect"
|
||||
echo " Client ID: ${CLIENT_ID}"
|
||||
echo " Client Secret: ${CLIENT_SECRET}"
|
||||
echo " OpenID Connect Auto Discovery URL:"
|
||||
echo " https://${AUTHENTIK_DOMAIN}/application/o/gitea/.well-known/openid-configuration"
|
||||
echo " Additional Scopes: email profile"
|
||||
echo ""
|
||||
echo "4. Click 'Add Authentication Source'"
|
||||
echo ""
|
||||
echo "5. Test by logging out and clicking 'Sign in with ${PROVIDER_NAME}'"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "Credentials JSON:"
|
||||
cat "$OUTPUT_FILE"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user