Secrets VM #21
							
								
								
									
										4
									
								
								.github/workflows/infra.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/infra.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -72,4 +72,8 @@ jobs: | |||||||
|           PROXMOX_TOKEN_ID: ${{ secrets.PROXMOX_TOKEN_ID }} |           PROXMOX_TOKEN_ID: ${{ secrets.PROXMOX_TOKEN_ID }} | ||||||
|           PROXMOX_TOKEN_SECRET: ${{ secrets.PROXMOX_TOKEN_SECRET }} |           PROXMOX_TOKEN_SECRET: ${{ secrets.PROXMOX_TOKEN_SECRET }} | ||||||
|           SSH_PUBLIC: ${{ secrets.SSH_PUBLIC }} |           SSH_PUBLIC: ${{ secrets.SSH_PUBLIC }} | ||||||
|  |           SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }} | ||||||
|  |           INFISICAL_ENCRYPTION_KEY: ${{ secrets.INFISICAL_ENCRYPTION_KEY }} | ||||||
|  |           INFISICAL_AUTH_SECRET: ${{ secrets.INFISICAL_AUTH_SECRET }} | ||||||
|  |           INFISICAL_MONGO_PASSWORD: ${{ secrets.INFISICAL_MONGO_PASSWORD }} | ||||||
|         run: ansible-playbook --inventory ./inventory ${{ steps.playbooks.outputs.to_run }} -vv |         run: ansible-playbook --inventory ./inventory ${{ steps.playbooks.outputs.to_run }} -vv | ||||||
|   | |||||||
							
								
								
									
										110
									
								
								infra/secrets/0000_proxmox_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								infra/secrets/0000_proxmox_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | |||||||
