cloud infra
0

Configure Feed

Select the types of activity you want to include in your feed.

add stuff....

nagee elghassein (Nov 7, 2025, 4:36 PM -0800) df0fa871 b36da66b

+185 -25
+11 -14
ansible/playbooks/containers.yml
··· 1 1 - name: Prepare dev server (dependencies only) 2 - hosts: dev 2 + hosts: [dev, prod] 3 3 become: true 4 4 tags: deps 5 5 ··· 21 21 enabled: true 22 22 23 23 - name: Configure dev services (dockerized) 24 - hosts: dev 24 + hosts: [dev, prod] 25 25 become: true 26 26 tags: services 27 + vars: 28 + default_networks: 29 + - name: caddy 27 30 vars_files: 28 31 - ../vars/secrets.yml # Load the encrypted variables 29 32 - ../vars/services.yml # Load the services configuration 30 - vars: 31 - blog_image: registry.digitalocean.com/isthisnagee/blog:latest 32 - blog_container_name: blog 33 - blog_port: 80 34 - blog_domain: dev-blog.nagee.dev 35 - 36 33 tasks: 37 34 - name: Ensure Docker network for reverse proxy exists 38 35 community.docker.docker_network: ··· 66 63 restart_policy: always 67 64 labels: 68 65 caddy: "{{ item.domain }}" 69 - caddy.reverse_proxy: "{{ item.container_name }}:{{ item.port }}" 70 - networks: 71 - - name: caddy 66 + caddy.reverse_proxy: "{{ item.container_name }}:{{ item.proxy_port }}" 67 + networks: "{{ default_networks + item.networks | default([]) }}" 68 + ports: "{{ item.ports | default([]) }}" 72 69 expose: 73 - - "{{ item.port }}" 74 - volumes: 75 - - "/mnt/data/{{ item.container_name }}:/data" 70 + - "{{ item.proxy_port }}" 71 + env: "{{ item.env| default({}) }}" 72 + volumes: "{{ item.volumes | default(['/mnt/data/' + item.container_name + ':/data']) }}" 76 73 loop: "{{ services }}" 77 74 when: inventory_hostname in item.hosts
+90
ansible/playbooks/update-container.yml
··· 1 + --- 2 + - name: Update a specific service container if image changed 3 + hosts: [dev, prod] 4 + become: true 5 + vars_files: 6 + - ../vars/secrets.yml 7 + - ../vars/services.yml 8 + 9 + vars: 10 + target_service: "{{ service }}" 11 + default_networks: 12 + - name: caddy 13 + 14 + tasks: 15 + - name: Find target service definition 16 + set_fact: 17 + service_def: "{{ (services | selectattr('name', 'equalto', target_service) | list).0 }}" 18 + when: services | selectattr('name', 'equalto', target_service) | list | length > 0 19 + 20 + - name: Fail if service not found 21 + fail: 22 + msg: "Service '{{ target_service }}' not found in vars/services.yml" 23 + when: service_def is not defined 24 + 25 + - name: Log in to DigitalOcean Container Registry 26 + community.docker.docker_login: 27 + registry_url: registry.digitalocean.com 28 + username: "do_token" 29 + password: "{{ do_token }}" 30 + 31 + - name: Pull the latest image 32 + community.docker.docker_image: 33 + name: "{{ service_def.image }}" 34 + source: pull 35 + register: pulled_image 36 + 37 + - name: Get current container info (if running) 38 + community.docker.docker_container_info: 39 + name: "{{ service_def.container_name }}" 40 + register: current_container 41 + ignore_errors: true 42 + 43 + - name: Extract current and pulled image IDs 44 + set_fact: 45 + current_image_id: >- 46 + {{ 47 + (current_container.containers[0].ImageID 48 + if (current_container is defined 49 + and 'containers' in current_container 50 + and current_container.containers | length > 0) 51 + else None) 52 + }} 53 + pulled_image_id: "{{ pulled_image.image.Id | default(None) }}" 54 + 55 + - name: Determine if container image differs 56 + set_fact: 57 + image_changed: >- 58 + {{ current_image_id is not defined 59 + or pulled_image_id is not defined 60 + or current_image_id != pulled_image_id }} 61 + 62 + - debug: 63 + msg: "Image changed: {{ image_changed }} (current={{ current_image_id }}, pulled={{ pulled_image_id }})" 64 + 65 + 66 + - name: Print whether image changed 67 + debug: 68 + msg: > 69 + {% if image_changed %} 70 + Image for {{ service_def.name }} changed — will recreate container. 71 + {% else %} 72 + Image for {{ service_def.name }} is up-to-date. 73 + {% endif %} 74 + 75 + - name: Recreate container only if image changed 76 + community.docker.docker_container: 77 + name: "{{ service_def.container_name }}" 78 + image: "{{ service_def.image }}" 79 + restart_policy: always 80 + recreate: true 81 + labels: 82 + caddy: "{{ service_def.domain }}" 83 + caddy.reverse_proxy: "{{ service_def.container_name }}:{{ service_def.proxy_port }}" 84 + networks: "{{ default_networks + service_def.networks | default([]) }}" 85 + ports: "{{ service_def.ports | default([]) }}" 86 + expose: 87 + - "{{ service_def.proxy_port }}" 88 + env: "{{ service_def.env| default({}) }}" 89 + volumes: "{{ service_def.volumes | default(['/mnt/data/' + service_def.container_name + ':/data']) }}" 90 + when: image_changed | bool
+10 -9
ansible/vars/secrets.yml
··· 1 1 $ANSIBLE_VAULT;1.1;AES256 2 - 62633561323834623266616431626232306533303962633332373336396338306636623335636633 3 - 3231376364613762653532343462383966636339656530650a323561316130313333386333326431 4 - 38333639663864636234623032663662323430636535346630316361356330336339633261633663 5 - 3461643165623836390a313465326236663336333038663938346338383338376166333838626266 6 - 34643435333832346531393135646533666333316363636233306566303265623032663039343730 7 - 32616364396339333337373538373532643666323431363865303234643261343038333239636331 8 - 32376563393464623033376164656230303134633731303139623134383662313562386565623232 9 - 61656163373061643263363433373638333732393733616236343338623231353162323839346138 10 - 6432 2 + 39623038353630663831643635323265396165333965373433346138626339323966343538313034 3 + 6536303932373431313731363832393435333334623633310a363564616532333864616262363762 4 + 66353235656336656161386263343531353234386531626539366663343934393436323866383432 5 + 3063383538666464300a616632366539633635336165643830333633376236613535306431373237 6 + 34373834623966643931363230643131316166343736626432343832323337666630633964346530 7 + 30353438393934363737313163636562333338313766333130613630663664373135313766393261 8 + 66326130656364666639396535633566383436303663306337656638336263663661626534356261 9 + 63303339343337343661336630303138623936333330616165306330316638623732366230353632 10 + 37396535386262386262623133383236366263616265373437633535393563626366323166383738 11 + 3635643863363333646637366131353735353262386332383666
+55 -2
ansible/vars/services.yml
··· 1 1 services: 2 2 - name: blog 3 3 hosts: ['devserver'] 4 - image: registry.digitalocean.com/isthisnagee/blog:latest 4 + image: registry.digitalocean.com/isthisnagee/registry:blog-latest 5 5 container_name: blog 6 - port: 80 6 + proxy_port: 80 7 7 domain: dev-blog.nagee.dev 8 + - name: home 9 + hosts: ['devserver'] 10 + image: registry.digitalocean.com/isthisnagee/registry:home-latest 11 + container_name: home 12 + proxy_port: 8080 13 + domain: dev-home.nagee.dev 14 + - name: home 15 + hosts: ['prodserver'] 16 + image: registry.digitalocean.com/isthisnagee/registry:home-prod 17 + container_name: home 18 + proxy_port: 8080 19 + ports: 20 + - "8091:8080" 21 + domain: isthisnagee.com 22 + - name: clock-in 23 + hosts: ['prodserver'] 24 + image: registry.digitalocean.com/isthisnagee/registry:clock-in-prod 25 + container_name: clock-in 26 + proxy_port: 8080 27 + ports: 28 + - "8092:8080" 29 + domain: clock-in.isthisnagee.com 30 + - name: gitea 31 + hosts: ['prodserver'] 32 + image: gitea/gitea:latest 33 + container_name: gitea 34 + proxy_port: 3000 35 + env: 36 + USER_UID: '1001' 37 + USER_GID: '1001' 38 + GITEA__database__DB_TYPE: postgres 39 + GITEA__database__HOST: db:5432 40 + GITEA__database__NAME: gitea 41 + GITEA__database__USER: gitea 42 + GITEA__database__PASSWD: "{{ gitea_pwd }}" 43 + domain: git.nagee.dev 44 + networks: 45 + - name: gitea_gitea 46 + ports: 47 + - "3000:3000" 48 + - "127.0.0.1:2222:22" 49 + - "222:22" 50 + volumes: 51 + - /home/nagee/gitea:/data 52 + - /etc/timezone:/etc/timezone:ro 53 + - /etc/localtime:/etc/localtime:ro 54 + - /home/git/.ssh/:/data/git/.ssh 55 + # - name: drone 56 + # hosts: ['prodserver'] 57 + # image: drone/drone:2 58 + # container_name: drone 59 + # proxy_port: 8090 60 + # domain: ci.nagee.dev
+19
dns.tf
··· 6 6 secret_key = var.porkbun_secret_key 7 7 } 8 8 9 + # isthisnagee.com DNS records 10 + resource "porkbun_dns_record" "home_isthisnagee" { 11 + domain = "isthisnagee.com" 12 + subdomain = "" 13 + type = "A" 14 + content = "137.184.81.138" 15 + ttl = 60 16 + } 17 + 18 + # clock-in.isthisnagee.com DNS records 19 + resource "porkbun_dns_record" "clock_in_isthisnagee" { 20 + domain = "isthisnagee.com" 21 + subdomain = "clock-in" 22 + type = "A" 23 + content = "137.184.81.138" 24 + ttl = 60 25 + } 26 + 27 + 9 28 resource "porkbun_dns_record" "books_isthisnagee" { 10 29 domain = "isthisnagee.com" 11 30