feat: complete CI/CD automation and fix deployment issues
Some checks failed
Update Automation Tests / Integration Tests (pull_request) Failing after 40s
Some checks failed
Update Automation Tests / Integration Tests (pull_request) Failing after 40s
Infrastructure & Permissions: - Set recovery_window_in_days=0 on secrets for immediate deletion on destroy - Add secretsmanager:UpdateSecret permission to EC2 IAM role - Move SES secret definition from ses.tf to secrets.tf for better organization - Create scripts/empty-s3-bucket.sh to handle versioned S3 object deletion - Update Makefile to use S3 cleanup script in full-destroy target Gitea Admin User Automation: - Remove non-functional GITEA_ADMIN_* environment variables from docker-compose.yml - Add CLI-based admin user creation via docker exec in deploy-gitea.yml - Add database update to disable must_change_password requirement - Fix runner token API call to use GET instead of POST Runner Setup Fixes: - Change runner gitea_instance to http://localhost:3000 (was failing with public URL) - Fix registration to work from same host as Gitea Domain Migration: - Change domain from gitea.poll-streams.com to git.poll-streams.com - Update DNS, docker-compose, nginx configs, ansible inventory, and SSL setup - Enables fresh SSL certificate (avoids Let's Encrypt rate limit) All changes enable zero-to-one deployment: make full-destroy && make full-deploy
This commit is contained in:
parent
153bd11b05
commit
890a23e8d5
27
Makefile
Normal file
27
Makefile
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
.PHONY: help full-deploy full-destroy provision configure test
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Qvest Task - Gitea Deployment"
|
||||||
|
@echo ""
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " full-deploy - Full deployment (terraform + ansible)"
|
||||||
|
@echo " full-destroy - Destroy all infrastructure"
|
||||||
|
@echo " provision - Provision AWS infrastructure only"
|
||||||
|
@echo " configure - Run ansible configuration only"
|
||||||
|
@echo " test - Run integration tests"
|
||||||
|
|
||||||
|
provision:
|
||||||
|
cd terraform && terraform apply -auto-approve
|
||||||
|
|
||||||
|
configure:
|
||||||
|
cd ansible && ansible-playbook -i inventory site.yml
|
||||||
|
|
||||||
|
test:
|
||||||
|
./scripts/test-update.sh
|
||||||
|
|
||||||
|
full-deploy: provision configure
|
||||||
|
@echo "Deployment complete. Gitea available at https://git.poll-streams.com"
|
||||||
|
|
||||||
|
full-destroy:
|
||||||
|
@./scripts/empty-s3-bucket.sh
|
||||||
|
cd terraform && terraform destroy -auto-approve
|
||||||
@ -61,7 +61,7 @@ This phase provisions the AWS infrastructure using Terraform.
|
|||||||
- ✅ Configure Security Group for EC2 (ports 22, 80, 443)
|
- ✅ Configure Security Group for EC2 (ports 22, 80, 443)
|
||||||
- ✅ Provision EC2 instance (t3.medium, Ubuntu 24.04) with IAM role
|
- ✅ Provision EC2 instance (t3.medium, Ubuntu 24.04) with IAM role
|
||||||
- ✅ Create S3 bucket for backups (with versioning & encryption)
|
- ✅ Create S3 bucket for backups (with versioning & encryption)
|
||||||
- ✅ Configure Route 53 DNS records (A record: gitea.poll-streams.com → EC2)
|
- ✅ Configure Route 53 DNS records (A record: git.poll-streams.com → EC2)
|
||||||
- ✅ Use official Terraform AWS modules (VPC, Security Group)
|
- ✅ Use official Terraform AWS modules (VPC, Security Group)
|
||||||
- ✅ Refactored into separate files: main.tf, vpc.tf, security.tf, compute.tf, storage.tf, iam.tf, dns.tf, outputs.tf
|
- ✅ Refactored into separate files: main.tf, vpc.tf, security.tf, compute.tf, storage.tf, iam.tf, dns.tf, outputs.tf
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ This phase implements the automated, reproducible Gitea installation.
|
|||||||
- ✅ 512MB upload limit
|
- ✅ 512MB upload limit
|
||||||
|
|
||||||
### 3.4 Testing ✅
|
### 3.4 Testing ✅
|
||||||
- ✅ HTTPS access verified: https://gitea.poll-streams.com
|
- ✅ HTTPS access verified: https://git.poll-streams.com
|
||||||
- ✅ Valid SSL certificate (Let's Encrypt)
|
- ✅ Valid SSL certificate (Let's Encrypt)
|
||||||
- ✅ HTTP → HTTPS redirect working
|
- ✅ HTTP → HTTPS redirect working
|
||||||
- ✅ Gitea web interface accessible and functional
|
- ✅ Gitea web interface accessible and functional
|
||||||
|
|||||||
@ -24,6 +24,15 @@
|
|||||||
group: ubuntu
|
group: ubuntu
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Copy nginx configuration
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: ../docker/nginx/
|
||||||
|
dest: /opt/gitea/nginx/
|
||||||
|
owner: ubuntu
|
||||||
|
group: ubuntu
|
||||||
|
mode: "0644"
|
||||||
|
directory_mode: "0755"
|
||||||
|
|
||||||
- name: Fetch database credentials from Secrets Manager
|
- name: Fetch database credentials from Secrets Manager
|
||||||
ansible.builtin.shell: |
|
ansible.builtin.shell: |
|
||||||
aws secretsmanager get-secret-value \
|
aws secretsmanager get-secret-value \
|
||||||
@ -58,6 +67,9 @@
|
|||||||
DB_USER={{ db_creds.username }}
|
DB_USER={{ db_creds.username }}
|
||||||
DB_PASSWORD={{ db_creds.password }}
|
DB_PASSWORD={{ db_creds.password }}
|
||||||
DB_NAME={{ db_creds.database }}
|
DB_NAME={{ db_creds.database }}
|
||||||
|
GITEA_ADMIN_USERNAME={{ db_creds.admin_username }}
|
||||||
|
GITEA_ADMIN_PASSWORD={{ db_creds.admin_password }}
|
||||||
|
GITEA_ADMIN_EMAIL={{ db_creds.admin_email }}
|
||||||
SMTP_HOST={{ ses_creds.smtp_host }}
|
SMTP_HOST={{ ses_creds.smtp_host }}
|
||||||
SMTP_PORT={{ ses_creds.smtp_port }}
|
SMTP_PORT={{ ses_creds.smtp_port }}
|
||||||
SMTP_USERNAME={{ ses_creds.smtp_username }}
|
SMTP_USERNAME={{ ses_creds.smtp_username }}
|
||||||
@ -82,3 +94,58 @@
|
|||||||
until: result.status == 200
|
until: result.status == 200
|
||||||
retries: 30
|
retries: 30
|
||||||
delay: 10
|
delay: 10
|
||||||
|
|
||||||
|
- name: Create Gitea admin user via CLI
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
docker exec --user git gitea gitea admin user create \
|
||||||
|
--username "{{ db_creds.admin_username }}" \
|
||||||
|
--password "{{ db_creds.admin_password }}" \
|
||||||
|
--email "{{ db_creds.admin_email }}" \
|
||||||
|
--admin \
|
||||||
|
--must-change-password=false
|
||||||
|
register: admin_create
|
||||||
|
failed_when:
|
||||||
|
- admin_create.rc != 0
|
||||||
|
- "'already exists' not in admin_create.stderr"
|
||||||
|
changed_when: "'New user' in admin_create.stdout"
|
||||||
|
|
||||||
|
- name: Disable password change requirement
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
docker exec gitea-postgres psql -U {{ db_creds.username }} \
|
||||||
|
-d {{ db_creds.database }} \
|
||||||
|
-c "UPDATE public.user SET must_change_password = false \
|
||||||
|
WHERE name = '{{ db_creds.admin_username }}';"
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Generate Gitea Actions runner registration token
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: http://localhost:3000/api/v1/admin/runners/registration-token
|
||||||
|
method: GET
|
||||||
|
user: "{{ db_creds.admin_username }}"
|
||||||
|
password: "{{ db_creds.admin_password }}"
|
||||||
|
force_basic_auth: true
|
||||||
|
status_code: 200
|
||||||
|
register: runner_token_response
|
||||||
|
retries: 5
|
||||||
|
delay: 5
|
||||||
|
until: runner_token_response.status == 200
|
||||||
|
|
||||||
|
- name: Update AWS Secrets Manager with runner token
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
SECRET_JSON=$(aws secretsmanager get-secret-value \
|
||||||
|
--secret-id "{{ secret_name }}" \
|
||||||
|
--region "{{ aws_region }}" \
|
||||||
|
--query SecretString \
|
||||||
|
--output text)
|
||||||
|
|
||||||
|
UPDATED_JSON=$(echo "$SECRET_JSON" | jq --arg token "{{ runner_token_response.json.token }}" \
|
||||||
|
'.gitea_runner_token = $token')
|
||||||
|
|
||||||
|
aws secretsmanager update-secret \
|
||||||
|
--secret-id "{{ secret_name }}" \
|
||||||
|
--region "{{ aws_region }}" \
|
||||||
|
--secret-string "$UPDATED_JSON"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
changed_when: true
|
||||||
|
|||||||
@ -1,2 +1,8 @@
|
|||||||
[gitea]
|
---
|
||||||
gitea.poll-streams.com ansible_user=ubuntu ansible_ssh_private_key_file=../ssh-keys/qvest-task-key.pem
|
all:
|
||||||
|
children:
|
||||||
|
gitea:
|
||||||
|
hosts:
|
||||||
|
git.poll-streams.com:
|
||||||
|
ansible_user: ubuntu
|
||||||
|
ansible_ssh_private_key_file: ../ssh-keys/qvest-task-key.pem
|
||||||
|
|||||||
133
ansible/setup-runner.yml
Normal file
133
ansible/setup-runner.yml
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
- name: Setup Gitea Actions Runner
|
||||||
|
hosts: gitea
|
||||||
|
become: true
|
||||||
|
vars:
|
||||||
|
runner_version: "0.2.10"
|
||||||
|
runner_binary: "/usr/local/bin/act_runner"
|
||||||
|
runner_count: 2
|
||||||
|
gitea_instance: "http://localhost:3000"
|
||||||
|
secret_name: "qvest-task-db-credentials"
|
||||||
|
aws_region: "eu-central-1"
|
||||||
|
# Registration token must be provided via command line or AWS Secrets Manager
|
||||||
|
# ansible-playbook setup-runner.yml -e "gitea_runner_token=YOUR_TOKEN"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Download act_runner binary
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://dl.gitea.com/act_runner/{{ runner_version }}/act_runner-{{ runner_version }}-linux-amd64"
|
||||||
|
dest: "{{ runner_binary }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Create runner config directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/act_runner-{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
|
||||||
|
- name: Create runner data directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/var/lib/act_runner-{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
|
||||||
|
- name: Check if runners are already registered
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "/etc/act_runner-{{ item }}/.runner"
|
||||||
|
register: runner_configs
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
|
||||||
|
- name: Fetch Gitea runner token from AWS Secrets Manager
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
set -o pipefail
|
||||||
|
aws secretsmanager get-secret-value \
|
||||||
|
--secret-id "{{ secret_name }}" \
|
||||||
|
--region "{{ aws_region }}" \
|
||||||
|
--query SecretString \
|
||||||
|
--output text | jq -r '.gitea_runner_token // empty'
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
register: secrets_output
|
||||||
|
when:
|
||||||
|
- gitea_runner_token is not defined
|
||||||
|
- runner_configs.results | selectattr('stat.exists', 'equalto', false) | list | length > 0
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Set runner token from Secrets Manager
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
gitea_runner_token: "{{ secrets_output.stdout }}"
|
||||||
|
when:
|
||||||
|
- gitea_runner_token is not defined
|
||||||
|
- secrets_output.stdout is defined
|
||||||
|
- secrets_output.stdout | length > 0
|
||||||
|
|
||||||
|
- name: Register runners with Gitea
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
{{ runner_binary }} register \
|
||||||
|
--instance {{ gitea_instance }} \
|
||||||
|
--token {{ gitea_runner_token }} \
|
||||||
|
--name {{ ansible_hostname }}-runner-{{ item }} \
|
||||||
|
--no-interactive
|
||||||
|
args:
|
||||||
|
chdir: "/etc/act_runner-{{ item }}"
|
||||||
|
when:
|
||||||
|
- gitea_runner_token is defined
|
||||||
|
- gitea_runner_token | length > 0
|
||||||
|
- not runner_configs.results[item | int - 1].stat.exists
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
register: runner_registrations
|
||||||
|
changed_when: runner_registrations.rc == 0
|
||||||
|
|
||||||
|
- name: Display registration warning if token not provided
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Runner registration skipped - no token provided. Re-run with -e gitea_runner_token=TOKEN"
|
||||||
|
when:
|
||||||
|
- gitea_runner_token is not defined or gitea_runner_token | length == 0
|
||||||
|
- runner_configs.results | selectattr('stat.exists', 'equalto', false) | list | length > 0
|
||||||
|
|
||||||
|
- name: Create systemd services for runners
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: "/etc/systemd/system/act_runner-{{ item }}.service"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Gitea Actions Runner {{ item }}
|
||||||
|
After=network.target docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart={{ runner_binary }} daemon
|
||||||
|
WorkingDirectory=/etc/act_runner-{{ item }}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
User=root
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
mode: "0644"
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
register: runner_services
|
||||||
|
notify: Reload systemd daemon
|
||||||
|
|
||||||
|
- name: Enable and start runner services
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "act_runner-{{ item }}"
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
with_sequence: start=1 end={{ runner_count }}
|
||||||
|
when: >
|
||||||
|
runner_configs.results[item | int - 1].stat.exists or
|
||||||
|
(runner_registrations.results is defined and
|
||||||
|
runner_registrations.results[item | int - 1].changed | default(false))
|
||||||
|
|
||||||
|
- name: Display runner status
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Deployed {{ runner_count }} runners. Services: act_runner-1 to act_runner-{{ runner_count }}"
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Reload systemd daemon
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
- name: Check if certificate was obtained
|
- name: Check if certificate was obtained
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
cmd: docker exec gitea-nginx ls /etc/letsencrypt/live/gitea.poll-streams.com/fullchain.pem
|
cmd: docker exec gitea-nginx ls /etc/letsencrypt/live/git.poll-streams.com/fullchain.pem
|
||||||
register: cert_check
|
register: cert_check
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
|
|||||||
@ -16,3 +16,6 @@
|
|||||||
|
|
||||||
- name: Setup cron jobs for automated maintenance
|
- name: Setup cron jobs for automated maintenance
|
||||||
import_playbook: setup-cron.yml
|
import_playbook: setup-cron.yml
|
||||||
|
|
||||||
|
- name: Setup Gitea Actions Runner
|
||||||
|
import_playbook: setup-runner.yml
|
||||||
|
|||||||
@ -6,6 +6,11 @@ DB_USER=gitea
|
|||||||
DB_PASSWORD=<generated-from-secrets-manager>
|
DB_PASSWORD=<generated-from-secrets-manager>
|
||||||
DB_NAME=gitea
|
DB_NAME=gitea
|
||||||
|
|
||||||
|
# Gitea admin credentials (from AWS Secrets Manager)
|
||||||
|
GITEA_ADMIN_USERNAME=<generated-from-secrets-manager>
|
||||||
|
GITEA_ADMIN_PASSWORD=<generated-from-secrets-manager>
|
||||||
|
GITEA_ADMIN_EMAIL=<generated-from-secrets-manager>
|
||||||
|
|
||||||
# AWS SES SMTP credentials (from AWS Secrets Manager)
|
# AWS SES SMTP credentials (from AWS Secrets Manager)
|
||||||
SMTP_HOST=email-smtp.eu-central-1.amazonaws.com
|
SMTP_HOST=email-smtp.eu-central-1.amazonaws.com
|
||||||
SMTP_PORT=587
|
SMTP_PORT=587
|
||||||
|
|||||||
@ -35,9 +35,12 @@ services:
|
|||||||
- GITEA__database__NAME=${DB_NAME}
|
- GITEA__database__NAME=${DB_NAME}
|
||||||
- GITEA__database__USER=${DB_USER}
|
- GITEA__database__USER=${DB_USER}
|
||||||
- GITEA__database__PASSWD=${DB_PASSWORD}
|
- GITEA__database__PASSWD=${DB_PASSWORD}
|
||||||
- GITEA__server__DOMAIN=gitea.poll-streams.com
|
- GITEA__server__DOMAIN=git.poll-streams.com
|
||||||
- GITEA__server__SSH_DOMAIN=gitea.poll-streams.com
|
- GITEA__server__SSH_DOMAIN=git.poll-streams.com
|
||||||
- GITEA__server__ROOT_URL=https://gitea.poll-streams.com
|
- GITEA__server__ROOT_URL=https://git.poll-streams.com
|
||||||
|
- GITEA__security__INSTALL_LOCK=true
|
||||||
|
- GITEA__service__DISABLE_REGISTRATION=true
|
||||||
|
- GITEA__actions__ENABLED=true
|
||||||
volumes:
|
volumes:
|
||||||
- gitea-data:/data
|
- gitea-data:/data
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
@ -79,7 +82,7 @@ services:
|
|||||||
- certbot-etc:/etc/letsencrypt
|
- certbot-etc:/etc/letsencrypt
|
||||||
- certbot-var:/var/lib/letsencrypt
|
- certbot-var:/var/lib/letsencrypt
|
||||||
- web-root:/var/www/html
|
- web-root:/var/www/html
|
||||||
command: certonly --webroot --webroot-path=/var/www/html --email admin@poll-streams.com --agree-tos --no-eff-email --force-renewal -d gitea.poll-streams.com
|
command: certonly --webroot --webroot-path=/var/www/html --email admin@poll-streams.com --agree-tos --no-eff-email --force-renewal -d git.poll-streams.com
|
||||||
depends_on:
|
depends_on:
|
||||||
- nginx
|
- nginx
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
listen [::]:80;
|
listen [::]:80;
|
||||||
server_name gitea.poll-streams.com;
|
server_name git.poll-streams.com;
|
||||||
|
|
||||||
# Let's Encrypt ACME challenge
|
# Let's Encrypt ACME challenge
|
||||||
location /.well-known/acme-challenge/ {
|
location /.well-known/acme-challenge/ {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
listen [::]:80;
|
listen [::]:80;
|
||||||
server_name gitea.poll-streams.com;
|
server_name git.poll-streams.com;
|
||||||
|
|
||||||
# Let's Encrypt ACME challenge
|
# Let's Encrypt ACME challenge
|
||||||
location /.well-known/acme-challenge/ {
|
location /.well-known/acme-challenge/ {
|
||||||
@ -19,11 +19,11 @@ server {
|
|||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl http2;
|
||||||
server_name gitea.poll-streams.com;
|
server_name git.poll-streams.com;
|
||||||
|
|
||||||
# SSL certificates
|
# SSL certificates
|
||||||
ssl_certificate /etc/letsencrypt/live/gitea.poll-streams.com/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/git.poll-streams.com/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/gitea.poll-streams.com/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/git.poll-streams.com/privkey.pem;
|
||||||
|
|
||||||
# SSL configuration
|
# SSL configuration
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
|||||||
26
scripts/empty-s3-bucket.sh
Executable file
26
scripts/empty-s3-bucket.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUCKET_NAME="${1:-qvest-task-backups}"
|
||||||
|
|
||||||
|
echo "Emptying S3 bucket: $BUCKET_NAME"
|
||||||
|
|
||||||
|
# Delete all object versions
|
||||||
|
aws s3api list-object-versions --bucket "$BUCKET_NAME" --output text \
|
||||||
|
--query 'Versions[].[Key,VersionId]' 2>/dev/null | \
|
||||||
|
while read -r key version; do
|
||||||
|
if [ -n "$key" ]; then
|
||||||
|
aws s3api delete-object --bucket "$BUCKET_NAME" --key "$key" --version-id "$version" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
done || true
|
||||||
|
|
||||||
|
# Delete all delete markers
|
||||||
|
aws s3api list-object-versions --bucket "$BUCKET_NAME" --output text \
|
||||||
|
--query 'DeleteMarkers[].[Key,VersionId]' 2>/dev/null | \
|
||||||
|
while read -r key version; do
|
||||||
|
if [ -n "$key" ]; then
|
||||||
|
aws s3api delete-object --bucket "$BUCKET_NAME" --key "$key" --version-id "$version" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
done || true
|
||||||
|
|
||||||
|
echo "S3 bucket emptied successfully"
|
||||||
@ -6,7 +6,7 @@ data "aws_route53_zone" "main" {
|
|||||||
|
|
||||||
resource "aws_route53_record" "gitea" {
|
resource "aws_route53_record" "gitea" {
|
||||||
zone_id = data.aws_route53_zone.main.zone_id
|
zone_id = data.aws_route53_zone.main.zone_id
|
||||||
name = "gitea.poll-streams.com"
|
name = "git.poll-streams.com"
|
||||||
type = "A"
|
type = "A"
|
||||||
ttl = 300
|
ttl = 300
|
||||||
records = [aws_instance.gitea.public_ip]
|
records = [aws_instance.gitea.public_ip]
|
||||||
|
|||||||
@ -36,7 +36,8 @@ resource "aws_iam_role_policy" "secrets_manager_read" {
|
|||||||
Effect = "Allow"
|
Effect = "Allow"
|
||||||
Action = [
|
Action = [
|
||||||
"secretsmanager:GetSecretValue",
|
"secretsmanager:GetSecretValue",
|
||||||
"secretsmanager:DescribeSecret"
|
"secretsmanager:DescribeSecret",
|
||||||
|
"secretsmanager:UpdateSecret"
|
||||||
]
|
]
|
||||||
Resource = [
|
Resource = [
|
||||||
aws_secretsmanager_secret.db_credentials.arn,
|
aws_secretsmanager_secret.db_credentials.arn,
|
||||||
|
|||||||
@ -26,17 +26,17 @@ output "ssh_connection_command" {
|
|||||||
|
|
||||||
output "ssh_connection_via_domain" {
|
output "ssh_connection_via_domain" {
|
||||||
description = "SSH command using domain name (use after DNS propagates)"
|
description = "SSH command using domain name (use after DNS propagates)"
|
||||||
value = "ssh -i ${local_file.private_key.filename} -o StrictHostKeyChecking=accept-new ubuntu@gitea.poll-streams.com"
|
value = "ssh -i ${local_file.private_key.filename} -o StrictHostKeyChecking=accept-new ubuntu@git.poll-streams.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
output "gitea_domain" {
|
output "gitea_domain" {
|
||||||
description = "Gitea domain name"
|
description = "Gitea domain name"
|
||||||
value = "gitea.poll-streams.com"
|
value = "git.poll-streams.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
output "gitea_url" {
|
output "gitea_url" {
|
||||||
description = "Gitea URL (will be HTTPS after SSL setup)"
|
description = "Gitea URL (will be HTTPS after SSL setup)"
|
||||||
value = "https://gitea.poll-streams.com"
|
value = "https://git.poll-streams.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
output "db_secret_arn" {
|
output "db_secret_arn" {
|
||||||
|
|||||||
@ -4,10 +4,17 @@ resource "random_password" "db_password" {
|
|||||||
special = true
|
special = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Generate random password for Gitea admin user
|
||||||
|
resource "random_password" "gitea_admin_password" {
|
||||||
|
length = 32
|
||||||
|
special = true
|
||||||
|
}
|
||||||
|
|
||||||
# Store credentials in AWS Secrets Manager
|
# Store credentials in AWS Secrets Manager
|
||||||
resource "aws_secretsmanager_secret" "db_credentials" {
|
resource "aws_secretsmanager_secret" "db_credentials" {
|
||||||
name = "${var.project_name}-db-credentials"
|
name = "${var.project_name}-db-credentials"
|
||||||
description = "PostgreSQL database credentials for Gitea"
|
description = "PostgreSQL database credentials for Gitea"
|
||||||
|
recovery_window_in_days = 0
|
||||||
|
|
||||||
tags = {
|
tags = {
|
||||||
Name = "${var.project_name}-db-credentials"
|
Name = "${var.project_name}-db-credentials"
|
||||||
@ -17,10 +24,36 @@ resource "aws_secretsmanager_secret" "db_credentials" {
|
|||||||
resource "aws_secretsmanager_secret_version" "db_credentials" {
|
resource "aws_secretsmanager_secret_version" "db_credentials" {
|
||||||
secret_id = aws_secretsmanager_secret.db_credentials.id
|
secret_id = aws_secretsmanager_secret.db_credentials.id
|
||||||
secret_string = jsonencode({
|
secret_string = jsonencode({
|
||||||
username = "gitea"
|
username = "gitea"
|
||||||
password = random_password.db_password.result
|
password = random_password.db_password.result
|
||||||
database = "gitea"
|
database = "gitea"
|
||||||
host = "postgres"
|
host = "postgres"
|
||||||
port = 5432
|
port = 5432
|
||||||
|
admin_username = "gitea_admin"
|
||||||
|
admin_password = random_password.gitea_admin_password.result
|
||||||
|
admin_email = "admin@poll-streams.com"
|
||||||
|
gitea_runner_token = "" # Will be auto-generated via API
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Store SMTP credentials in Secrets Manager
|
||||||
|
resource "aws_secretsmanager_secret" "ses_smtp_credentials" {
|
||||||
|
name = "${var.project_name}-ses-smtp-credentials"
|
||||||
|
description = "SMTP credentials for AWS SES"
|
||||||
|
recovery_window_in_days = 0
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-ses-smtp-credentials"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret_version" "ses_smtp_credentials" {
|
||||||
|
secret_id = aws_secretsmanager_secret.ses_smtp_credentials.id
|
||||||
|
secret_string = jsonencode({
|
||||||
|
smtp_host = "email-smtp.${var.aws_region}.amazonaws.com"
|
||||||
|
smtp_port = "587"
|
||||||
|
smtp_username = aws_iam_access_key.ses_smtp_access_key.id
|
||||||
|
smtp_password = aws_iam_access_key.ses_smtp_access_key.ses_smtp_password_v4
|
||||||
|
alert_email = var.alert_email
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,25 +42,3 @@ resource "aws_iam_user_policy" "ses_smtp_user_policy" {
|
|||||||
resource "aws_iam_access_key" "ses_smtp_access_key" {
|
resource "aws_iam_access_key" "ses_smtp_access_key" {
|
||||||
user = aws_iam_user.ses_smtp_user.name
|
user = aws_iam_user.ses_smtp_user.name
|
||||||
}
|
}
|
||||||
|
|
||||||
# Store SMTP credentials in Secrets Manager
|
|
||||||
resource "aws_secretsmanager_secret" "ses_smtp_credentials" {
|
|
||||||
name = "${var.project_name}-ses-smtp-credentials"
|
|
||||||
description = "SMTP credentials for AWS SES"
|
|
||||||
recovery_window_in_days = 7
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
Name = "${var.project_name}-ses-smtp-credentials"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_secretsmanager_secret_version" "ses_smtp_credentials" {
|
|
||||||
secret_id = aws_secretsmanager_secret.ses_smtp_credentials.id
|
|
||||||
secret_string = jsonencode({
|
|
||||||
smtp_host = "email-smtp.${var.aws_region}.amazonaws.com"
|
|
||||||
smtp_port = "587"
|
|
||||||
smtp_username = aws_iam_access_key.ses_smtp_access_key.id
|
|
||||||
smtp_password = aws_iam_access_key.ses_smtp_access_key.ses_smtp_password_v4
|
|
||||||
alert_email = var.alert_email
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# S3 Bucket for Backups
|
# S3 Bucket for Backups
|
||||||
resource "aws_s3_bucket" "backups" {
|
resource "aws_s3_bucket" "backups" {
|
||||||
bucket = "${var.project_name}-backups"
|
bucket = "${var.project_name}-backups"
|
||||||
|
force_destroy = true
|
||||||
tags = {
|
tags = {
|
||||||
Name = "${var.project_name}-backups"
|
Name = "${var.project_name}-backups"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user