Skip to content

Commit 045935f

Browse files
committed
feat: transition from Dokku to Compose-first architecture and enhance deployment configurations
- Updated the CLI to support a Compose-first approach, including modifications to the deployment process and environment variable management. - Removed Dokku-specific configurations and templates, streamlining the setup for Docker Compose. - Enhanced the Ansible playbook to ensure proper environment variable handling and security measures, including SSH access restrictions and Fail2ban integration. - Updated README and documentation to reflect the new deployment strategy and configuration requirements for the Hetzner cloud environment. - Improved Docker Compose configurations for internal services, ensuring better isolation and security.
1 parent 5c5fb62 commit 045935f

File tree

13 files changed

+741
-1171
lines changed

13 files changed

+741
-1171
lines changed

cli/index.ts

Lines changed: 463 additions & 686 deletions
Large diffs are not rendered by default.

infra/ansible/group_vars/constructa/vars.example.yml

Lines changed: 56 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,88 @@
1-
# Copy this file to infra/ansible/group_vars/constructa/vars.yml and
2-
# fill in values before running the playbook. Keep the populated
3-
# file out of version control.
1+
# Copy this file to infra/ansible/group_vars/constructa/vars.yml and **encrypt it with Ansible Vault**:
2+
# ansible-vault encrypt infra/ansible/group_vars/constructa/vars.yml
3+
#
4+
# Manage it via the CLI:
5+
# pnpm run ex0 -- vault edit
6+
#
7+
# The playbook will render /opt/constructa/.env from this map.
48

5-
# Set to true only on the very first run when no app image exists yet.
6-
# After the first Dokku deploy (which builds dokku/constructa:latest), set back to false.
7-
constructa_enable_registry_login: false
8-
9-
constructa_app_name: constructa
10-
constructa_domain: app.example.com
11-
# Optional list of domains that should 301 redirect to constructa_domain.
12-
# Example: ['www.app.example.com']
13-
constructa_redirect_domains: []
149
constructa_deploy_dir: /opt/constructa
1510

11+
# Sudo password for the deploy user (store encrypted via Vault)
12+
constructa_deploy_sudo_passwort: 'change-me-deploy-password'
13+
14+
# Make Ansible escalate with the password above
15+
ansible_become: true
16+
ansible_become_method: sudo
17+
ansible_become_password: "{{ constructa_deploy_sudo_passwort }}"
18+
19+
# Optional: login to image registry before pulling
1620
constructa_enable_registry_login: false
1721
constructa_registry_server: ghcr.io
1822
constructa_registry_username: 'your-ghcr-username'
1923
constructa_registry_password: 'ghp_...'
2024

21-
constructa_redirect_plugin_repo: 'https://github.com/dokku/dokku-redirect.git'
22-
constructa_redirect_plugin_version: '0.9.1'
23-
# lets encrypt
24-
constructa_letsencrypt_plugin_repo: 'https://github.com/dokku/dokku-letsencrypt.git'
25-
constructa_letsencrypt_plugin_version: '0.22.0'
26-
constructa_letsencrypt_email: ''
25+
# Optional Docker GC
26+
constructa_enable_docker_gc: false
27+
constructa_docker_gc_schedule: weekly
28+
constructa_docker_gc_prune_age: 720h
2729

30+
# Optional swap on small VPS
31+
constructa_swap_file: /swapfile
32+
constructa_swap_size: 2G
2833

29-
# Values rendered into /opt/constructa/.env for the compose stack.
30-
# Strings are quoted to preserve literal values.
31-
constructa_compose_env:
32-
# For "Dokku-first": set after the first dokku deploy:
33-
# APP_IMAGE="dokku/constructa" APP_TAG="latest"
34-
# For registry pull (e.g., GHCR):
35-
# APP_IMAGE="ghcr.io/your-org/your-repo/app" APP_TAG="sha-or-tag"
34+
# Application environment (rendered into .env). Example values shown; replace with real ones.
35+
# TIP: Keep this file Vault-encrypted.
36+
constructa_env:
37+
# Image + tag used by compose
3638
APP_IMAGE: 'ghcr.io/your-org/your-repo/app'
3739
APP_TAG: 'latest'
3840

39-
# Compose exposes services to the host on this address. Dokku apps reach
40-
# them through host.docker.internal, so we keep them bound to 127.0.0.1 on the VPS.
41-
HOST_BIND_ADDR: '127.0.0.1'
41+
# Domain + certificates (Caddy)
4242
APP_HOSTNAME: 'app.example.com'
4343
ACME_EMAIL: 'admin@example.com'
4444