|  | - name: Provision secrets Proxmox VM | ||||||
|  |   hosts: secrets | ||||||
|  |   connection: ansible.builtin.local | ||||||
|  |   gather_facts: false | ||||||
|  |   vars: | ||||||
|  |     api_user: "{{ lookup('ansible.builtin.env', 'PROXMOX_USER') }}" | ||||||
|  |     api_host: "{{ lookup('ansible.builtin.env', 'PROXMOX_HOST' ) }}" | ||||||
|  |     api_token_id: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_ID') }}" | ||||||
|  |     api_token_secret: "{{ lookup('ansible.builtin.env', 'PROXMOX_TOKEN_SECRET') }}" | ||||||
|  |     ssh_public: "{{ lookup('ansible.builtin.env', 'SSH_PUBLIC') }}" | ||||||
|  |     vmname: "{{ inventory_hostname | regex_replace('^([^\\.]+)\\..+$', '\\1') }}" | ||||||
|  |     node: pve | ||||||
|  |   module_defaults: | ||||||
|  |     community.general.proxmox_kvm: | ||||||
|  |       api_user: "{{ api_user }}" | ||||||
|  |       api_host: "{{ api_host }}" | ||||||
|  |       api_token_id: "{{ api_token_id }}" | ||||||
|  |       api_token_secret: "{{ api_token_secret }}" | ||||||
|  |       name: "{{ vmname }}" | ||||||
|  |       node: "{{ node }}" | ||||||
|  |     community.general.proxmox_nic: | ||||||
|  |       api_user: "{{ api_user }}" | ||||||
|  |       api_host: "{{ api_host }}" | ||||||
|  |       api_token_id: "{{ api_token_id }}" | ||||||
|  |       api_token_secret: "{{ api_token_secret }}" | ||||||
|  |       name: "{{ vmname }}" | ||||||
|  |     community.general.proxmox_disk: | ||||||
|  |       api_user: "{{ api_user }}" | ||||||
|  |       api_host: "{{ api_host }}" | ||||||
|  |       api_token_id: "{{ api_token_id }}" | ||||||
|  |       api_token_secret: "{{ api_token_secret }}" | ||||||
|  |       name: "{{ vmname }}" | ||||||
|  |   tasks: | ||||||
|  |     # Initial setup | ||||||
|  |     - name: Create VM | ||||||
|  |       community.general.proxmox_kvm: | ||||||
|  |         clone: "{{ node }}-debian-12" | ||||||
|  |         storage: nvme | ||||||
|  |       register: create | ||||||
|  |     - name: Wait for status | ||||||
|  |       community.general.proxmox_kvm: | ||||||
|  |         state: current | ||||||
|  |       register: vm | ||||||
|  |       retries: 30 | ||||||
|  |       delay: 10 | ||||||
|  |       until: vm.status is defined | ||||||
|  |  | ||||||
|  |     # Networking and initial config | ||||||
|  |     - name: Add PUB NIC | ||||||
|  |       community.general.proxmox_nic: | ||||||
|  |         interface: net0 | ||||||
|  |         firewall: false | ||||||
|  |         bridge: PUB | ||||||
|  |     - name: Add SRV NIC | ||||||
|  |       community.general.proxmox_nic: | ||||||
|  |         interface: net1 | ||||||
|  |         firewall: false | ||||||
|  |         bridge: SRV | ||||||
|  |     - name: Configure cloud-init | ||||||
|  |       community.general.proxmox_kvm: | ||||||
|  |         update: true | ||||||
|  |         ciuser: debian | ||||||
|  |         sshkeys: "{{ ssh_public }}" | ||||||
|  |         ipconfig: | ||||||
|  |           ipconfig0: ip=dhcp,ip6=auto | ||||||
|  |           ipconfig1: ip=dhcp | ||||||
|  |  | ||||||
|  |     # Initial boot | ||||||
|  |     # For some reason debian cloud images don't use | ||||||
|  |     # cloud-init for networking on first boot (cloud-init files | ||||||
|  |     # are regenerated AFTER networking starts). But we need the | ||||||
|  |     # hostname to be registered with DHCP later on so ¯\_(ツ)_/¯ | ||||||
|  |     - name: Initial boot | ||||||
|  |       when: create.changed is true | ||||||
|  |       block: | ||||||
|  |         - name: Start | ||||||
|  |           community.general.proxmox_kvm: | ||||||
|  |             state: started | ||||||
|  |           register: start | ||||||
|  |         - name: Wait 1.5 min # Initial apt update, apt upgrade, cloud-init | ||||||
|  |           ansible.builtin.wait_for: | ||||||
|  |             timeout: 90 | ||||||
|  |  | ||||||
|  |     # VM Configuration | ||||||
|  |     - name: Resize root disk | ||||||
|  |       community.general.proxmox_disk: | ||||||
|  |         disk: scsi0 | ||||||
|  |         size: 16G | ||||||
|  |         state: resized | ||||||
|  |     - name: Create data disk | ||||||
|  |       community.general.proxmox_disk: | ||||||
|  |         disk: scsi1 | ||||||
|  |         backup: true | ||||||
|  |         storage: nvme | ||||||
|  |         size: 64 | ||||||
|  |     - name: Update VM | ||||||
|  |       community.general.proxmox_kvm: | ||||||
|  |         update: true | ||||||
|  |         agent: enabled=1 | ||||||
|  |         tags: | ||||||
|  |           - debian-12 | ||||||
|  |           - managed | ||||||
|  |         onboot: true | ||||||
|  |         cores: 4 | ||||||
|  |         memory: 4096 | ||||||
|  |  | ||||||
|  |     - name: Retart VM | ||||||
|  |       community.general.proxmox_kvm: | ||||||
|  |         state: restarted | ||||||
|  |         timeout: 60 | ||||||
							
								
								
									
										42
									
								
								infra/secrets/0001_initialise_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								infra/secrets/0001_initialise_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | - name: Initialise VM | ||||||
