From e68335e159146feb00fefa2512da2deea02af552 Mon Sep 17 00:00:00 2001 From: RaymondVerhoef Date: Sun, 17 May 2026 10:00:14 +0200 Subject: [PATCH] feat: implement automated Ansible deployment workflows and secure Anthropic API key management via reverse proxy injection --- .github/workflows/deploy-dev.yml | 1 + .github/workflows/deploy-prod.yml | 1 + Caddyfile | 1 + docker-compose.yml | 2 +- infra/development/site/compose.yml | 2 ++ infra/development/site/deploy-playbook.yml | 7 +++++++ infra/production/site/compose.yml | 2 ++ infra/production/site/deploy-playbook.yml | 7 +++++++ src/lib/api.js | 6 +----- 9 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 1d6bd7b..ebb85f5 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -27,4 +27,5 @@ jobs: ansible-playbook \ -i infra/development/hosts.ini \ -e "ansible_ssh_private_key_file=~/.ssh/deploy_key" \ + -e "anthropic_api_key=${{ secrets.ANTHROPIC_API_KEY }}" \ infra/development/site/deploy-playbook.yml diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index a697367..df0e00e 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -29,4 +29,5 @@ jobs: ansible-playbook \ -i infra/production/hosts.ini \ -e "ansible_ssh_private_key_file=~/.ssh/deploy_key" \ + -e "anthropic_api_key=${{ secrets.ANTHROPIC_API_KEY }}" \ infra/production/site/deploy-playbook.yml diff --git a/Caddyfile b/Caddyfile index 08f432e..d202cd6 100644 --- a/Caddyfile +++ b/Caddyfile @@ -14,6 +14,7 @@ uri strip_prefix /api/anthropic reverse_proxy https://api.anthropic.com { header_up Host api.anthropic.com + header_up x-api-key "{$ANTHROPIC_API_KEY}" } } diff --git a/docker-compose.yml b/docker-compose.yml index fc367e9..3e6b511 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ services: frontend: build: . restart: unless-stopped - ports: + environment:\n - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}\n ports: - "8080:80" pocketbase-learning: diff --git a/infra/development/site/compose.yml b/infra/development/site/compose.yml index c92ee6e..874599c 100644 --- a/infra/development/site/compose.yml +++ b/infra/development/site/compose.yml @@ -9,6 +9,8 @@ services: image: git.labs.respellion.tech/respellion/learning-platform/learning-platform:latest container_name: learning-platform restart: unless-stopped + environment: + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} networks: - learning-platform diff --git a/infra/development/site/deploy-playbook.yml b/infra/development/site/deploy-playbook.yml index 64dc737..b98dbe6 100644 --- a/infra/development/site/deploy-playbook.yml +++ b/infra/development/site/deploy-playbook.yml @@ -36,6 +36,13 @@ src: compose.yml dest: "{{ dest_dir }}/compose.yml" + - name: Create .env file for secrets + ansible.builtin.copy: + dest: "{{ dest_dir }}/.env" + content: | + ANTHROPIC_API_KEY={{ anthropic_api_key | default('') }} + mode: '0600' + - name: Pull latest image community.docker.docker_compose_v2: project_src: "{{ dest_dir }}" diff --git a/infra/production/site/compose.yml b/infra/production/site/compose.yml index dce027c..f52764d 100644 --- a/infra/production/site/compose.yml +++ b/infra/production/site/compose.yml @@ -12,6 +12,8 @@ services: image: git.labs.respellion.tech/respellion/learning-platform/learning-platform:latest container_name: learning-platform restart: unless-stopped + environment: + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} networks: - learning-platform diff --git a/infra/production/site/deploy-playbook.yml b/infra/production/site/deploy-playbook.yml index 64dc737..b98dbe6 100644 --- a/infra/production/site/deploy-playbook.yml +++ b/infra/production/site/deploy-playbook.yml @@ -36,6 +36,13 @@ src: compose.yml dest: "{{ dest_dir }}/compose.yml" + - name: Create .env file for secrets + ansible.builtin.copy: + dest: "{{ dest_dir }}/.env" + content: | + ANTHROPIC_API_KEY={{ anthropic_api_key | default('') }} + mode: '0600' + - name: Pull latest image community.docker.docker_compose_v2: project_src: "{{ dest_dir }}" diff --git a/src/lib/api.js b/src/lib/api.js index 0d244c6..9a4f1cd 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -16,10 +16,7 @@ export const anthropicApi = { return await simulateResponse(); } - const apiKey = storage.get('admin:anthropic_key') || import.meta.env.VITE_ANTHROPIC_API_KEY; - if (!apiKey) { - throw new Error('No Anthropic API key found. Please configure it in Admin -> Settings.'); - } + // The API key is now securely injected by the Caddy reverse proxy via environment variables. // Model is configurable from Admin > Settings, defaults to the original spec model const model = storage.get('admin:model') || DEFAULT_MODEL; @@ -32,7 +29,6 @@ export const anthropicApi = { method: 'POST', headers: { 'Content-Type': 'application/json', - 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'anthropic-dangerous-direct-browser-access': 'true' },