diff --git a/inventory/my-cluster/host_vars/dawarich b/inventory/my-cluster/host_vars/dawarich new file mode 100644 index 0000000..f9e3dae --- /dev/null +++ b/inventory/my-cluster/host_vars/dawarich @@ -0,0 +1,6 @@ +--- + +ansible_user: root +ansible_host: 10.0.2.48 +ansible_ssh_pass: "{{ proxmox_api_password }}" +vmid: 648 diff --git a/inventory/my-cluster/host_vars/ghost b/inventory/my-cluster/host_vars/ghost new file mode 100644 index 0000000..060b7a5 --- /dev/null +++ b/inventory/my-cluster/host_vars/ghost @@ -0,0 +1,6 @@ +--- + +ansible_user: root +ansible_host: 10.0.2.47 +ansible_ssh_pass: "{{ proxmox_api_password }}" +vmid: 647 diff --git a/inventory/my-cluster/host_vars/yunobo b/inventory/my-cluster/host_vars/yunobo new file mode 100644 index 0000000..7c7feaa --- /dev/null +++ b/inventory/my-cluster/host_vars/yunobo @@ -0,0 +1,10 @@ +--- + +ansible_user: root +ansible_host: 10.0.3.3 +ansible_ssh_pass: "{{ proxmox_api_password }}" +ip_addr: 10.0.3.3 + +# interface which will be used for flannel + +flannel_iface: "vmbr0" diff --git a/inventory/my-cluster/hosts.ini b/inventory/my-cluster/hosts.ini index f748cd4..8b27e83 100644 --- a/inventory/my-cluster/hosts.ini +++ b/inventory/my-cluster/hosts.ini @@ -27,14 +27,18 @@ convertx nocodb super-productivity droposs +ghost +dawarich [baremetal] mipha purah -revali +; revali yuga -impa +; impa sidon +yunobo + [pihole] epona-pihole diff --git a/playbook-47-ghost.yml b/playbook-47-ghost.yml new file mode 100644 index 0000000..86494cf --- /dev/null +++ b/playbook-47-ghost.yml @@ -0,0 +1,27 @@ +--- +- hosts: localhost + become: yes + roles: + - role: 47-ghost/provision/delete + vars: + vmid: 647 + - role: 47-ghost/provision/create + vars: + vmid: 647 + - role: 47-ghost/provision/start + vars: + vmid: 647 + +- hosts: purah + become: yes + roles: + - role: 47-ghost/enable-ssh + vars: + vmid: 647 + +- hosts: ghost + become: yes + roles: + - role: 47-ghost/update + - role: 47-ghost/install-docker + - role: 47-ghost/install-app diff --git a/playbook-48-dawarich.yml b/playbook-48-dawarich.yml new file mode 100644 index 0000000..0df099a --- /dev/null +++ b/playbook-48-dawarich.yml @@ -0,0 +1,27 @@ +--- +# - hosts: localhost +# become: yes +# roles: +# - role: 48-dawarich/provision/delete +# vars: +# vmid: 648 +# - role: 48-dawarich/provision/create +# vars: +# vmid: 648 +# - role: 48-dawarich/provision/start +# vars: +# vmid: 648 + +# - hosts: yunobo +# become: yes +# roles: +# - role: 48-dawarich/enable-ssh +# vars: +# vmid: 648 + +- hosts: dawarich + become: yes + roles: + - role: 48-dawarich/update + - role: 48-dawarich/install-docker + - role: 48-dawarich/install-app diff --git a/roles/47-ghost-wip/enable-ssh/tasks/main.yml b/roles/47-ghost-wip/enable-ssh/tasks/main.yml new file mode 100644 index 0000000..fb52b1b --- /dev/null +++ b/roles/47-ghost-wip/enable-ssh/tasks/main.yml @@ -0,0 +1,12 @@ +--- +# Unable to use ansible.builtin.lineinfile, because we need to run this through the proxmox host (because SSH is not enabled duh) + +- name: Pause for 10 seconds to wait for SSH server + ansible.builtin.pause: + seconds: 10 + +- name: Allow SSH into LXC + ansible.builtin.command: lxc-attach -n 647 -- sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config + +- name: Restart SSH Service + ansible.builtin.command: lxc-attach -n 647 service ssh restart diff --git a/roles/47-ghost-wip/install-app/tasks/main.yml b/roles/47-ghost-wip/install-app/tasks/main.yml new file mode 100644 index 0000000..3aa3110 --- /dev/null +++ b/roles/47-ghost-wip/install-app/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: Create directory for docker-compose + ansible.builtin.file: + path: /root/docker/ + state: directory + mode: "0755" + +- name: Copy docker-compose file + template: + src: "docker-compose.yml" + dest: /root/docker/docker-compose.yml + owner: root + group: root + mode: 0755 + +- name: Run docker-compose + ansible.builtin.shell: + args: + cmd: docker compose up -d + chdir: /root/docker/ diff --git a/roles/47-ghost-wip/install-app/templates/.env b/roles/47-ghost-wip/install-app/templates/.env new file mode 100644 index 0000000..21c2c81 --- /dev/null +++ b/roles/47-ghost-wip/install-app/templates/.env @@ -0,0 +1,48 @@ +# Use the below flags to enable the Analytics or ActivityPub containers as well +# COMPOSE_PROFILES=analytics,activitypub + +# Ghost domain +# Custom public domain Ghost will run on +DOMAIN=example.com + +# Ghost Admin domain +# If you have Ghost Admin setup on a separate domain uncomment the line below and add the domain +# You also need to uncomment the corresponding block in your Caddyfile +# ADMIN_DOMAIN= + +# Database settings +# All database settings must not be changed once the database is initialised +DATABASE_ROOT_PASSWORD=reallysecurerootpassword +# DATABASE_USER=optionalusername +DATABASE_PASSWORD=ghostpassword + +# Ghost configuration (https://ghost.org/docs/config/) + +# SMTP Email (https://ghost.org/docs/config/#mail) +# Transactional email is required for logins, account creation (staff invites), password resets and other features +# This is not related to bulk mail / newsletter sending +mail__transport=SMTP +mail__options__host=smtp.example.com +mail__options__port=465 +mail__options__secure=true +mail__options__auth__user=postmaster@example.com +mail__options__auth__pass=1234567890 + +# Advanced customizations + +# Force Ghost version +# You should only do this if you need to pin a specific version +# The update commands won't work +# GHOST_VERSION=6-alpine + +# Port Ghost should listen on +# You should only need to edit this if you want to host +# multiple sites on the same server +# GHOST_PORT=2368 + +# Data locations +# Location to store uploaded data +UPLOAD_LOCATION=./data/ghost + +# Location for database data +MYSQL_DATA_LOCATION=./data/mysql \ No newline at end of file diff --git a/roles/47-ghost-wip/install-app/templates/docker-compose.yml b/roles/47-ghost-wip/install-app/templates/docker-compose.yml new file mode 100644 index 0000000..ee54215 --- /dev/null +++ b/roles/47-ghost-wip/install-app/templates/docker-compose.yml @@ -0,0 +1,64 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/compose-spec/compose-spec/main/schema/compose-spec.json +services: + ghost: + # Do not alter this without updating the Tinybird Sync container as well + image: ghost:${GHOST_VERSION:-6-alpine} + restart: always + expose: + - "127.0.0.1:${GHOST_PORT:-2368}:2368" + # This is required to import current config when migrating + env_file: + - .env + environment: + NODE_ENV: production + url: https://${DOMAIN:?DOMAIN environment variable is required} + admin__url: ${ADMIN_DOMAIN:+https://${ADMIN_DOMAIN}} + database__client: mysql + database__connection__host: db + database__connection__user: ${DATABASE_USER:-ghost} + database__connection__password: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required} + database__connection__database: ghost + tinybird__tracker__endpoint: https://${DOMAIN:?DOMAIN environment variable is required}/.ghost/analytics/api/v1/page_hit + tinybird__adminToken: ${TINYBIRD_ADMIN_TOKEN:-} + tinybird__workspaceId: ${TINYBIRD_WORKSPACE_ID:-} + tinybird__tracker__datasource: analytics_events + tinybird__stats__endpoint: ${TINYBIRD_API_URL:-https://api.tinybird.co} + volumes: + - ${UPLOAD_LOCATION:-./data/ghost}:/var/lib/ghost/content + depends_on: + db: + condition: service_healthy + tinybird-sync: + condition: service_completed_successfully + required: false + tinybird-deploy: + condition: service_completed_successfully + required: false + activitypub: + condition: service_started + required: false + + db: + image: mysql:8.0.42@sha256:4445b2668d41143cb50e471ee207f8822006249b6859b24f7e12479684def5d9 + restart: always + expose: + - "3306" + environment: + MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD:?DATABASE_ROOT_PASSWORD environment variable is required} + MYSQL_USER: ${DATABASE_USER:-ghost} + MYSQL_PASSWORD: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required} + MYSQL_DATABASE: ghost + MYSQL_MULTIPLE_DATABASES: activitypub + volumes: + - ${MYSQL_DATA_LOCATION:-./data/mysql}:/var/lib/mysql + - ./mysql-init:/docker-entrypoint-initdb.d + healthcheck: + test: mysqladmin ping -p$$MYSQL_ROOT_PASSWORD -h 127.0.0.1 + interval: 1s + start_period: 30s + start_interval: 10s + retries: 120 + env_file: + - .env + diff --git a/roles/47-ghost-wip/install-docker/tasks/main.yml b/roles/47-ghost-wip/install-docker/tasks/main.yml new file mode 100644 index 0000000..d5baba9 --- /dev/null +++ b/roles/47-ghost-wip/install-docker/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Get convenience script + uri: + url: "https://get.docker.com" + method: GET + dest: /tmp/get-docker.sh + mode: a+x + creates: /tmp/get-docker.sh + +- name: Execute script + ansible.builtin.shell: /tmp/get-docker.sh + +- name: Ensure group "docker" exists + ansible.builtin.group: + name: docker + state: present + +- name: Add root user to docker group + ansible.builtin.user: + name: root + groups: docker + append: yes + +- name: Enable docker on startup + ansible.builtin.shell: | + systemctl enable docker.service + systemctl enable containerd.service diff --git a/roles/47-ghost-wip/provision/create/tasks/main.yml b/roles/47-ghost-wip/provision/create/tasks/main.yml new file mode 100644 index 0000000..84f0be0 --- /dev/null +++ b/roles/47-ghost-wip/provision/create/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Create container + community.general.proxmox: + vmid: 647 + node: purah + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + password: "{{ lxc_password }}" + hostname: ghost + ostemplate: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst" + netif: "{'net0':'name=eth0,\ + gw=10.0.0.1,\ + ip=10.0.2.47/21,\ + hwaddr=cc:c6:cf:de:20:47,\ + bridge=vmbr0'}" + cores: 2 + memory: 4196 + unprivileged: no + swap: 0 + searchdomain: "home" + onboot: 1 + features: + - nesting=1 + - keyctl=1 + disk: purah-mirror-860gb:20 + mounts: '{ + "mp0":"purah-mirror-860gb:10,mp=/data,backup=1" + }' + force: yes diff --git a/roles/47-ghost-wip/provision/delete/tasks/main.yml b/roles/47-ghost-wip/provision/delete/tasks/main.yml new file mode 100644 index 0000000..19914ee --- /dev/null +++ b/roles/47-ghost-wip/provision/delete/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Stop container + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: stopped + ignore_errors: true + timeout: 90 + +- name: Remove containers + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: absent + ignore_errors: true + timeout: 90 + +- name: Remove .ssh/known_hosts lines + ansible.builtin.lineinfile: + path: /Users/lino.silva/.ssh/known_hosts + state: absent + regexp: "^10.0.2.47" + diff --git a/roles/47-ghost-wip/provision/start/tasks/main.yml b/roles/47-ghost-wip/provision/start/tasks/main.yml new file mode 100644 index 0000000..de86b9b --- /dev/null +++ b/roles/47-ghost-wip/provision/start/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: Start deployments + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: started diff --git a/roles/47-ghost-wip/update/tasks/main.yml b/roles/47-ghost-wip/update/tasks/main.yml new file mode 100644 index 0000000..8227bf4 --- /dev/null +++ b/roles/47-ghost-wip/update/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- name: Update all packages to their latest version + become: true + ansible.builtin.apt: + update_cache: yes + upgrade: full diff --git a/roles/48-dawarich/enable-ssh/tasks/main.yml b/roles/48-dawarich/enable-ssh/tasks/main.yml new file mode 100644 index 0000000..8644aef --- /dev/null +++ b/roles/48-dawarich/enable-ssh/tasks/main.yml @@ -0,0 +1,12 @@ +--- +# Unable to use ansible.builtin.lineinfile, because we need to run this through the proxmox host (because SSH is not enabled duh) + +- name: Pause for 10 seconds to wait for SSH server + ansible.builtin.pause: + seconds: 10 + +- name: Allow SSH into LXC + ansible.builtin.command: lxc-attach -n 648 -- sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config + +- name: Restart SSH Service + ansible.builtin.command: lxc-attach -n 648 service ssh restart diff --git a/roles/48-dawarich/install-app/tasks/main.yml b/roles/48-dawarich/install-app/tasks/main.yml new file mode 100644 index 0000000..3aa3110 --- /dev/null +++ b/roles/48-dawarich/install-app/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: Create directory for docker-compose + ansible.builtin.file: + path: /root/docker/ + state: directory + mode: "0755" + +- name: Copy docker-compose file + template: + src: "docker-compose.yml" + dest: /root/docker/docker-compose.yml + owner: root + group: root + mode: 0755 + +- name: Run docker-compose + ansible.builtin.shell: + args: + cmd: docker compose up -d + chdir: /root/docker/ diff --git a/roles/48-dawarich/install-app/templates/docker-compose.yml b/roles/48-dawarich/install-app/templates/docker-compose.yml new file mode 100644 index 0000000..a9bbe2b --- /dev/null +++ b/roles/48-dawarich/install-app/templates/docker-compose.yml @@ -0,0 +1,137 @@ +services: + dawarich_redis: + image: redis:7.4-alpine + container_name: dawarich_redis + command: redis-server + volumes: + - /data/shared:/data + restart: always + healthcheck: + test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ] + interval: 10s + retries: 5 + start_period: 30s + timeout: 10s + dawarich_db: + image: postgis/postgis:17-3.5-alpine + shm_size: 1G + container_name: dawarich_db + volumes: + - /data/db:/var/lib/postgresql/data + - /data/shared:/var/shared + # - ./postgresql.conf:/etc/postgresql/postgresql.conf # Optional, uncomment if you want to use a custom config + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: dawarich_development + restart: always + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U postgres -d dawarich_development" ] + interval: 10s + retries: 5 + start_period: 30s + timeout: 10s + # command: postgres -c config_file=/etc/postgresql/postgresql.conf # Use custom config, uncomment if you want to use a custom config + dawarich_app: + image: freikin/dawarich:latest + container_name: dawarich_app + volumes: + - /data/public:/var/app/public + - /data/watched:/var/app/tmp/imports/watched + - /data/storage:/var/app/storage + - /data/db:/dawarich_db_data + ports: + - 3000:3000 + # - 9394:9394 # Prometheus exporter, uncomment if needed + stdin_open: true + tty: true + entrypoint: web-entrypoint.sh + command: ['bin/rails', 'server', '-p', '3000', '-b', '::'] + restart: on-failure + environment: + RAILS_ENV: development + REDIS_URL: redis://dawarich_redis:6379 + DATABASE_HOST: dawarich_db + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: password + DATABASE_NAME: dawarich_development + MIN_MINUTES_SPENT_IN_CITY: 60 + APPLICATION_HOSTS: localhost + TIME_ZONE: Europe/London + APPLICATION_PROTOCOL: http + PROMETHEUS_EXPORTER_ENABLED: "false" + PROMETHEUS_EXPORTER_HOST: 0.0.0.0 + PROMETHEUS_EXPORTER_PORT: 9394 + SELF_HOSTED: "true" + STORE_GEODATA: "true" + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + healthcheck: + test: [ "CMD-SHELL", "wget -qO - http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"\\s*:\\s*\"ok\"'" ] + interval: 10s + retries: 30 + start_period: 30s + timeout: 10s + depends_on: + dawarich_db: + condition: service_healthy + restart: true + dawarich_redis: + condition: service_healthy + restart: true + deploy: + resources: + limits: + cpus: '0.50' # Limit CPU usage to 50% of one core + memory: '4G' # Limit memory usage to 4GB + dawarich_sidekiq: + image: freikin/dawarich:latest + container_name: dawarich_sidekiq + volumes: + - /data/public:/var/app/public + - /data/watched:/var/app/tmp/imports/watched + - /data/storage:/var/app/storage + stdin_open: true + tty: true + entrypoint: sidekiq-entrypoint.sh + command: ['sidekiq'] + restart: on-failure + environment: + RAILS_ENV: development + REDIS_URL: redis://dawarich_redis:6379 + DATABASE_HOST: dawarich_db + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: password + DATABASE_NAME: dawarich_development + APPLICATION_HOSTS: localhost + BACKGROUND_PROCESSING_CONCURRENCY: 10 + APPLICATION_PROTOCOL: http + PROMETHEUS_EXPORTER_ENABLED: "false" + PROMETHEUS_EXPORTER_HOST: dawarich_app + PROMETHEUS_EXPORTER_PORT: 9394 + SELF_HOSTED: "true" + STORE_GEODATA: "true" + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" + healthcheck: + test: [ "CMD-SHELL", "pgrep -f sidekiq" ] + interval: 10s + retries: 30 + start_period: 30s + timeout: 10s + depends_on: + dawarich_db: + condition: service_healthy + restart: true + dawarich_redis: + condition: service_healthy + restart: true + dawarich_app: + condition: service_healthy + restart: true diff --git a/roles/48-dawarich/install-docker/tasks/main.yml b/roles/48-dawarich/install-docker/tasks/main.yml new file mode 100644 index 0000000..d5baba9 --- /dev/null +++ b/roles/48-dawarich/install-docker/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Get convenience script + uri: + url: "https://get.docker.com" + method: GET + dest: /tmp/get-docker.sh + mode: a+x + creates: /tmp/get-docker.sh + +- name: Execute script + ansible.builtin.shell: /tmp/get-docker.sh + +- name: Ensure group "docker" exists + ansible.builtin.group: + name: docker + state: present + +- name: Add root user to docker group + ansible.builtin.user: + name: root + groups: docker + append: yes + +- name: Enable docker on startup + ansible.builtin.shell: | + systemctl enable docker.service + systemctl enable containerd.service diff --git a/roles/48-dawarich/provision/create/tasks/main.yml b/roles/48-dawarich/provision/create/tasks/main.yml new file mode 100644 index 0000000..99fa342 --- /dev/null +++ b/roles/48-dawarich/provision/create/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Create container + community.general.proxmox: + vmid: 648 + node: yunobo + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + password: "{{ lxc_password }}" + hostname: dawarich + ostemplate: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst" + netif: "{'net0':'name=eth0,\ + gw=10.0.0.1,\ + ip=10.0.2.48/21,\ + hwaddr=cc:c6:cf:de:20:48,\ + bridge=vmbr0'}" + cores: 2 + memory: 4196 + unprivileged: no + swap: 0 + searchdomain: "home" + onboot: 1 + features: + - nesting=1 + - keyctl=1 + disk: nvme-2tb:20 + mounts: '{ + "mp0":"nvme-2tb:10,mp=/data,backup=1" + }' + force: yes diff --git a/roles/48-dawarich/provision/delete/tasks/main.yml b/roles/48-dawarich/provision/delete/tasks/main.yml new file mode 100644 index 0000000..42fb0bf --- /dev/null +++ b/roles/48-dawarich/provision/delete/tasks/main.yml @@ -0,0 +1,27 @@ +--- +- name: Stop container + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: stopped + ignore_errors: true + timeout: 90 + +- name: Remove containers + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: absent + ignore_errors: true + timeout: 90 + +- name: Remove .ssh/known_hosts lines + ansible.builtin.lineinfile: + path: /Users/lino.silva/.ssh/known_hosts + state: absent + regexp: "^10.0.2.48" + diff --git a/roles/48-dawarich/provision/start/tasks/main.yml b/roles/48-dawarich/provision/start/tasks/main.yml new file mode 100644 index 0000000..de86b9b --- /dev/null +++ b/roles/48-dawarich/provision/start/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: Start deployments + community.general.proxmox: + vmid: "{{ vmid }}" + api_user: root@pam + api_password: "{{ proxmox_api_password }}" + api_host: 10.0.2.2 + state: started diff --git a/roles/48-dawarich/update/tasks/main.yml b/roles/48-dawarich/update/tasks/main.yml new file mode 100644 index 0000000..8227bf4 --- /dev/null +++ b/roles/48-dawarich/update/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- name: Update all packages to their latest version + become: true + ansible.builtin.apt: + update_cache: yes + upgrade: full