|  |   hosts: secrets | ||||||
|  |   gather_facts: false | ||||||
|  |   tasks: | ||||||
|  |     - name: Wait for connection | ||||||
|  |       ansible.builtin.wait_for_connection: | ||||||
|  |         timeout: 300 | ||||||
|  |     - name: Install system packages | ||||||
|  |       ansible.builtin.apt: | ||||||
|  |         update_cache: true | ||||||
|  |         pkg: | ||||||
|  |           - qemu-guest-agent | ||||||
|  |           - parted | ||||||
|  |       become: true | ||||||
|  |     - name: Enable qemu-guest-agent | ||||||
|  |       ansible.builtin.systemd: | ||||||
|  |         name: qemu-guest-agent | ||||||
|  |         state: started | ||||||
|  |         enabled: true | ||||||
|  |       become: true | ||||||
|  |  | ||||||
|  |     - name: Create data partition | ||||||
|  |       community.general.parted: | ||||||
|  |         device: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1 | ||||||
|  |         label: gpt | ||||||
|  |         name: data | ||||||
|  |         number: 1 | ||||||
|  |         state: present | ||||||
|  |       become: true | ||||||
|  |     - name: Create data filesystem | ||||||
|  |       community.general.filesystem: | ||||||
|  |         dev: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1 | ||||||
|  |         fstype: ext4 | ||||||
|  |       become: true | ||||||
|  |     - name: Mount data partition | ||||||
|  |       ansible.posix.mount: | ||||||
|  |         src: /dev/disk/by-path/pci-0000:00:05.0-scsi-0:0:0:1-part1 | ||||||
|  |         path: /var/lib/docker | ||||||
|  |         fstype: ext4 | ||||||
|  |         opts: rw,errors=remount-ro,x-systemd.growfs | ||||||
|  |         state: mounted | ||||||
|  |       become: true | ||||||
							
								
								
									
										47
									
								
								infra/secrets/0002_docker_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								infra/secrets/0002_docker_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | - name: Install software | ||||||
|  |   hosts: secrets | ||||||
|  |   gather_facts: false | ||||||
|  |   tasks: | ||||||
|  |     - name: Wait for connection | ||||||
|  |       ansible.builtin.wait_for_connection: | ||||||
|  |         timeout: 300 | ||||||
|  |     - name: Install dependencies | ||||||
|  |       ansible.builtin.apt: | ||||||
|  |         update_cache: true | ||||||
|  |         pkg: | ||||||
|  |           - curl | ||||||
|  |           - python3-apt | ||||||
|  |           - gpg | ||||||
|  |       become: true | ||||||
|  |     - name: Add docker key | ||||||
|  |       ansible.builtin.apt_key: | ||||||
|  |         url: https://download.docker.com/linux/debian/gpg | ||||||
|  |         keyring: /etc/apt/keyrings/docker.gpg | ||||||
|  |       become: true | ||||||
|  |     - name: Add docker repo | ||||||
|  |       ansible.builtin.apt_repository: | ||||||
|  |         repo: deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable | ||||||
|  |       become: true | ||||||
|  |     - name: Install docker | ||||||
|  |       ansible.builtin.apt: | ||||||
|  |         update_cache: true | ||||||
|  |         pkg: | ||||||
|  |           - docker-ce | ||||||
|  |           - docker-ce-cli | ||||||
|  |           - containerd.io | ||||||
|  |           - docker-buildx-plugin | ||||||
|  |           - docker-compose-plugin | ||||||
|  |       become: true | ||||||
|  |     - name: Add user to docker group | ||||||
|  |       ansible.builtin.user: | ||||||
|  |         user: debian | ||||||
|  |         groups: | ||||||
|  |           - docker | ||||||
|  |         append: true | ||||||
|  |       become: true | ||||||
|  |     - name: Enable docker | ||||||
|  |       ansible.builtin.systemd: | ||||||
|  |         name: docker | ||||||
|  |         state: started | ||||||
|  |         enabled: true | ||||||
|  |       become: true | ||||||
							
								
								
									
										47
									
								
								infra/secrets/0003_infiscal_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								infra/secrets/0003_infiscal_playbook.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | - name: Deploy app | ||||||
