Add infra setup: Terraform for DO droplet + Cloudflare DNS, Ansible roles for Gitea, Vaultwarden, and Gitea runner
This commit is contained in:
10
infra/ansible/roles/gitea-runner/defaults/main.yml
Normal file
10
infra/ansible/roles/gitea-runner/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
gitea_runner_version: "0.2.11"
|
||||
gitea_runner_data_dir: /var/lib/gitea-runner
|
||||
gitea_instance_url: "https://git.example.com"
|
||||
|
||||
# Generate in Gitea: Site Admin → Actions → Runners → Create new runner
|
||||
gitea_runner_token: ""
|
||||
|
||||
gitea_runner_name: "{{ inventory_hostname }}"
|
||||
gitea_runner_labels: "ubuntu-latest:docker://node:20"
|
||||
6
infra/ansible/roles/gitea-runner/handlers/main.yml
Normal file
6
infra/ansible/roles/gitea-runner/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Restart gitea-runner
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ gitea_runner_data_dir }}"
|
||||
state: present
|
||||
recreate: always
|
||||
27
infra/ansible/roles/gitea-runner/tasks/main.yml
Normal file
27
infra/ansible/roles/gitea-runner/tasks/main.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: Create gitea-runner data directory
|
||||
file:
|
||||
path: "{{ gitea_runner_data_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Deploy docker-compose file
|
||||
template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ gitea_runner_data_dir }}/docker-compose.yml"
|
||||
mode: "0600"
|
||||
notify: Restart gitea-runner
|
||||
|
||||
- name: Deploy runner config
|
||||
template:
|
||||
src: config.yml.j2
|
||||
dest: "{{ gitea_runner_data_dir }}/config.yml"
|
||||
mode: "0600"
|
||||
notify: Restart gitea-runner
|
||||
|
||||
- name: Start gitea-runner
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ gitea_runner_data_dir }}"
|
||||
state: present
|
||||
17
infra/ansible/roles/gitea-runner/templates/config.yml.j2
Normal file
17
infra/ansible/roles/gitea-runner/templates/config.yml.j2
Normal file
@@ -0,0 +1,17 @@
|
||||
log:
|
||||
level: info
|
||||
|
||||
runner:
|
||||
file: /data/.runner
|
||||
capacity: 2 # max concurrent jobs — lower if droplet is under load
|
||||
labels:
|
||||
- "ubuntu-latest:docker://node:20"
|
||||
- "ubuntu-22.04:docker://node:20"
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
dir: /data/cache
|
||||
|
||||
container:
|
||||
network: bridge
|
||||
force_pull: false # reuse cached images to speed up builds
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
gitea-runner:
|
||||
image: gitea/act_runner:{{ gitea_runner_version }}
|
||||
container_name: gitea-runner
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- {{ gitea_runner_data_dir }}/config.yml:/config.yml
|
||||
- {{ gitea_runner_data_dir }}/data:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock # allows runner to spin up job containers
|
||||
environment:
|
||||
CONFIG_FILE: /config.yml
|
||||
GITEA_INSTANCE_URL: "{{ gitea_instance_url }}"
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: "{{ gitea_runner_token }}"
|
||||
GITEA_RUNNER_NAME: "{{ gitea_runner_name }}"
|
||||
10
infra/ansible/roles/gitea/defaults/main.yml
Normal file
10
infra/ansible/roles/gitea/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
gitea_version: "1.22.3"
|
||||
gitea_domain: "git.example.com"
|
||||
gitea_http_port: 3000
|
||||
gitea_ssh_port: 2222
|
||||
gitea_data_dir: /var/lib/gitea
|
||||
|
||||
# Cloudflare Origin Certificate
|
||||
cf_origin_cert: ""
|
||||
cf_origin_key: ""
|
||||
11
infra/ansible/roles/gitea/handlers/main.yml
Normal file
11
infra/ansible/roles/gitea/handlers/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Restart gitea
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ gitea_data_dir }}"
|
||||
state: present
|
||||
recreate: always
|
||||
|
||||
- name: Reload nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
88
infra/ansible/roles/gitea/tasks/main.yml
Normal file
88
infra/ansible/roles/gitea/tasks/main.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
- name: Install dependencies
|
||||
apt:
|
||||
name: [nginx, docker.io, docker-compose-v2]
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Enable and start Docker
|
||||
systemd:
|
||||
name: docker
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Create gitea data directory
|
||||
file:
|
||||
path: "{{ gitea_data_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Deploy docker-compose file
|
||||
template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ gitea_data_dir }}/docker-compose.yml"
|
||||
mode: "0600"
|
||||
notify: Restart gitea
|
||||
|
||||
- name: Start gitea
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ gitea_data_dir }}"
|
||||
state: present
|
||||
|
||||
# ─── Cloudflare Origin Certificate ───────────────────────────────────────────
|
||||
|
||||
- name: Create SSL directory
|
||||
file:
|
||||
path: /etc/nginx/ssl
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Install Cloudflare origin certificate
|
||||
copy:
|
||||
content: "{{ cf_origin_cert }}"
|
||||
dest: /etc/nginx/ssl/cf-origin.pem
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Install Cloudflare origin key
|
||||
copy:
|
||||
content: "{{ cf_origin_key }}"
|
||||
dest: /etc/nginx/ssl/cf-origin.key
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
notify: Reload nginx
|
||||
|
||||
# ─── nginx ────────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Deploy nginx config
|
||||
template:
|
||||
src: nginx.conf.j2
|
||||
dest: /etc/nginx/sites-available/gitea
|
||||
mode: "0644"
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Enable nginx site
|
||||
file:
|
||||
src: /etc/nginx/sites-available/gitea
|
||||
dest: /etc/nginx/sites-enabled/gitea
|
||||
state: link
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Remove nginx default site
|
||||
file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Ensure nginx is started
|
||||
systemd:
|
||||
name: nginx
|
||||
enabled: true
|
||||
state: started
|
||||
19
infra/ansible/roles/gitea/templates/docker-compose.yml.j2
Normal file
19
infra/ansible/roles/gitea/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:{{ gitea_version }}
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- {{ gitea_data_dir }}/data:/data
|
||||
environment:
|
||||
USER_UID: 1000
|
||||
USER_GID: 1000
|
||||
GITEA__server__DOMAIN: "{{ gitea_domain }}"
|
||||
GITEA__server__ROOT_URL: "https://{{ gitea_domain }}/"
|
||||
GITEA__server__HTTP_PORT: 3000
|
||||
GITEA__server__SSH_DOMAIN: "{{ gitea_domain }}"
|
||||
GITEA__server__SSH_PORT: "{{ gitea_ssh_port }}"
|
||||
GITEA__server__START_SSH_SERVER: "true"
|
||||
ports:
|
||||
- "127.0.0.1:{{ gitea_http_port }}:3000"
|
||||
- "{{ gitea_ssh_port }}:22"
|
||||
24
infra/ansible/roles/gitea/templates/nginx.conf.j2
Normal file
24
infra/ansible/roles/gitea/templates/nginx.conf.j2
Normal file
@@ -0,0 +1,24 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ gitea_domain }};
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name {{ gitea_domain }};
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/cf-origin.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/cf-origin.key;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:{{ gitea_http_port }};
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
18
infra/ansible/roles/vaultwarden/defaults/main.yml
Normal file
18
infra/ansible/roles/vaultwarden/defaults/main.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
vaultwarden_domain: "vault.example.com"
|
||||
vaultwarden_port: 8080
|
||||
vaultwarden_data_dir: /var/lib/vaultwarden
|
||||
|
||||
# Set to your postgres connection string or leave as default for SQLite
|
||||
vaultwarden_database_url: "" # e.g. postgresql://user:pass@host/vaultwarden
|
||||
|
||||
# Restrict signups after first admin account is created
|
||||
vaultwarden_signups_allowed: "true"
|
||||
|
||||
# Admin token — set this to a strong random string
|
||||
# Generate with: openssl rand -base64 48
|
||||
vaultwarden_admin_token: ""
|
||||
|
||||
# Cloudflare Origin Certificate
|
||||
cf_origin_cert: ""
|
||||
cf_origin_key: ""
|
||||
11
infra/ansible/roles/vaultwarden/handlers/main.yml
Normal file
11
infra/ansible/roles/vaultwarden/handlers/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Restart vaultwarden
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ vaultwarden_data_dir }}"
|
||||
state: present
|
||||
recreate: always
|
||||
|
||||
- name: Reload nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
76
infra/ansible/roles/vaultwarden/tasks/main.yml
Normal file
76
infra/ansible/roles/vaultwarden/tasks/main.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
- name: Install dependencies
|
||||
apt:
|
||||
name: [docker.io, docker-compose-v2]
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Enable and start Docker
|
||||
systemd:
|
||||
name: docker
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Create vaultwarden data directory
|
||||
file:
|
||||
path: "{{ vaultwarden_data_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Deploy docker-compose file
|
||||
template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ vaultwarden_data_dir }}/docker-compose.yml"
|
||||
mode: "0600"
|
||||
notify: Restart vaultwarden
|
||||
|
||||
- name: Start vaultwarden
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ vaultwarden_data_dir }}"
|
||||
state: present
|
||||
|
||||
# ─── Cloudflare Origin Certificate ───────────────────────────────────────────
|
||||
|
||||
- name: Create SSL directory
|
||||
file:
|
||||
path: /etc/nginx/ssl
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
|
||||
- name: Install Cloudflare origin certificate
|
||||
copy:
|
||||
content: "{{ cf_origin_cert }}"
|
||||
dest: /etc/nginx/ssl/cf-origin.pem
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Install Cloudflare origin key
|
||||
copy:
|
||||
content: "{{ cf_origin_key }}"
|
||||
dest: /etc/nginx/ssl/cf-origin.key
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
notify: Reload nginx
|
||||
|
||||
# ─── nginx ────────────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Deploy nginx config
|
||||
template:
|
||||
src: nginx.conf.j2
|
||||
dest: /etc/nginx/sites-available/vaultwarden
|
||||
mode: "0644"
|
||||
notify: Reload nginx
|
||||
|
||||
- name: Enable nginx site
|
||||
file:
|
||||
src: /etc/nginx/sites-available/vaultwarden
|
||||
dest: /etc/nginx/sites-enabled/vaultwarden
|
||||
state: link
|
||||
notify: Reload nginx
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
vaultwarden:
|
||||
image: vaultwarden/server:latest
|
||||
container_name: vaultwarden
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- {{ vaultwarden_data_dir }}/data:/data
|
||||
environment:
|
||||
DOMAIN: "https://{{ vaultwarden_domain }}"
|
||||
SIGNUPS_ALLOWED: "{{ vaultwarden_signups_allowed }}"
|
||||
ADMIN_TOKEN: "{{ vaultwarden_admin_token }}"
|
||||
{% if vaultwarden_database_url %}
|
||||
DATABASE_URL: "{{ vaultwarden_database_url }}"
|
||||
{% endif %}
|
||||
ports:
|
||||
- "127.0.0.1:{{ vaultwarden_port }}:80"
|
||||
27
infra/ansible/roles/vaultwarden/templates/nginx.conf.j2
Normal file
27
infra/ansible/roles/vaultwarden/templates/nginx.conf.j2
Normal file
@@ -0,0 +1,27 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ vaultwarden_domain }};
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name {{ vaultwarden_domain }};
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/cf-origin.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/cf-origin.key;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
# Required for Bitwarden web vault
|
||||
client_max_body_size 525m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:{{ vaultwarden_port }};
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user