45-
POSTGRES_USER: 'ex0'
46-
POSTGRES_PASSWORD: 'change-me'
45+
# Postgres (internal)
46+
POSTGRES_USER: 'user'
47+
POSTGRES_PASSWORD: 'password'
4748
POSTGRES_DB: 'ex0'
48-
BETTER_AUTH_SECRET: 'please-change-me'
49-
BETTER_AUTH_URL: 'https://app.example.com'
50-
OPENAI_API_KEY: 'sk-...'
49+
DATABASE_URL: 'postgresql://user:password@db:5432/ex0'
50+
51+
# MinIO/S3
5152
MINIO_ROOT_USER: 'minioadmin'
5253
MINIO_ROOT_PASSWORD: 'minioadmin'
5354
MINIO_BUCKET: 'constructa-files'
54-
REDIS_PASSWORD: 'change-me-redis-password'
55-
REDIS_URL: 'redis://:change-me-redis-password@127.0.0.1:6379'
56-
MEILI_MASTER_KEY: 'changeme-master-key'
57-
MEILI_HOST: 'http://127.0.0.1:7700'
58-
MEILI_API_KEY: 'changeme-master-key'
59-
S3_ENDPOINT: 'http://127.0.0.1:9000'
6055
S3_REGION: 'us-east-1'
61-
S3_ACCESS_KEY_ID: 'minioadmin'
62-
S3_SECRET_ACCESS_KEY: 'minioadmin'
63-
S3_BUCKET: 'constructa-files'
56+
S3_ACCESS_KEY_ID: '${MINIO_ROOT_USER}'
57+
S3_SECRET_ACCESS_KEY: '${MINIO_ROOT_PASSWORD}'
58+
S3_BUCKET: '${MINIO_BUCKET}'
6459
S3_ENABLE_PATH_STYLE: '1'
6560
S3_PREVIEW_URL_EXPIRE_IN: '7200'
66-
SEARCH_REINDEX_ON_BOOT: 'false'
61+
62+
# Redis / BullMQ
63+
REDIS_PASSWORD: 'change-me-redis-password'
64+
REDIS_URL: 'redis://:${REDIS_PASSWORD}@redis:6379'
6765
BULLMQ_PREFIX: 'constructa'
6866
DAILY_CREDIT_REFILL_CRON: '0 3 * * *'
6967
JOB_DAILY_CREDIT_REFILL_URL: 'http://app:3000/api/jobs/daily-credit-refill'
70-
JOBS_SECRET: 'change-me'
71-
ENABLE_EMAIL_VERIFICATION: 'true'
72-
VITE_ENABLE_EMAIL_VERIFICATION: 'true'
73-
VITE_ENTERPRISE_DEMO_URL: 'https://calendly.com/your-team/demo'
74-
VITE_POLAR_PRODUCT_PRO_MONTHLY: ''
75-
VITE_POLAR_PRODUCT_BUSINESS_MONTHLY: ''
76-
VITE_POLAR_PRODUCT_CREDITS_50: ''
77-
VITE_POLAR_PRODUCT_CREDITS_100: ''
78-
VITE_BASE_URL: 'https://app.example.com'
79-
PUBLIC_URL: 'https://app.example.com'
80-
CHECKOUT_SUCCESS_URL: 'https://app.example.com/dashboard/billing/success'
81-
CHECKOUT_CANCEL_URL: 'https://app.example.com/dashboard/billing'
82-
EMAIL_PROVIDER: 'smtp'
83-
EMAIL_FROM: 'noreply@example.org'
84-
SMTP_HOST: 'smtp.example.net'
85-
SMTP_PORT: '587'
86-
SMTP_SECURE: 'false'
87-
SMTP_USER: 'apikey'
88-
SMTP_PASS: 'change-me-sendgrid-api-key'
89-
POLAR_SERVER: 'production' # or 'sandbox'
90-
POLAR_ACCESS_TOKEN: ''
91-
POLAR_WEBHOOK_SECRET: ''
92-
POLAR_ORGANIZATION_ID: ''
93-
POLAR_PRODUCT_PRO_MONTHLY: ''
94-
POLAR_PRODUCT_BUSINESS_MONTHLY: ''
95-
POLAR_PRODUCT_CREDITS_50: ''
96-
POLAR_PRODUCT_CREDITS_100: ''
97-
DATABASE_URL: 'postgresql://ex0:change-me@127.0.0.1:5432/ex0'
68+
JOBS_SECRET: ''
9869