|  |   hosts: secrets | ||||||
|  |   gather_facts: false | ||||||
|  |   vars: | ||||||
|  |     app: infisical | ||||||
|  |   tasks: | ||||||
|  |     - name: Wait for connection | ||||||
|  |       ansible.builtin.wait_for_connection: | ||||||
|  |         timeout: 300 | ||||||
|  |     - name: Get user | ||||||
|  |       ansible.builtin.user: | ||||||
|  |         name: debian | ||||||
|  |       register: user | ||||||
|  |     - name: Docker compose down | ||||||
|  |       ansible.builtin.command: docker compose down | ||||||
|  |       args: | ||||||
|  |         chdir: "{{ user.home }}/{{ app }}" | ||||||
|  |       ignore_errors: true | ||||||
|  |     - name: Copy project | ||||||
|  |       ansible.builtin.copy: | ||||||
|  |         src: "./{{ app }}" | ||||||
|  |         dest: "{{ user.home }}" | ||||||
|  |         mode: "0744" | ||||||
|  |     - name: Replace Encryption Key secret | ||||||
|  |       ansible.builtin.replace: | ||||||
|  |         path: "{{ user.home }}/{{ app }}/.env" | ||||||
|  |         regexp: "ENCRYPTION_KEY_VALUE" | ||||||
|  |         replace: "{{ lookup('ansible.builtin.env', 'INFISICAL_ENCRYPTION_KEY') }}" | ||||||
|  |     - name: Replace Auth secret | ||||||
|  |       ansible.builtin.replace: | ||||||
|  |         path: "{{ user.home }}/{{ app }}/.env" | ||||||
|  |         regexp: "AUTH_SECRET_VALUE" | ||||||
|  |         replace: "{{ lookup('ansible.builtin.env', 'INFISICAL_AUTH_SECRET') }}" | ||||||
|  |     - name: Replace Mongo Password secret | ||||||
|  |       ansible.builtin.replace: | ||||||
|  |         path: "{{ user.home }}/{{ app }}/.env" | ||||||
|  |         regexp: "MONGO_PASSWORD_VALUE" | ||||||
|  |         replace: "{{ lookup('ansible.builtin.env', 'INFISICAL_MONGO_PASSWORD') }}" | ||||||
|  |     - name: Replace SMTP Password secret | ||||||
|  |       ansible.builtin.replace: | ||||||
|  |         path: "{{ user.home }}/{{ app }}/.env" | ||||||
|  |         regexp: "SMTP_PASSWORD_VALUE" | ||||||
|  |         replace: "{{ lookup('ansible.builtin.env', 'SMTP_PASSWORD') }}" | ||||||
|  |     - name: Docker compose up -d | ||||||
|  |       ansible.builtin.command: docker compose up -d | ||||||
|  |       args: | ||||||
|  |         chdir: "{{ user.home }}/{{ app }}" | ||||||
							
								
								
									
										68
									
								
								infra/secrets/infisical/.env
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								infra/secrets/infisical/.env
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | # Keys | ||||||
|  | # Required key for platform encryption/decryption ops | ||||||
|  | # THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NEVER BE USED FOR PRODUCTION | ||||||
|  | ENCRYPTION_KEY=ENCRYPTION_KEY_VALUE | ||||||
|  |  | ||||||
|  | # JWT | ||||||
|  | # Required secrets to sign JWT tokens | ||||||
|  | # THIS IS A SAMPLE AUTH_SECRET KEY AND SHOULD NEVER BE USED FOR PRODUCTION | ||||||
|  | AUTH_SECRET=AUTH_SECRET_VALUE | ||||||
|  |  | ||||||
|  | # MongoDB | ||||||
|  | # Backend will connect to the MongoDB instance at connection string MONGO_URL which can either be a ref | ||||||
|  | # to the MongoDB container instance or Mongo Cloud | ||||||
|  | # Required | ||||||
|  | MONGO_URL=mongodb://root:MONGO_PASSWORD_VALUE@mongo:27017/?authSource=admin | ||||||
|  |  | ||||||
|  | # Redis | ||||||
|  | REDIS_URL=redis://redis:6379 | ||||||
|  |  | ||||||
|  | # Optional credentials for MongoDB container instance and Mongo-Express | ||||||
|  | MONGO_USERNAME=root | ||||||
|  | MONGO_PASSWORD=MONGO_PASSWORD_VALUE | ||||||
|  |  | ||||||
|  | # Website URL | ||||||
|  | # Required | ||||||
|  | SITE_URL=https://secrets.koval.net | ||||||
|  |  | ||||||
|  | # Mail/SMTP  | ||||||
|  | SMTP_HOST=mx.koval.net | ||||||
|  | SMTP_PORT=465 | ||||||
|  | SMTP_SECURE=true | ||||||
|  | SMTP_USERNAME=no-reply@koval.net | ||||||
|  | SMTP_PASSWORD=SMTP_PASSWORD_VALUE | ||||||
|  | SMTP_FROM_NAME=KovalHome Infisical | ||||||
|  |  | ||||||
|  | # Integration | ||||||
|  | # Optional only if integration is used | ||||||
|  | CLIENT_ID_HEROKU= | ||||||
|  | CLIENT_ID_VERCEL= | ||||||
|  | CLIENT_ID_NETLIFY= | ||||||
|  | CLIENT_ID_GITHUB= | ||||||
|  | CLIENT_ID_GITLAB= | ||||||
|  | CLIENT_ID_BITBUCKET= | ||||||
|  | CLIENT_SECRET_HEROKU= | ||||||
|  | CLIENT_SECRET_VERCEL= | ||||||
|  | CLIENT_SECRET_NETLIFY= | ||||||
|  | CLIENT_SECRET_GITHUB= | ||||||
|  | CLIENT_SECRET_GITLAB= | ||||||
|  | CLIENT_SECRET_BITBUCKET= | ||||||
|  | CLIENT_SLUG_VERCEL= | ||||||
|  |  | ||||||
|  | # Sentry (optional) for monitoring errors | ||||||
|  | SENTRY_DSN= | ||||||
|  |  | ||||||
|  | # Infisical Cloud-specific configs | ||||||
|  | # Ignore - Not applicable for self-hosted version | ||||||
|  | POSTHOG_HOST= | ||||||
|  | POSTHOG_PROJECT_API_KEY= | ||||||
|  |  | ||||||
|  | # SSO-specific variables | ||||||
|  | CLIENT_ID_GOOGLE_LOGIN= | ||||||
|  | CLIENT_SECRET_GOOGLE_LOGIN= | ||||||
|  |  | ||||||
|  | CLIENT_ID_GITHUB_LOGIN= | ||||||
|  | CLIENT_SECRET_GITHUB_LOGIN= | ||||||
|  |  | ||||||
|  | CLIENT_ID_GITLAB_LOGIN= | ||||||
|  | CLIENT_SECRET_GITLAB_LOGIN= | ||||||
							
								
								
									
										1
									
								
								infra/secrets/infisical/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								infra/secrets/infisical/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | !.env | ||||||
							
								
								
									
										33
									
								
								infra/secrets/infisical/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								infra/secrets/infisical/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | version: "3" | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   backend: | ||||||
