octopize.deploy_tool 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- octopize_avatar_deploy/configure.py +35 -8
- octopize_avatar_deploy/defaults.yaml +29 -45
- octopize_avatar_deploy/download_templates.py +126 -25
- octopize_avatar_deploy/state_manager.py +16 -9
- octopize_avatar_deploy/steps/required.py +8 -3
- octopize_avatar_deploy/steps/telemetry.py +6 -5
- octopize_avatar_deploy/version_compat.py +1 -1
- octopize_deploy_tool-0.3.0.dist-info/METADATA +168 -0
- {octopize_deploy_tool-0.1.0.dist-info → octopize_deploy_tool-0.3.0.dist-info}/RECORD +11 -11
- octopize_deploy_tool-0.3.0.dist-info/entry_points.txt +2 -0
- octopize_deploy_tool-0.1.0.dist-info/METADATA +0 -346
- octopize_deploy_tool-0.1.0.dist-info/entry_points.txt +0 -2
- {octopize_deploy_tool-0.1.0.dist-info → octopize_deploy_tool-0.3.0.dist-info}/WHEEL +0 -0
|
@@ -30,6 +30,8 @@ import yaml
|
|
|
30
30
|
from jinja2 import Environment, FileSystemLoader
|
|
31
31
|
|
|
32
32
|
from octopize_avatar_deploy.download_templates import (
|
|
33
|
+
REQUIRED_DOCKER_FILES,
|
|
34
|
+
REQUIRED_TEMPLATE_FILES,
|
|
33
35
|
LocalTemplateProvider,
|
|
34
36
|
download_templates,
|
|
35
37
|
)
|
|
@@ -187,7 +189,9 @@ class DeploymentConfigurator:
|
|
|
187
189
|
|
|
188
190
|
output_path = self.output_dir / output_name
|
|
189
191
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
190
|
-
|
|
192
|
+
# Ensure trailing newline for pre-commit end-of-file-fixer
|
|
193
|
+
content = rendered if rendered.endswith("\n") else rendered + "\n"
|
|
194
|
+
output_path.write_text(content)
|
|
191
195
|
|
|
192
196
|
self.printer.print_success(f"Generated: {output_path}")
|
|
193
197
|
except Exception as e:
|
|
@@ -215,13 +219,32 @@ class DeploymentConfigurator:
|
|
|
215
219
|
"authentik/octopize-avatar-blueprint.yaml",
|
|
216
220
|
)
|
|
217
221
|
|
|
218
|
-
# Copy docker-compose.yml from templates
|
|
222
|
+
# Copy docker-compose.yml from templates
|
|
219
223
|
docker_compose_src = self.templates_dir / "docker-compose.yml"
|
|
220
224
|
docker_compose_dst = self.output_dir / "docker-compose.yml"
|
|
221
225
|
if docker_compose_src.exists():
|
|
222
226
|
shutil.copy2(docker_compose_src, docker_compose_dst)
|
|
223
227
|
self.printer.print_success(f"Generated: {docker_compose_dst}")
|
|
224
228
|
|
|
229
|
+
# Copy authentik custom templates (email templates)
|
|
230
|
+
custom_templates_src = self.templates_dir / "authentik" / "custom-templates"
|
|
231
|
+
custom_templates_dst = self.output_dir / "authentik" / "custom-templates"
|
|
232
|
+
if custom_templates_src.exists():
|
|
233
|
+
custom_templates_dst.mkdir(parents=True, exist_ok=True)
|
|
234
|
+
for template_file in custom_templates_src.glob("*.html"):
|
|
235
|
+
shutil.copy2(template_file, custom_templates_dst / template_file.name)
|
|
236
|
+
self.printer.print_success(f"Copied: email templates to {custom_templates_dst}")
|
|
237
|
+
|
|
238
|
+
# Copy authentik branding files
|
|
239
|
+
branding_src = self.templates_dir / "authentik" / "branding"
|
|
240
|
+
branding_dst = self.output_dir / "authentik" / "branding"
|
|
241
|
+
if branding_src.exists():
|
|
242
|
+
branding_dst.mkdir(parents=True, exist_ok=True)
|
|
243
|
+
for branding_file in branding_src.glob("*"):
|
|
244
|
+
if branding_file.is_file():
|
|
245
|
+
shutil.copy2(branding_file, branding_dst / branding_file.name)
|
|
246
|
+
self.printer.print_success(f"Copied: branding files to {branding_dst}")
|
|
247
|
+
|
|
225
248
|
self.printer.print()
|
|
226
249
|
self.printer.print_success("Configuration files generated successfully!")
|
|
227
250
|
|
|
@@ -263,7 +286,7 @@ class DeploymentConfigurator:
|
|
|
263
286
|
# Check for existing state and prompt to resume or restart
|
|
264
287
|
if self.state and self.state.has_started() and not self.state.is_complete():
|
|
265
288
|
if interactive:
|
|
266
|
-
self.state.print_status()
|
|
289
|
+
self.state.print_status(self.printer)
|
|
267
290
|
self.printer.print_header("")
|
|
268
291
|
response = self.input_gatherer.prompt_yes_no(
|
|
269
292
|
"Resume from where you left off?", default=True
|
|
@@ -481,16 +504,19 @@ class DeploymentRunner:
|
|
|
481
504
|
Returns:
|
|
482
505
|
True if templates are available, False otherwise
|
|
483
506
|
"""
|
|
484
|
-
from octopize_avatar_deploy.download_templates import REQUIRED_FILES
|
|
485
|
-
|
|
486
507
|
if not self.templates_dir.exists():
|
|
487
508
|
if self.verbose:
|
|
488
509
|
self.printer.print_error(f"Templates directory not found: {self.templates_dir}")
|
|
489
510
|
return False
|
|
490
511
|
|
|
491
|
-
# Check for required files
|
|
512
|
+
# Check for required template files
|
|
492
513
|
missing_files = []
|
|
493
|
-
for filename in
|
|
514
|
+
for filename in REQUIRED_TEMPLATE_FILES:
|
|
515
|
+
if not (self.templates_dir / filename).exists():
|
|
516
|
+
missing_files.append(filename)
|
|
517
|
+
|
|
518
|
+
# Check for required docker files
|
|
519
|
+
for filename in REQUIRED_DOCKER_FILES:
|
|
494
520
|
if not (self.templates_dir / filename).exists():
|
|
495
521
|
missing_files.append(filename)
|
|
496
522
|
|
|
@@ -501,8 +527,9 @@ class DeploymentRunner:
|
|
|
501
527
|
)
|
|
502
528
|
return False
|
|
503
529
|
|
|
530
|
+
total_files = len(REQUIRED_TEMPLATE_FILES) + len(REQUIRED_DOCKER_FILES)
|
|
504
531
|
if self.verbose:
|
|
505
|
-
self.printer.print_success(f"Found all {
|
|
532
|
+
self.printer.print_success(f"Found all {total_files} required template files")
|
|
506
533
|
|
|
507
534
|
# Validate template version compatibility
|
|
508
535
|
return self._validate_template_version()
|
|
@@ -1,63 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
# Version: 1.0.0 (MAJOR.MINOR.PATCH)
|
|
3
|
-
# Compatible with script version: >=1.0.0,<2.0.0
|
|
4
|
-
|
|
5
|
-
version: "1.0.0"
|
|
6
|
-
|
|
7
|
-
# Image versions - updated regularly with new releases
|
|
1
|
+
version: 1.0.0
|
|
8
2
|
images:
|
|
9
|
-
api:
|
|
10
|
-
web:
|
|
11
|
-
pdfgenerator:
|
|
12
|
-
seaweedfs:
|
|
13
|
-
authentik:
|
|
14
|
-
|
|
15
|
-
# Email configuration defaults
|
|
3
|
+
api: 2.47.0
|
|
4
|
+
web: 0.52.0
|
|
5
|
+
pdfgenerator: 0.2.3
|
|
6
|
+
seaweedfs: 0.4.0
|
|
7
|
+
authentik: 2025.12.3
|
|
16
8
|
email:
|
|
17
|
-
provider:
|
|
9
|
+
provider: aws
|
|
18
10
|
smtp:
|
|
19
|
-
host:
|
|
20
|
-
port:
|
|
21
|
-
use_tls:
|
|
22
|
-
start_tls:
|
|
23
|
-
verify:
|
|
24
|
-
sender_email:
|
|
25
|
-
|
|
26
|
-
# Telemetry configuration (for usage analytics)
|
|
11
|
+
host: email-smtp.eu-west-3.amazonaws.com
|
|
12
|
+
port: '587'
|
|
13
|
+
use_tls: 'true'
|
|
14
|
+
start_tls: 'false'
|
|
15
|
+
verify: 'true'
|
|
16
|
+
sender_email: noreply@octopize.io
|
|
27
17
|
telemetry:
|
|
28
|
-
enabled: true
|
|
29
|
-
endpoint_url:
|
|
30
|
-
region:
|
|
31
|
-
|
|
32
|
-
# Application settings (defaults when no preset is selected)
|
|
18
|
+
enabled: true
|
|
19
|
+
endpoint_url: https://s3.fr-par.scw.cloud
|
|
20
|
+
region: fr-par
|
|
33
21
|
application:
|
|
34
|
-
use_console_logging:
|
|
35
|
-
log_level:
|
|
36
|
-
sentry_enabled:
|
|
37
|
-
email_authentication:
|
|
38
|
-
|
|
39
|
-
# Deployment presets - pre-configured settings for common scenarios
|
|
22
|
+
use_console_logging: 'false'
|
|
23
|
+
log_level: INFO
|
|
24
|
+
sentry_enabled: 'true'
|
|
25
|
+
email_authentication: 'true'
|
|
40
26
|
presets:
|
|
41
27
|
default:
|
|
42
|
-
description:
|
|
28
|
+
description: Production-ready configuration with telemetry and monitoring
|
|
43
29
|
application:
|
|
44
|
-
use_console_logging:
|
|
45
|
-
sentry_enabled:
|
|
30
|
+
use_console_logging: 'false'
|
|
31
|
+
sentry_enabled: 'true'
|
|
46
32
|
telemetry:
|
|
47
33
|
enabled: true
|
|
48
|
-
|
|
49
34
|
dev-mode:
|
|
50
|
-
description:
|
|
35
|
+
description: Development mode with console logging, no external services
|
|
51
36
|
application:
|
|
52
|
-
use_console_logging:
|
|
53
|
-
sentry_enabled:
|
|
37
|
+
use_console_logging: 'true'
|
|
38
|
+
sentry_enabled: 'false'
|
|
54
39
|
telemetry:
|
|
55
40
|
enabled: false
|
|
56
|
-
|
|
57
41
|
airgapped:
|
|
58
|
-
description:
|
|
42
|
+
description: Air-gapped deployment without external monitoring or telemetry
|
|
59
43
|
application:
|
|
60
|
-
use_console_logging:
|
|
61
|
-
sentry_enabled:
|
|
44
|
+
use_console_logging: 'false'
|
|
45
|
+
sentry_enabled: 'false'
|
|
62
46
|
telemetry:
|
|
63
47
|
enabled: false
|
|
@@ -15,7 +15,7 @@ GITHUB_RAW_BASE = "https://raw.githubusercontent.com/octopize/avatar-deployment"
|
|
|
15
15
|
DEFAULT_BRANCH = "main"
|
|
16
16
|
|
|
17
17
|
# Files to download from the docker/templates/ directory
|
|
18
|
-
|
|
18
|
+
REQUIRED_TEMPLATE_FILES = [
|
|
19
19
|
".env.template",
|
|
20
20
|
"nginx.conf.template",
|
|
21
21
|
"docker-compose.yml",
|
|
@@ -23,6 +23,19 @@ REQUIRED_FILES = [
|
|
|
23
23
|
"authentik/octopize-avatar-blueprint.yaml.j2",
|
|
24
24
|
]
|
|
25
25
|
|
|
26
|
+
# Additional files to download from docker/ directory (not in templates/)
|
|
27
|
+
REQUIRED_DOCKER_FILES = [
|
|
28
|
+
"authentik/custom-templates/email_account_confirmation.html",
|
|
29
|
+
"authentik/custom-templates/email_account_exists.html",
|
|
30
|
+
"authentik/custom-templates/email_account_invitation.html",
|
|
31
|
+
"authentik/custom-templates/email_forgotten_password.html",
|
|
32
|
+
"authentik/custom-templates/email_password_changed.html",
|
|
33
|
+
"authentik/custom-templates/email_password_reset.html",
|
|
34
|
+
"authentik/branding/favicon.ico",
|
|
35
|
+
"authentik/branding/logo.png",
|
|
36
|
+
"authentik/branding/background.png",
|
|
37
|
+
]
|
|
38
|
+
|
|
26
39
|
|
|
27
40
|
class TemplateProvider(ABC):
|
|
28
41
|
"""Abstract base class for template providers."""
|
|
@@ -37,12 +50,26 @@ class TemplateProvider(ABC):
|
|
|
37
50
|
self.verbose = verbose
|
|
38
51
|
|
|
39
52
|
@abstractmethod
|
|
40
|
-
def
|
|
53
|
+
def provide_template_file(self, filename: str, destination: Path) -> bool:
|
|
54
|
+
"""
|
|
55
|
+
Provide a single template file to the destination.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
filename: Name of file to provide (from docker/templates/)
|
|
59
|
+
destination: Local path where file should be saved
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
True if successful, False otherwise
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def provide_docker_file(self, filename: str, destination: Path) -> bool:
|
|
41
68
|
"""
|
|
42
|
-
Provide a single file to the destination.
|
|
69
|
+
Provide a single docker file to the destination.
|
|
43
70
|
|
|
44
71
|
Args:
|
|
45
|
-
filename: Name of file to provide
|
|
72
|
+
filename: Name of file to provide (from docker/)
|
|
46
73
|
destination: Local path where file should be saved
|
|
47
74
|
|
|
48
75
|
Returns:
|
|
@@ -52,7 +79,7 @@ class TemplateProvider(ABC):
|
|
|
52
79
|
|
|
53
80
|
def provide_all(self, output_dir: Path) -> bool:
|
|
54
81
|
"""
|
|
55
|
-
Provide all required template files.
|
|
82
|
+
Provide all required template and docker files.
|
|
56
83
|
|
|
57
84
|
Args:
|
|
58
85
|
output_dir: Directory where files should be saved
|
|
@@ -67,9 +94,17 @@ class TemplateProvider(ABC):
|
|
|
67
94
|
print(f"\nProviding templates to {output_dir}/")
|
|
68
95
|
print("=" * 60)
|
|
69
96
|
|
|
70
|
-
|
|
97
|
+
# Provide template files
|
|
98
|
+
for filename in REQUIRED_TEMPLATE_FILES:
|
|
99
|
+
destination = output_dir / filename
|
|
100
|
+
if not self.provide_template_file(filename, destination):
|
|
101
|
+
success = False
|
|
102
|
+
print(f"⚠ Warning: Failed to provide {filename}")
|
|
103
|
+
|
|
104
|
+
# Provide docker files (authentik branding, email templates, etc.)
|
|
105
|
+
for filename in REQUIRED_DOCKER_FILES:
|
|
71
106
|
destination = output_dir / filename
|
|
72
|
-
if not self.
|
|
107
|
+
if not self.provide_docker_file(filename, destination):
|
|
73
108
|
success = False
|
|
74
109
|
print(f"⚠ Warning: Failed to provide {filename}")
|
|
75
110
|
|
|
@@ -92,7 +127,10 @@ class TemplateProvider(ABC):
|
|
|
92
127
|
True if all required files exist
|
|
93
128
|
"""
|
|
94
129
|
output_dir = Path(output_dir)
|
|
95
|
-
for filename in
|
|
130
|
+
for filename in REQUIRED_TEMPLATE_FILES:
|
|
131
|
+
if not (output_dir / filename).exists():
|
|
132
|
+
return False
|
|
133
|
+
for filename in REQUIRED_DOCKER_FILES:
|
|
96
134
|
if not (output_dir / filename).exists():
|
|
97
135
|
return False
|
|
98
136
|
return True
|
|
@@ -111,11 +149,12 @@ class GitHubTemplateProvider(TemplateProvider):
|
|
|
111
149
|
"""
|
|
112
150
|
super().__init__(verbose=verbose)
|
|
113
151
|
self.branch = branch
|
|
114
|
-
self.
|
|
152
|
+
self.templates_base_url = f"{GITHUB_RAW_BASE}/{branch}/docker/templates"
|
|
153
|
+
self.docker_base_url = f"{GITHUB_RAW_BASE}/{branch}/docker"
|
|
115
154
|
|
|
116
|
-
def
|
|
155
|
+
def provide_template_file(self, filename: str, destination: Path) -> bool:
|
|
117
156
|
"""
|
|
118
|
-
Download a single file from GitHub.
|
|
157
|
+
Download a single template file from GitHub.
|
|
119
158
|
|
|
120
159
|
Args:
|
|
121
160
|
filename: Name of file to download (in docker/templates/ directory)
|
|
@@ -124,7 +163,7 @@ class GitHubTemplateProvider(TemplateProvider):
|
|
|
124
163
|
Returns:
|
|
125
164
|
True if successful, False otherwise
|
|
126
165
|
"""
|
|
127
|
-
url = f"{self.
|
|
166
|
+
url = f"{self.templates_base_url}/{filename}"
|
|
128
167
|
|
|
129
168
|
if self.verbose:
|
|
130
169
|
print(f"Downloading {filename}...")
|
|
@@ -151,21 +190,43 @@ class GitHubTemplateProvider(TemplateProvider):
|
|
|
151
190
|
print(f" ✗ Failed: {e}")
|
|
152
191
|
return False
|
|
153
192
|
|
|
154
|
-
def
|
|
193
|
+
def provide_docker_file(self, filename: str, destination: Path) -> bool:
|
|
155
194
|
"""
|
|
156
|
-
|
|
195
|
+
Download a single docker file from GitHub.
|
|
157
196
|
|
|
158
197
|
Args:
|
|
159
|
-
|
|
198
|
+
filename: Name of file to download (in docker/ directory)
|
|
199
|
+
destination: Local path where file should be saved
|
|
160
200
|
|
|
161
201
|
Returns:
|
|
162
|
-
True if
|
|
202
|
+
True if successful, False otherwise
|
|
163
203
|
"""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
204
|
+
url = f"{self.docker_base_url}/{filename}"
|
|
205
|
+
|
|
206
|
+
if self.verbose:
|
|
207
|
+
print(f"Downloading {filename}...")
|
|
208
|
+
print(f" URL: {url}")
|
|
209
|
+
print(f" Destination: {destination}")
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
with urllib.request.urlopen(url, timeout=10) as response:
|
|
213
|
+
content = response.read()
|
|
214
|
+
|
|
215
|
+
# Ensure parent directory exists
|
|
216
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
217
|
+
|
|
218
|
+
# Write file
|
|
219
|
+
destination.write_bytes(content)
|
|
220
|
+
|
|
221
|
+
if self.verbose:
|
|
222
|
+
print(f" ✓ Downloaded {len(content)} bytes")
|
|
223
|
+
|
|
224
|
+
return True
|
|
225
|
+
|
|
226
|
+
except Exception as e:
|
|
227
|
+
if self.verbose:
|
|
228
|
+
print(f" ✗ Failed: {e}")
|
|
229
|
+
return False
|
|
169
230
|
|
|
170
231
|
|
|
171
232
|
class LocalTemplateProvider(TemplateProvider):
|
|
@@ -176,18 +237,20 @@ class LocalTemplateProvider(TemplateProvider):
|
|
|
176
237
|
Initialize local template provider.
|
|
177
238
|
|
|
178
239
|
Args:
|
|
179
|
-
source_dir: Local directory containing template files
|
|
240
|
+
source_dir: Local directory containing template files (docker/templates/)
|
|
180
241
|
verbose: Print progress information
|
|
181
242
|
"""
|
|
182
243
|
super().__init__(verbose=verbose)
|
|
183
244
|
self.source_dir = Path(source_dir)
|
|
245
|
+
# Parent of templates is docker/
|
|
246
|
+
self.docker_dir = self.source_dir.parent
|
|
184
247
|
|
|
185
|
-
def
|
|
248
|
+
def provide_template_file(self, filename: str, destination: Path) -> bool:
|
|
186
249
|
"""
|
|
187
|
-
Copy a single file from source to destination.
|
|
250
|
+
Copy a single template file from source to destination.
|
|
188
251
|
|
|
189
252
|
Args:
|
|
190
|
-
filename: Name of file to copy
|
|
253
|
+
filename: Name of file to copy (from docker/templates/)
|
|
191
254
|
destination: Local path where file should be saved
|
|
192
255
|
|
|
193
256
|
Returns:
|
|
@@ -220,6 +283,44 @@ class LocalTemplateProvider(TemplateProvider):
|
|
|
220
283
|
print(f" ✗ Failed: {e}")
|
|
221
284
|
return False
|
|
222
285
|
|
|
286
|
+
def provide_docker_file(self, filename: str, destination: Path) -> bool:
|
|
287
|
+
"""
|
|
288
|
+
Copy a single docker file from source to destination.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
filename: Name of file to copy (from docker/)
|
|
292
|
+
destination: Local path where file should be saved
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
True if successful, False otherwise
|
|
296
|
+
"""
|
|
297
|
+
source = self.docker_dir / filename
|
|
298
|
+
|
|
299
|
+
if self.verbose:
|
|
300
|
+
print(f"Copying {filename}...")
|
|
301
|
+
print(f" Source: {source}")
|
|
302
|
+
print(f" Destination: {destination}")
|
|
303
|
+
|
|
304
|
+
try:
|
|
305
|
+
if not source.exists():
|
|
306
|
+
raise FileNotFoundError(f"Source file not found: {source}")
|
|
307
|
+
|
|
308
|
+
# Ensure parent directory exists
|
|
309
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
310
|
+
|
|
311
|
+
# Copy file
|
|
312
|
+
shutil.copy2(source, destination)
|
|
313
|
+
|
|
314
|
+
if self.verbose:
|
|
315
|
+
print(f" ✓ Copied {source.stat().st_size} bytes")
|
|
316
|
+
|
|
317
|
+
return True
|
|
318
|
+
|
|
319
|
+
except Exception as e:
|
|
320
|
+
if self.verbose:
|
|
321
|
+
print(f" ✗ Failed: {e}")
|
|
322
|
+
return False
|
|
323
|
+
|
|
223
324
|
|
|
224
325
|
def download_templates(
|
|
225
326
|
output_dir: Path,
|
|
@@ -116,21 +116,28 @@ class DeploymentState:
|
|
|
116
116
|
total = len(self.steps)
|
|
117
117
|
return f"{completed}/{total} steps completed"
|
|
118
118
|
|
|
119
|
-
def print_status(self) -> None:
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
def print_status(self, printer=None) -> None:
|
|
120
|
+
"""
|
|
121
|
+
Print current status.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
printer: Optional printer to use for output. If None, uses built-in print().
|
|
125
|
+
"""
|
|
126
|
+
_print = printer.print if printer else print
|
|
127
|
+
|
|
128
|
+
_print("\n" + "=" * 60)
|
|
129
|
+
_print("Deployment Configuration Status")
|
|
130
|
+
_print("=" * 60)
|
|
131
|
+
_print(f"\n{self.get_progress_summary()}\n")
|
|
125
132
|
|
|
126
133
|
for step in self.steps:
|
|
127
134
|
status = self.get_step_status(step)
|
|
128
135
|
icon = "✓" if status == "completed" else "○" if status == "not-started" else "◐"
|
|
129
|
-
|
|
136
|
+
_print(f" {icon} {step.replace('_', ' ').title()}: {status}")
|
|
130
137
|
|
|
131
138
|
if self.is_complete():
|
|
132
|
-
|
|
139
|
+
_print("\n✓ Configuration is complete!")
|
|
133
140
|
elif self.has_started():
|
|
134
141
|
next_step = self.get_next_step()
|
|
135
142
|
if next_step:
|
|
136
|
-
|
|
143
|
+
_print(f"\n→ Next step: {next_step.replace('_', ' ').title()}")
|
|
@@ -19,11 +19,16 @@ class RequiredConfigStep(DeploymentStep):
|
|
|
19
19
|
|
|
20
20
|
# Public URL - Required
|
|
21
21
|
if "PUBLIC_URL" in self.config:
|
|
22
|
-
|
|
22
|
+
public_url = self.config["PUBLIC_URL"]
|
|
23
23
|
elif self.interactive:
|
|
24
|
-
|
|
24
|
+
public_url = self.prompt("Public URL (domain name, e.g., avatar.example.com)")
|
|
25
25
|
else:
|
|
26
|
-
|
|
26
|
+
public_url = ""
|
|
27
|
+
|
|
28
|
+
# Normalize PUBLIC_URL to strip protocol and store just the domain
|
|
29
|
+
if public_url:
|
|
30
|
+
public_url = public_url.replace("https://", "").replace("http://", "").rstrip("/")
|
|
31
|
+
config["PUBLIC_URL"] = public_url
|
|
27
32
|
|
|
28
33
|
# Environment name - Required
|
|
29
34
|
if "ENV_NAME" in self.config:
|
|
@@ -50,9 +50,10 @@ class TelemetryStep(DeploymentStep):
|
|
|
50
50
|
def generate_secrets(self) -> dict[str, str]:
|
|
51
51
|
"""Generate telemetry-related secrets."""
|
|
52
52
|
# Only generate secrets if telemetry is enabled
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
|
|
54
|
+
# The user will have to provide these if telemetry is enabled
|
|
55
|
+
return {
|
|
56
|
+
"telemetry_s3_access_key_id": "",
|
|
57
|
+
"telemetry_s3_secret_access_key": "",
|
|
58
|
+
}
|
|
58
59
|
return {}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: octopize.deploy_tool
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Deployment configuration tool for Octopize Avatar platform
|
|
5
|
+
Project-URL: Homepage, https://octopize.io
|
|
6
|
+
Project-URL: Documentation, https://docs.octopize.io/docs/deploying/self-hosted
|
|
7
|
+
Project-URL: Repository, https://github.com/octopize/avatar-deployment
|
|
8
|
+
Project-URL: Issues, https://github.com/octopize/avatar-deployment/issues
|
|
9
|
+
Author-email: Octopize <contact@octopize.io>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: avatar,configuration,deployment,octopize
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: System :: Installation/Setup
|
|
19
|
+
Classifier: Topic :: System :: Systems Administration
|
|
20
|
+
Requires-Python: >=3.13
|
|
21
|
+
Requires-Dist: jinja2>=3.1.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Requires-Dist: rich>=13.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Octopize Avatar Deployment Tool
|
|
31
|
+
|
|
32
|
+
Automated configuration tool for deploying Octopize Avatar platform using Docker Compose.
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Install
|
|
38
|
+
pip install octopize-avatar-deploy
|
|
39
|
+
|
|
40
|
+
# Run interactive configuration
|
|
41
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
42
|
+
|
|
43
|
+
# Deploy
|
|
44
|
+
cd /app/avatar
|
|
45
|
+
docker compose down --volumes --remove-orphans # Clean old containers if redeploying
|
|
46
|
+
docker compose up -d
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage Options
|
|
50
|
+
|
|
51
|
+
### Interactive Mode (Default)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Non-Interactive Mode
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Create config file
|
|
61
|
+
cat > config.yaml << EOF
|
|
62
|
+
PUBLIC_URL: avatar.example.com
|
|
63
|
+
ENV_NAME: prod
|
|
64
|
+
ORGANIZATION_NAME: MyCompany
|
|
65
|
+
EOF
|
|
66
|
+
|
|
67
|
+
# Run with config
|
|
68
|
+
octopize-avatar-deploy --output-dir /app/avatar --config config.yaml --non-interactive
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Command Line Options
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
--output-dir DIR Output directory (default: current directory)
|
|
75
|
+
--config FILE YAML configuration file
|
|
76
|
+
--non-interactive Non-interactive mode (requires config file)
|
|
77
|
+
--template-from PATH Use local templates instead of downloading from GitHub
|
|
78
|
+
--save-config Save configuration to deployment-config.yaml
|
|
79
|
+
--verbose Show detailed output
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## What Gets Generated
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
/app/avatar/
|
|
86
|
+
├── .env # Environment configuration
|
|
87
|
+
├── docker-compose.yml # Docker services
|
|
88
|
+
├── nginx/nginx.conf # Nginx config
|
|
89
|
+
├── authentik/
|
|
90
|
+
│ ├── octopize-avatar-blueprint.yaml
|
|
91
|
+
│ ├── custom-templates/ # Email templates
|
|
92
|
+
│ └── branding/ # Logo, favicon, background
|
|
93
|
+
└── .secrets/ # Generated secrets (22 files)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Deployment Steps
|
|
97
|
+
|
|
98
|
+
1. **Generate configuration:**
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
octopize-avatar-deploy --output-dir /app/avatar
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
2. **Review generated files:**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cd /app/avatar
|
|
108
|
+
cat .env
|
|
109
|
+
ls -la .secrets/
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
3. **Add TLS certificates (production):**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
mkdir -p tls
|
|
116
|
+
cp /path/to/fullchain.pem tls/
|
|
117
|
+
cp /path/to/privkey.pem tls/
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
4. **Start services:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
docker compose down --volumes --remove-orphans
|
|
124
|
+
docker compose up -d
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
5. **Verify deployment:**
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
docker compose ps
|
|
131
|
+
docker compose logs -f
|
|
132
|
+
curl https://avatar.example.com/api/health
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Troubleshooting
|
|
136
|
+
|
|
137
|
+
### "bind source path does not exist" error
|
|
138
|
+
|
|
139
|
+
Old containers from previous deployment. Solution:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
docker compose down --volumes --remove-orphans
|
|
143
|
+
docker compose up -d
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Templates not downloading
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
rm -rf .avatar-templates/
|
|
150
|
+
octopize-avatar-deploy --output-dir /app/avatar --verbose
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Clone
|
|
157
|
+
git clone https://github.com/octopize/avatar-deployment
|
|
158
|
+
cd avatar-deployment/deployment-tool
|
|
159
|
+
|
|
160
|
+
# Install dependencies
|
|
161
|
+
just install
|
|
162
|
+
|
|
163
|
+
# Run tests
|
|
164
|
+
just test-all
|
|
165
|
+
|
|
166
|
+
# Run locally
|
|
167
|
+
just run-interactive-local
|
|
168
|
+
```
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
octopize_avatar_deploy/__init__.py,sha256=5RK4GI9PpEGMfABm3nZ2rEDyohQ0W_Hvn_cHQBBnAsw,651
|
|
2
2
|
octopize_avatar_deploy/cli_test_harness.py,sha256=wIMKQ3VPuJDg6LVQcJVQA8WYbKOEwNwUPBD2swl5WkU,6703
|
|
3
|
-
octopize_avatar_deploy/configure.py,sha256=
|
|
4
|
-
octopize_avatar_deploy/defaults.yaml,sha256
|
|
5
|
-
octopize_avatar_deploy/download_templates.py,sha256=
|
|
3
|
+
octopize_avatar_deploy/configure.py,sha256=BnNFFVAmA64gCV1df9bVpL3QM5xBMCB_mIOBGn-Zqls,26174
|
|
4
|
+
octopize_avatar_deploy/defaults.yaml,sha256=sZWjUOza8XXYTT7m2mcUWADXHaFqefH_jv50ySpWBX0,1144
|
|
5
|
+
octopize_avatar_deploy/download_templates.py,sha256=86oG4356rciqbEzmJSjHhwUEt0MZhKA4FBPUQbzWL2U,10797
|
|
6
6
|
octopize_avatar_deploy/input_gatherer.py,sha256=HztvV1_nK2ZWjtZWVoQcwQNjAtJbPJT0dDQ5l_GpSWU,11287
|
|
7
7
|
octopize_avatar_deploy/printer.py,sha256=3MdaL_eXk283z7BmZM94buvYeGfEvE9hAgaBgq0MoNs,6659
|
|
8
|
-
octopize_avatar_deploy/state_manager.py,sha256=
|
|
9
|
-
octopize_avatar_deploy/version_compat.py,sha256=
|
|
8
|
+
octopize_avatar_deploy/state_manager.py,sha256=3IstFyh-esorqmxOx0Bie6z3gAtHNolSlcJa0knUZSE,5090
|
|
9
|
+
octopize_avatar_deploy/version_compat.py,sha256=kgtU-344Sas9c3vXX2_fm1ZW0XI5i-KWO7v_fVsswEk,10559
|
|
10
10
|
octopize_avatar_deploy/steps/__init__.py,sha256=bITxXeDG9bvAyJ4EGUESb_uX0UTLHou98Jd8TjBrO_o,626
|
|
11
11
|
octopize_avatar_deploy/steps/authentik.py,sha256=6iSJUb18GRmz0SRYR0VzZGqPmhFRV1YZb1M9kS5XUUk,1460
|
|
12
12
|
octopize_avatar_deploy/steps/authentik_blueprint.py,sha256=fWM7F9V2gCv7Lq9vRE4YKdOfD4Bw7PTn8Iakc8FkMpw,2786
|
|
@@ -14,11 +14,11 @@ octopize_avatar_deploy/steps/base.py,sha256=91Ph8bGJRFa2ceKrpXlN3IOsFEX2F7hR3p6t
|
|
|
14
14
|
octopize_avatar_deploy/steps/database.py,sha256=9-RKxz0h2HdTSJyPdoW3iQ6veHVLH8aSfKxiAGUsqU4,1182
|
|
15
15
|
octopize_avatar_deploy/steps/email.py,sha256=9yz9qx7vBSt8Dfg-7CZ3yM2kfIoWimyyUyiGmAUP7LQ,3139
|
|
16
16
|
octopize_avatar_deploy/steps/logging.py,sha256=ks10nx0Mf0ZX9lygdIG4zoWFmAupJ528DbDRGM-PQnU,856
|
|
17
|
-
octopize_avatar_deploy/steps/required.py,sha256=
|
|
17
|
+
octopize_avatar_deploy/steps/required.py,sha256=08xxCDpMwYiKCSq4rlQhWEiF0aoZCAPatIF_x-o4Ecs,3309
|
|
18
18
|
octopize_avatar_deploy/steps/storage.py,sha256=4-GVz8cMFY_fP4m1XR0yakGXfqpAGT3ZCY-lGB2uBG4,972
|
|
19
|
-
octopize_avatar_deploy/steps/telemetry.py,sha256=
|
|
19
|
+
octopize_avatar_deploy/steps/telemetry.py,sha256=9ikriAzn0OJr4zxW-saYfvhW4GJp0WDomtzhOQU7yb8,1880
|
|
20
20
|
octopize_avatar_deploy/steps/user.py,sha256=3FSeEVjTHFieLGN2PqUwKzwIqe4vcx5eTw651Vg66ug,2825
|
|
21
|
-
octopize_deploy_tool-0.
|
|
22
|
-
octopize_deploy_tool-0.
|
|
23
|
-
octopize_deploy_tool-0.
|
|
24
|
-
octopize_deploy_tool-0.
|
|
21
|
+
octopize_deploy_tool-0.3.0.dist-info/METADATA,sha256=nuRD0VPZss-GpL8qO0z6zXBfX6kLaHdTP48tX06FG38,4113
|
|
22
|
+
octopize_deploy_tool-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
23
|
+
octopize_deploy_tool-0.3.0.dist-info/entry_points.txt,sha256=A0f3VrMyKxoPfL_jsk7VnQUy5NbbC9r1pe-y9zczPDQ,79
|
|
24
|
+
octopize_deploy_tool-0.3.0.dist-info/RECORD,,
|
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: octopize.deploy_tool
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Deployment configuration tool for Octopize Avatar platform
|
|
5
|
-
Project-URL: Homepage, https://octopize.io
|
|
6
|
-
Project-URL: Documentation, https://docs.octopize.io/docs/deploying/self-hosted
|
|
7
|
-
Project-URL: Repository, https://github.com/octopize/avatar-deployment
|
|
8
|
-
Project-URL: Issues, https://github.com/octopize/avatar-deployment/issues
|
|
9
|
-
Author-email: Octopize <contact@octopize.io>
|
|
10
|
-
License: MIT
|
|
11
|
-
Keywords: avatar,configuration,deployment,octopize
|
|
12
|
-
Classifier: Development Status :: 4 - Beta
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Intended Audience :: System Administrators
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Operating System :: OS Independent
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
Classifier: Topic :: System :: Installation/Setup
|
|
19
|
-
Classifier: Topic :: System :: Systems Administration
|
|
20
|
-
Requires-Python: >=3.13
|
|
21
|
-
Requires-Dist: jinja2>=3.1.0
|
|
22
|
-
Requires-Dist: pyyaml>=6.0
|
|
23
|
-
Requires-Dist: rich>=13.0.0
|
|
24
|
-
Provides-Extra: dev
|
|
25
|
-
Requires-Dist: mypy; extra == 'dev'
|
|
26
|
-
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
27
|
-
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
28
|
-
Description-Content-Type: text/markdown
|
|
29
|
-
|
|
30
|
-
# Octopize Avatar Deployment Tool
|
|
31
|
-
|
|
32
|
-
Automated configuration tool for deploying Octopize Avatar platform using Docker Compose.
|
|
33
|
-
|
|
34
|
-
## Overview
|
|
35
|
-
|
|
36
|
-
This tool simplifies Avatar deployment by:
|
|
37
|
-
- **📦 Standalone package** - No need to clone the entire repository
|
|
38
|
-
- **⬇️ Downloads templates** automatically from GitHub
|
|
39
|
-
- **🎯 Deployment presets** - dev-mode, production, airgapped configurations
|
|
40
|
-
- **🔐 Secure secrets generation** - Automatic creation of encryption keys
|
|
41
|
-
- **✅ Stateless by design** - Minimal bundled dependencies
|
|
42
|
-
- **🔄 Resumable configuration** - State management for interrupted setups
|
|
43
|
-
|
|
44
|
-
## Architecture
|
|
45
|
-
|
|
46
|
-
### What's Bundled vs Downloaded
|
|
47
|
-
|
|
48
|
-
**Bundled in PyPI Package:**
|
|
49
|
-
- `configure.py` - Main configuration logic
|
|
50
|
-
- `state_manager.py` - State management for resuming
|
|
51
|
-
- `download_templates.py` - Template downloader
|
|
52
|
-
- `defaults.yaml` - Default values and presets
|
|
53
|
-
|
|
54
|
-
**Downloaded from GitHub (on-demand):**
|
|
55
|
-
- `.env.template` - Environment configuration template
|
|
56
|
-
- `nginx.conf.template` - Nginx configuration template
|
|
57
|
-
- `docker-compose.yml` - Docker services definition
|
|
58
|
-
- `.template-version` - Template version information
|
|
59
|
-
- Other deployment files
|
|
60
|
-
|
|
61
|
-
These templates are located in `docker/templates/` in the avatar-deployment repository.
|
|
62
|
-
|
|
63
|
-
This design means you can install and run the tool without cloning the repository!
|
|
64
|
-
|
|
65
|
-
## Quick Start
|
|
66
|
-
|
|
67
|
-
### Option 1: Using uvx (Recommended - After PyPI Publication)
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
uvx octopize-avatar-deploy --output-dir /app/avatar
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Option 2: Using pip
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
pip install octopize-avatar-deploy
|
|
77
|
-
octopize-avatar-deploy --output-dir /app/avatar
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Option 3: From Source with uv
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# Sparse clone (only deployment-tool directory)
|
|
84
|
-
git clone --depth 1 --filter=blob:none --sparse https://github.com/octopize/avatar-deployment
|
|
85
|
-
cd avatar-deployment
|
|
86
|
-
git sparse-checkout set deployment-tool
|
|
87
|
-
|
|
88
|
-
# Run with uv
|
|
89
|
-
cd deployment-tool
|
|
90
|
-
uv run configure.py --output-dir /app/avatar
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Deployment Presets
|
|
94
|
-
|
|
95
|
-
Choose a preset to quickly configure for your environment:
|
|
96
|
-
|
|
97
|
-
### `default` - Production Configuration
|
|
98
|
-
- Console logging: **disabled** (use structured logs)
|
|
99
|
-
- Sentry monitoring: **enabled**
|
|
100
|
-
- Telemetry: **enabled**
|
|
101
|
-
- Best for: Production deployments with monitoring
|
|
102
|
-
|
|
103
|
-
### `dev-mode` - Development Configuration
|
|
104
|
-
- Console logging: **enabled** (see logs in terminal)
|
|
105
|
-
- Sentry monitoring: **disabled**
|
|
106
|
-
- Telemetry: **disabled**
|
|
107
|
-
- Best for: Local development and testing
|
|
108
|
-
|
|
109
|
-
### `airgapped` - Air-Gapped Deployment
|
|
110
|
-
- Console logging: **disabled**
|
|
111
|
-
- Sentry monitoring: **disabled** (no external connections)
|
|
112
|
-
- Telemetry: **disabled** (no external connections)
|
|
113
|
-
- Best for: Secure, isolated environments
|
|
114
|
-
|
|
115
|
-
### `custom` - Manual Configuration
|
|
116
|
-
- Configure all options interactively
|
|
117
|
-
- Best for: Specific requirements
|
|
118
|
-
|
|
119
|
-
## Usage
|
|
120
|
-
|
|
121
|
-
### Interactive Mode with Preset
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
octopize-avatar-deploy --output-dir /app/avatar --preset dev-mode
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
The tool will:
|
|
128
|
-
1. Download latest templates from GitHub
|
|
129
|
-
2. Apply preset configuration
|
|
130
|
-
3. Prompt for required values (PUBLIC_URL, ENV_NAME)
|
|
131
|
-
4. Generate configuration files
|
|
132
|
-
|
|
133
|
-
### Non-Interactive Mode
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
# Create config file
|
|
137
|
-
cat > my-config.yaml << EOF
|
|
138
|
-
PUBLIC_URL: avatar.mycompany.com
|
|
139
|
-
ENV_NAME: mycompany-prod
|
|
140
|
-
AVATAR_API_VERSION: 2.20.1
|
|
141
|
-
AVATAR_WEB_VERSION: 0.40.0
|
|
142
|
-
MAIL_PROVIDER: smtp
|
|
143
|
-
SMTP_HOST: mail.mycompany.com
|
|
144
|
-
EOF
|
|
145
|
-
|
|
146
|
-
# Run with config
|
|
147
|
-
octopize-avatar-deploy \
|
|
148
|
-
--config my-config.yaml \
|
|
149
|
-
--preset default \
|
|
150
|
-
--non-interactive \
|
|
151
|
-
--output-dir /app/avatar
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### Advanced Options
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
octopize-avatar-deploy \
|
|
158
|
-
--output-dir /app/avatar \
|
|
159
|
-
--preset dev-mode \
|
|
160
|
-
--download-branch main \ # Git branch to download from
|
|
161
|
-
--skip-download \ # Use cached templates
|
|
162
|
-
--save-config \ # Save config to deployment-config.yaml
|
|
163
|
-
--verbose # Show detailed progress
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Command Line Options
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
--output-dir DIR Output directory (default: current directory)
|
|
170
|
-
--preset NAME Use preset: default, dev-mode, airgapped
|
|
171
|
-
--config FILE YAML configuration file
|
|
172
|
-
--non-interactive Non-interactive mode (use config/defaults)
|
|
173
|
-
--auth-type TYPE Authentication: email or username (default: email)
|
|
174
|
-
--save-config Save config to deployment-config.yaml
|
|
175
|
-
--download-branch BRANCH Git branch for templates (default: main)
|
|
176
|
-
--skip-download Use cached templates
|
|
177
|
-
--verbose Detailed output
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## What Gets Generated
|
|
181
|
-
|
|
182
|
-
After running the tool, you'll have:
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
/app/avatar/
|
|
186
|
-
├── .env # Environment configuration
|
|
187
|
-
├── nginx.conf # Nginx reverse proxy config
|
|
188
|
-
├── .secrets/ # Generated secrets (gitignored)
|
|
189
|
-
│ ├── db_password
|
|
190
|
-
│ ├── authentik_secret_key
|
|
191
|
-
│ ├── avatar_api_encryption_key
|
|
192
|
-
│ └── ...
|
|
193
|
-
├── docker-compose.yml # Downloaded from GitHub
|
|
194
|
-
└── .avatar-templates/ # Cached templates (auto-downloaded)
|
|
195
|
-
├── .env.template
|
|
196
|
-
├── nginx.conf.template
|
|
197
|
-
├── docker-compose.yml
|
|
198
|
-
└── .template-version
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Configuration Presets in Detail
|
|
202
|
-
|
|
203
|
-
Presets are defined in `defaults.yaml`:
|
|
204
|
-
|
|
205
|
-
```yaml
|
|
206
|
-
presets:
|
|
207
|
-
default:
|
|
208
|
-
description: "Production-ready with telemetry and monitoring"
|
|
209
|
-
application:
|
|
210
|
-
use_console_logging: "false"
|
|
211
|
-
sentry_enabled: "true"
|
|
212
|
-
telemetry:
|
|
213
|
-
enabled: true
|
|
214
|
-
|
|
215
|
-
dev-mode:
|
|
216
|
-
description: "Development with console logging"
|
|
217
|
-
application:
|
|
218
|
-
use_console_logging: "true"
|
|
219
|
-
sentry_enabled: "false"
|
|
220
|
-
telemetry:
|
|
221
|
-
enabled: false
|
|
222
|
-
|
|
223
|
-
airgapped:
|
|
224
|
-
description: "No external monitoring/telemetry"
|
|
225
|
-
application:
|
|
226
|
-
use_console_logging: "false"
|
|
227
|
-
sentry_enabled: "false"
|
|
228
|
-
telemetry:
|
|
229
|
-
enabled: false
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
You can override preset values during interactive configuration.
|
|
233
|
-
|
|
234
|
-
## Template Download Mechanism
|
|
235
|
-
|
|
236
|
-
Templates are downloaded from GitHub on first run:
|
|
237
|
-
|
|
238
|
-
1. **Check cache** - `.avatar-templates/` directory
|
|
239
|
-
2. **Download if needed** - From `github.com/octopize/avatar-deployment`
|
|
240
|
-
3. **Use cached** - On subsequent runs (unless `--skip-download` is used)
|
|
241
|
-
|
|
242
|
-
This ensures:
|
|
243
|
-
- ✅ Always get latest templates (from specified branch)
|
|
244
|
-
- ✅ Offline support (once cached)
|
|
245
|
-
- ✅ No repository cloning required
|
|
246
|
-
- ✅ Minimal package size
|
|
247
|
-
|
|
248
|
-
## State Management
|
|
249
|
-
|
|
250
|
-
The tool saves progress to `.deployment-state.yaml` allowing you to:
|
|
251
|
-
|
|
252
|
-
- **Resume interrupted configurations**
|
|
253
|
-
- **Track which steps completed**
|
|
254
|
-
- **Avoid re-entering values**
|
|
255
|
-
|
|
256
|
-
Steps:
|
|
257
|
-
1. Collect required config
|
|
258
|
-
2. Collect optional config
|
|
259
|
-
3. Generate .env file
|
|
260
|
-
4. Generate nginx.conf
|
|
261
|
-
5. Generate secrets
|
|
262
|
-
6. Prompt for user secrets (optional)
|
|
263
|
-
7. Finalize
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
# If interrupted, just run again:
|
|
267
|
-
octopize-avatar-deploy --output-dir /app/avatar
|
|
268
|
-
|
|
269
|
-
# Tool will ask: "Continue from where you left off? [Y/n]"
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Troubleshooting
|
|
273
|
-
|
|
274
|
-
### Templates not downloading
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
# Force re-download
|
|
278
|
-
rm -rf .avatar-templates/
|
|
279
|
-
octopize-avatar-deploy --output-dir /app/avatar --verbose
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Use specific Git branch
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
# Download from development branch
|
|
286
|
-
octopize-avatar-deploy \
|
|
287
|
-
--output-dir /app/avatar \
|
|
288
|
-
--download-branch develop \
|
|
289
|
-
--verbose
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Offline mode
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
# Download templates once
|
|
296
|
-
octopize-avatar-deploy --output-dir /app/avatar
|
|
297
|
-
|
|
298
|
-
# Then use cached versions
|
|
299
|
-
octopize-avatar-deploy --output-dir /app/avatar --skip-download
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## Development
|
|
303
|
-
|
|
304
|
-
### Project Structure
|
|
305
|
-
|
|
306
|
-
```
|
|
307
|
-
deployment-tool/
|
|
308
|
-
├── configure.py # Main script (bundled)
|
|
309
|
-
├── state_manager.py # State management (bundled)
|
|
310
|
-
├── download_templates.py # Template downloader (bundled)
|
|
311
|
-
├── defaults.yaml # Defaults and presets (bundled)
|
|
312
|
-
├── tests/ # Test suite
|
|
313
|
-
├── README.md
|
|
314
|
-
└── pyproject.toml # Package configuration
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### Running Tests
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
cd deployment-tool
|
|
321
|
-
pytest tests/
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Building Package
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
pip install build
|
|
328
|
-
python -m build
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
## Related Documentation
|
|
332
|
-
|
|
333
|
-
- [Deployment Guide](../deploying-on-single-instance.md)
|
|
334
|
-
- [Docker Compose Configuration](../docker-compose.yml)
|
|
335
|
-
- [Migration Guide](../MIGRATION_GUIDE.md)
|
|
336
|
-
|
|
337
|
-
## Support
|
|
338
|
-
|
|
339
|
-
For issues and questions:
|
|
340
|
-
- Email: help@octopize.io
|
|
341
|
-
- Documentation: https://docs.octopize.io
|
|
342
|
-
- Repository: https://github.com/octopize/avatar-deployment
|
|
343
|
-
|
|
344
|
-
## License
|
|
345
|
-
|
|
346
|
-
Apache License v2.0
|
|
File without changes
|