99-
constructa_enable_docker_gc: false
100-
constructa_docker_gc_schedule: weekly # or 'daily', or a full OnCalendar expr
101-
constructa_docker_gc_prune_age: 720h # only prune artifacts unused for this long
102-
constructa_docker_allowed_cidr: '172.17.0.0/16'
103-
constructa_run_compose_migrate: false
104-
constructa_swap_file: /swapfile
105-
constructa_swap_size: 2G
106-
107-
# Dokku config key/values that point the app at the loopback services.
108-
# DATABASE_URL should match constructa_compose_env but use host.docker.internal.
109-
constructa_dokku_config:
110-
NODE_ENV: production
111-
PORT: '5000'
112-
DOKKU_PROXY_PORT_MAP: 'http:80:5000 https:443:5000'
113-
DATABASE_URL: 'postgresql://ex0:change-me@host.docker.internal:5432/ex0'
114-
S3_ENDPOINT: 'http://host.docker.internal:9000'
115-
S3_REGION: 'us-east-1'
116-
S3_ACCESS_KEY_ID: 'minioadmin'
117-
S3_SECRET_ACCESS_KEY: 'minioadmin'
118-
S3_BUCKET: 'constructa-files'
119-
S3_ENABLE_PATH_STYLE: '1'
120-
S3_PREVIEW_URL_EXPIRE_IN: '7200'
121-
MEILI_HOST: 'http://host.docker.internal:7700'
122-
MEILI_API_KEY: 'changeme-master-key'
123-
REDIS_URL: 'redis://:change-me-redis-password@host.docker.internal:6379'
70+
# Search (Meilisearch)
71+
MEILI_MASTER_KEY: 'changeme-master-key'
72+
MEILI_HOST: 'http://meilisearch:7700'
73+
MEILI_API_KEY: '${MEILI_MASTER_KEY}'
12474
SEARCH_REINDEX_ON_BOOT: 'false'
125-
BULLMQ_PREFIX: 'constructa'
126-
DAILY_CREDIT_REFILL_CRON: '0 3 * * *'
127-
JOB_DAILY_CREDIT_REFILL_URL: 'http://app:3000/api/jobs/daily-credit-refill'
128-
JOBS_SECRET: 'change-me'
129-
ENABLE_EMAIL_VERIFICATION: 'true'
130-
VITE_ENABLE_EMAIL_VERIFICATION: 'true'
131-
VITE_ENTERPRISE_DEMO_URL: 'https://calendly.com/your-team/demo'
132-
VITE_POLAR_PRODUCT_PRO_MONTHLY: ''
133-
VITE_POLAR_PRODUCT_BUSINESS_MONTHLY: ''
134-
VITE_POLAR_PRODUCT_CREDITS_50: ''
135-
VITE_POLAR_PRODUCT_CREDITS_100: ''
136-
VITE_BASE_URL: 'https://app.example.com'
137-
BETTER_AUTH_SECRET: 'please-change-me'
138-
BETTER_AUTH_URL: 'https://app.example.com'
139-
OPENAI_API_KEY: 'sk-...'
140-
PUBLIC_URL: 'https://app.example.com'
141-
CHECKOUT_SUCCESS_URL: 'https://app.example.com/dashboard/billing/success'
142-
CHECKOUT_CANCEL_URL: 'https://app.example.com/dashboard/billing'
143-
EMAIL_PROVIDER: 'smtp'
75+
76+
# Auth / Email / Third-parties
77+
BETTER_AUTH_SECRET: 'your-secret-key-here'
78+
BETTER_AUTH_URL: 'https://${APP_HOSTNAME}'
79+
80+
EMAIL_PROVIDER: 'smtp' # "smtp" | "resend" | "console"
14481
EMAIL_FROM: 'noreply@example.org'
145-
SMTP_HOST: 'smtp.sendgrid.net'
146-
SMTP_PORT: '587'
147-
SMTP_SECURE: 'false'
148-
SMTP_USER: 'apikey'
149-
SMTP_PASS: 'change-me-sendgrid-api-key'
150-
POLAR_SERVER: 'production' # or 'sandbox'
82+
RESEND_API_KEY: ''
83+
84+
OPENAI_API_KEY: ''
85+
POLAR_SERVER: 'production' # or "sandbox"
15186
POLAR_ACCESS_TOKEN: ''
15287
POLAR_WEBHOOK_SECRET: ''
15388
POLAR_ORGANIZATION_ID: ''

infra/ansible/inventory/hosts.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[constructa]
2-
# Replace with the reachable hostname or IP of your Dokku server
2+
# Replace with the reachable hostname or IP of your Compose host
33
# example: ex0-dev ansible_user=deploy
4-
ex0-dev ansible_host=5.75.251.186 ansible_user=deploy
4+
ex0-dev ansible_host=<IP> ansible_user=deploy

infra/ansible/site-env-vars.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)