|  |     restart: unless-stopped | ||||||
|  |     depends_on: | ||||||
|  |       - mongo | ||||||
|  |     image: infisical/infisical:latest | ||||||
|  |     env_file: .env | ||||||
|  |     ports: | ||||||
|  |       - 80:8080 | ||||||
|  |     environment: | ||||||
|  |       - NODE_ENV=production | ||||||
|  |  | ||||||
|  |   redis: | ||||||
|  |     image: redis | ||||||
|  |     env_file: .env | ||||||
|  |     environment: | ||||||
|  |       - ALLOW_EMPTY_PASSWORD=yes | ||||||
|  |     ports: | ||||||
|  |       - 6379:6379 | ||||||
|  |     volumes: | ||||||
|  |       - /mnt/nvme/redis-data:/data | ||||||
|  |  | ||||||
|  |   mongo: | ||||||
|  |     image: mongo | ||||||
|  |     restart: always | ||||||
|  |     env_file: .env | ||||||
|  |     environment: | ||||||
|  |       - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME} | ||||||
|  |       - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} | ||||||
|  |     volumes: | ||||||
|  |       - /mnt/nvme/mongo-data:/data/db | ||||||
| @@ -14,6 +14,9 @@ proxmox: | |||||||
|             photos: |             photos: | ||||||
|               hosts: |               hosts: | ||||||
|                 photos.srv.home.local.koval.net: |                 photos.srv.home.local.koval.net: | ||||||
|  |             secrets: | ||||||
|  |               hosts: | ||||||
|  |                 secrets.srv.home.local.koval.net: | ||||||
|           vars: |           vars: | ||||||
|             ansible_user: debian |             ansible_user: debian | ||||||
|             ansible_ssh_private_key_file: ~/.ssh/id_rsa |             ansible_ssh_private_key_file: ~/.ssh/id_rsa | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user