nvoi 0.1.5
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.
- checksums.yaml +7 -0
- data/.rubocop.yml +19 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +151 -0
- data/Makefile +26 -0
- data/Rakefile +16 -0
- data/doc/config-schema.yaml +357 -0
- data/examples/apex-wildcard/deploy.yml +68 -0
- data/examples/golang/.gitignore +19 -0
- data/examples/golang/Dockerfile +43 -0
- data/examples/golang/README.md +59 -0
- data/examples/golang/deploy.enc +0 -0
- data/examples/golang/deploy.yml +54 -0
- data/examples/golang/go.mod +39 -0
- data/examples/golang/go.sum +96 -0
- data/examples/golang/main.go +177 -0
- data/examples/golang/models/user.go +17 -0
- data/examples/golang-postgres-multi/.gitignore +18 -0
- data/examples/golang-postgres-multi/Dockerfile +39 -0
- data/examples/golang-postgres-multi/README.md +211 -0
- data/examples/golang-postgres-multi/deploy.yml +67 -0
- data/examples/golang-postgres-multi/go.mod +45 -0
- data/examples/golang-postgres-multi/go.sum +108 -0
- data/examples/golang-postgres-multi/main.go +197 -0
- data/examples/golang-postgres-multi/models/user.go +17 -0
- data/examples/postgres-multi/.env.production.example +11 -0
- data/examples/postgres-multi/README.md +112 -0
- data/examples/postgres-multi/deploy.yml +74 -0
- data/examples/postgres-single/.env.production.example +11 -0
- data/examples/postgres-single/.gitignore +15 -0
- data/examples/postgres-single/Dockerfile +35 -0
- data/examples/postgres-single/README.md +76 -0
- data/examples/postgres-single/deploy.yml +56 -0
- data/examples/postgres-single/go.mod +45 -0
- data/examples/postgres-single/go.sum +108 -0
- data/examples/postgres-single/main.go +184 -0
- data/examples/rails-single/.dockerignore +51 -0
- data/examples/rails-single/.env.production.example +11 -0
- data/examples/rails-single/.github/dependabot.yml +12 -0
- data/examples/rails-single/.github/workflows/ci.yml +39 -0
- data/examples/rails-single/.gitignore +20 -0
- data/examples/rails-single/.node-version +1 -0
- data/examples/rails-single/.rubocop.yml +8 -0
- data/examples/rails-single/.ruby-version +1 -0
- data/examples/rails-single/Dockerfile +86 -0
- data/examples/rails-single/Gemfile +56 -0
- data/examples/rails-single/Gemfile.lock +350 -0
- data/examples/rails-single/Procfile.dev +3 -0
- data/examples/rails-single/README.md +17 -0
- data/examples/rails-single/Rakefile +6 -0
- data/examples/rails-single/app/assets/builds/.keep +0 -0
- data/examples/rails-single/app/assets/images/.keep +0 -0
- data/examples/rails-single/app/assets/stylesheets/application.tailwind.css +1 -0
- data/examples/rails-single/app/controllers/application_controller.rb +4 -0
- data/examples/rails-single/app/controllers/concerns/.keep +0 -0
- data/examples/rails-single/app/controllers/users_controller.rb +19 -0
- data/examples/rails-single/app/helpers/application_helper.rb +2 -0
- data/examples/rails-single/app/javascript/application.js +3 -0
- data/examples/rails-single/app/javascript/controllers/application.js +9 -0
- data/examples/rails-single/app/javascript/controllers/hello_controller.js +7 -0
- data/examples/rails-single/app/javascript/controllers/index.js +8 -0
- data/examples/rails-single/app/jobs/application_job.rb +7 -0
- data/examples/rails-single/app/mailers/application_mailer.rb +4 -0
- data/examples/rails-single/app/models/application_record.rb +3 -0
- data/examples/rails-single/app/models/concerns/.keep +0 -0
- data/examples/rails-single/app/models/user.rb +2 -0
- data/examples/rails-single/app/views/layouts/application.html.erb +28 -0
- data/examples/rails-single/app/views/layouts/mailer.html.erb +13 -0
- data/examples/rails-single/app/views/layouts/mailer.text.erb +1 -0
- data/examples/rails-single/app/views/pwa/manifest.json.erb +22 -0
- data/examples/rails-single/app/views/pwa/service-worker.js +26 -0
- data/examples/rails-single/app/views/users/index.html.erb +38 -0
- data/examples/rails-single/bin/brakeman +7 -0
- data/examples/rails-single/bin/bundle +109 -0
- data/examples/rails-single/bin/dev +11 -0
- data/examples/rails-single/bin/docker-entrypoint +14 -0
- data/examples/rails-single/bin/jobs +6 -0
- data/examples/rails-single/bin/kamal +27 -0
- data/examples/rails-single/bin/rails +4 -0
- data/examples/rails-single/bin/rake +4 -0
- data/examples/rails-single/bin/rubocop +8 -0
- data/examples/rails-single/bin/setup +37 -0
- data/examples/rails-single/bin/thrust +5 -0
- data/examples/rails-single/bun.lock +224 -0
- data/examples/rails-single/config/application.rb +42 -0
- data/examples/rails-single/config/boot.rb +4 -0
- data/examples/rails-single/config/cable.yml +17 -0
- data/examples/rails-single/config/cache.yml +16 -0
- data/examples/rails-single/config/credentials.yml.enc +1 -0
- data/examples/rails-single/config/database.yml +100 -0
- data/examples/rails-single/config/environment.rb +5 -0
- data/examples/rails-single/config/environments/development.rb +69 -0
- data/examples/rails-single/config/environments/production.rb +87 -0
- data/examples/rails-single/config/environments/test.rb +50 -0
- data/examples/rails-single/config/initializers/assets.rb +7 -0
- data/examples/rails-single/config/initializers/content_security_policy.rb +25 -0
- data/examples/rails-single/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/rails-single/config/initializers/inflections.rb +16 -0
- data/examples/rails-single/config/locales/en.yml +31 -0
- data/examples/rails-single/config/puma.rb +41 -0
- data/examples/rails-single/config/queue.yml +18 -0
- data/examples/rails-single/config/recurring.yml +15 -0
- data/examples/rails-single/config/routes.rb +4 -0
- data/examples/rails-single/config.ru +6 -0
- data/examples/rails-single/db/cable_schema.rb +11 -0
- data/examples/rails-single/db/cache_schema.rb +12 -0
- data/examples/rails-single/db/migrate/20251123095526_create_users.rb +10 -0
- data/examples/rails-single/db/queue_schema.rb +129 -0
- data/examples/rails-single/db/seeds.rb +9 -0
- data/examples/rails-single/deploy.yml +57 -0
- data/examples/rails-single/lib/tasks/.keep +0 -0
- data/examples/rails-single/log/.keep +0 -0
- data/examples/rails-single/package.json +17 -0
- data/examples/rails-single/public/400.html +114 -0
- data/examples/rails-single/public/404.html +114 -0
- data/examples/rails-single/public/406-unsupported-browser.html +114 -0
- data/examples/rails-single/public/422.html +114 -0
- data/examples/rails-single/public/500.html +114 -0
- data/examples/rails-single/public/icon.png +0 -0
- data/examples/rails-single/public/icon.svg +3 -0
- data/examples/rails-single/public/robots.txt +1 -0
- data/examples/rails-single/script/.keep +0 -0
- data/examples/rails-single/vendor/.keep +0 -0
- data/examples/rails-single/yarn.lock +188 -0
- data/exe/nvoi +6 -0
- data/lib/nvoi/cli.rb +190 -0
- data/lib/nvoi/cloudflare/client.rb +287 -0
- data/lib/nvoi/config/config.rb +248 -0
- data/lib/nvoi/config/env_resolver.rb +63 -0
- data/lib/nvoi/config/loader.rb +102 -0
- data/lib/nvoi/config/naming.rb +196 -0
- data/lib/nvoi/config/ssh_keys.rb +82 -0
- data/lib/nvoi/config/types.rb +274 -0
- data/lib/nvoi/constants.rb +59 -0
- data/lib/nvoi/credentials/crypto.rb +88 -0
- data/lib/nvoi/credentials/editor.rb +272 -0
- data/lib/nvoi/credentials/manager.rb +173 -0
- data/lib/nvoi/deployer/cleaner.rb +36 -0
- data/lib/nvoi/deployer/image_builder.rb +23 -0
- data/lib/nvoi/deployer/infrastructure.rb +126 -0
- data/lib/nvoi/deployer/orchestrator.rb +146 -0
- data/lib/nvoi/deployer/retry.rb +67 -0
- data/lib/nvoi/deployer/service_deployer.rb +311 -0
- data/lib/nvoi/deployer/tunnel_manager.rb +57 -0
- data/lib/nvoi/deployer/types.rb +8 -0
- data/lib/nvoi/errors.rb +67 -0
- data/lib/nvoi/k8s/renderer.rb +44 -0
- data/lib/nvoi/k8s/templates.rb +29 -0
- data/lib/nvoi/logger.rb +72 -0
- data/lib/nvoi/providers/aws.rb +403 -0
- data/lib/nvoi/providers/base.rb +111 -0
- data/lib/nvoi/providers/hetzner.rb +288 -0
- data/lib/nvoi/providers/hetzner_client.rb +170 -0
- data/lib/nvoi/remote/docker_manager.rb +203 -0
- data/lib/nvoi/remote/ssh_executor.rb +72 -0
- data/lib/nvoi/remote/volume_manager.rb +103 -0
- data/lib/nvoi/service/delete.rb +234 -0
- data/lib/nvoi/service/deploy.rb +80 -0
- data/lib/nvoi/service/exec.rb +144 -0
- data/lib/nvoi/service/provider.rb +36 -0
- data/lib/nvoi/steps/application_deployer.rb +26 -0
- data/lib/nvoi/steps/database_provisioner.rb +60 -0
- data/lib/nvoi/steps/k3s_cluster_setup.rb +105 -0
- data/lib/nvoi/steps/k3s_provisioner.rb +351 -0
- data/lib/nvoi/steps/server_provisioner.rb +43 -0
- data/lib/nvoi/steps/services_provisioner.rb +29 -0
- data/lib/nvoi/steps/tunnel_configurator.rb +66 -0
- data/lib/nvoi/steps/volume_provisioner.rb +154 -0
- data/lib/nvoi/version.rb +5 -0
- data/lib/nvoi.rb +79 -0
- data/templates/app-deployment.yaml.erb +102 -0
- data/templates/app-ingress.yaml.erb +20 -0
- data/templates/app-secret.yaml.erb +10 -0
- data/templates/app-service.yaml.erb +12 -0
- data/templates/db-statefulset.yaml.erb +76 -0
- data/templates/service-deployment.yaml.erb +91 -0
- data/templates/worker-deployment.yaml.erb +50 -0
- metadata +361 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: fb54d0e596f64c761d8c3b6f38e6ae0ea7f71186e89744078e6b09e9906bfc1a
|
|
4
|
+
data.tar.gz: 22eca4a7d6bc75e7d5f9c0372a261d3c82b88b07f3d82db38828c486249495c7
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2f18b886aa28994c1f6f8caace570f1ad714815f4161ce2bbb48b00be06f7f3f60e7fa14e04d8c1423aa0b55039ca43165bf360c73fc11e8ccb73ea7a7b0a67f
|
|
7
|
+
data.tar.gz: 53d83331ca4ecd654fb1d563149f04ffae292474b2cf930cbeefafa00f6bbb746ade07fc1c400409445282718bb50eaf5db26dd0df187ac011313a242b3ca6a0
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Omakase Ruby styling for Rails
|
|
2
|
+
inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
|
3
|
+
|
|
4
|
+
# Overwrite or add rules to create your own house style
|
|
5
|
+
#
|
|
6
|
+
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
|
|
7
|
+
Layout/SpaceInsideArrayLiteralBrackets:
|
|
8
|
+
Enabled: false
|
|
9
|
+
|
|
10
|
+
# Enforce Ruby 3.1+ hash shorthand syntax
|
|
11
|
+
Style/HashSyntax:
|
|
12
|
+
EnforcedStyle: ruby19_no_mixed_keys
|
|
13
|
+
EnforcedShorthandSyntax: always
|
|
14
|
+
|
|
15
|
+
Layout/IndentationConsistency:
|
|
16
|
+
Enabled: true
|
|
17
|
+
|
|
18
|
+
Layout/IndentationWidth:
|
|
19
|
+
Enabled: true
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
nvoi (0.1.5)
|
|
5
|
+
aws-sdk-ec2 (~> 1.400)
|
|
6
|
+
faraday (~> 2.7)
|
|
7
|
+
net-scp (~> 4.0)
|
|
8
|
+
net-ssh (~> 7.2)
|
|
9
|
+
thor (~> 1.3)
|
|
10
|
+
|
|
11
|
+
GEM
|
|
12
|
+
remote: https://rubygems.org/
|
|
13
|
+
specs:
|
|
14
|
+
activesupport (8.1.1)
|
|
15
|
+
base64
|
|
16
|
+
bigdecimal
|
|
17
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
18
|
+
connection_pool (>= 2.2.5)
|
|
19
|
+
drb
|
|
20
|
+
i18n (>= 1.6, < 2)
|
|
21
|
+
json
|
|
22
|
+
logger (>= 1.4.2)
|
|
23
|
+
minitest (>= 5.1)
|
|
24
|
+
securerandom (>= 0.3)
|
|
25
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
26
|
+
uri (>= 0.13.1)
|
|
27
|
+
addressable (2.8.8)
|
|
28
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
29
|
+
ast (2.4.3)
|
|
30
|
+
aws-eventstream (1.4.0)
|
|
31
|
+
aws-partitions (1.1191.0)
|
|
32
|
+
aws-sdk-core (3.239.2)
|
|
33
|
+
aws-eventstream (~> 1, >= 1.3.0)
|
|
34
|
+
aws-partitions (~> 1, >= 1.992.0)
|
|
35
|
+
aws-sigv4 (~> 1.9)
|
|
36
|
+
base64
|
|
37
|
+
bigdecimal
|
|
38
|
+
jmespath (~> 1, >= 1.6.1)
|
|
39
|
+
logger
|
|
40
|
+
aws-sdk-ec2 (1.584.0)
|
|
41
|
+
aws-sdk-core (~> 3, >= 3.239.1)
|
|
42
|
+
aws-sigv4 (~> 1.5)
|
|
43
|
+
aws-sigv4 (1.12.1)
|
|
44
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
45
|
+
base64 (0.3.0)
|
|
46
|
+
bigdecimal (3.3.1)
|
|
47
|
+
concurrent-ruby (1.3.5)
|
|
48
|
+
connection_pool (3.0.2)
|
|
49
|
+
crack (1.0.1)
|
|
50
|
+
bigdecimal
|
|
51
|
+
rexml
|
|
52
|
+
drb (2.2.3)
|
|
53
|
+
faraday (2.14.0)
|
|
54
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
55
|
+
json
|
|
56
|
+
logger
|
|
57
|
+
faraday-net_http (3.4.2)
|
|
58
|
+
net-http (~> 0.5)
|
|
59
|
+
hashdiff (1.2.1)
|
|
60
|
+
i18n (1.14.7)
|
|
61
|
+
concurrent-ruby (~> 1.0)
|
|
62
|
+
jmespath (1.6.2)
|
|
63
|
+
json (2.17.1)
|
|
64
|
+
language_server-protocol (3.17.0.5)
|
|
65
|
+
lint_roller (1.1.0)
|
|
66
|
+
logger (1.7.0)
|
|
67
|
+
minitest (5.26.2)
|
|
68
|
+
net-http (0.8.0)
|
|
69
|
+
uri (>= 0.11.1)
|
|
70
|
+
net-scp (4.1.0)
|
|
71
|
+
net-ssh (>= 2.6.5, < 8.0.0)
|
|
72
|
+
net-ssh (7.3.0)
|
|
73
|
+
parallel (1.27.0)
|
|
74
|
+
parser (3.3.10.0)
|
|
75
|
+
ast (~> 2.4.1)
|
|
76
|
+
racc
|
|
77
|
+
prism (1.6.0)
|
|
78
|
+
public_suffix (7.0.0)
|
|
79
|
+
racc (1.8.1)
|
|
80
|
+
rack (3.2.4)
|
|
81
|
+
rainbow (3.1.1)
|
|
82
|
+
rake (13.3.1)
|
|
83
|
+
regexp_parser (2.11.3)
|
|
84
|
+
rexml (3.4.4)
|
|
85
|
+
rubocop (1.81.7)
|
|
86
|
+
json (~> 2.3)
|
|
87
|
+
language_server-protocol (~> 3.17.0.2)
|
|
88
|
+
lint_roller (~> 1.1.0)
|
|
89
|
+
parallel (~> 1.10)
|
|
90
|
+
parser (>= 3.3.0.2)
|
|
91
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
92
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
93
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
94
|
+
ruby-progressbar (~> 1.7)
|
|
95
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
96
|
+
rubocop-ast (1.48.0)
|
|
97
|
+
parser (>= 3.3.7.2)
|
|
98
|
+
prism (~> 1.4)
|
|
99
|
+
rubocop-performance (1.26.1)
|
|
100
|
+
lint_roller (~> 1.1)
|
|
101
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
102
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
103
|
+
rubocop-rails (2.34.2)
|
|
104
|
+
activesupport (>= 4.2.0)
|
|
105
|
+
lint_roller (~> 1.1)
|
|
106
|
+
rack (>= 1.1)
|
|
107
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
108
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
|
109
|
+
rubocop-rails-omakase (1.1.0)
|
|
110
|
+
rubocop (>= 1.72)
|
|
111
|
+
rubocop-performance (>= 1.24)
|
|
112
|
+
rubocop-rails (>= 2.30)
|
|
113
|
+
ruby-progressbar (1.13.0)
|
|
114
|
+
securerandom (0.4.1)
|
|
115
|
+
thor (1.4.0)
|
|
116
|
+
tzinfo (2.0.6)
|
|
117
|
+
concurrent-ruby (~> 1.0)
|
|
118
|
+
unicode-display_width (3.2.0)
|
|
119
|
+
unicode-emoji (~> 4.1)
|
|
120
|
+
unicode-emoji (4.1.0)
|
|
121
|
+
uri (1.1.1)
|
|
122
|
+
webmock (3.26.1)
|
|
123
|
+
addressable (>= 2.8.0)
|
|
124
|
+
crack (>= 0.3.2)
|
|
125
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
126
|
+
|
|
127
|
+
PLATFORMS
|
|
128
|
+
aarch64-linux-gnu
|
|
129
|
+
aarch64-linux-musl
|
|
130
|
+
arm-linux-gnu
|
|
131
|
+
arm-linux-musl
|
|
132
|
+
arm64-darwin
|
|
133
|
+
ruby
|
|
134
|
+
x86-linux-gnu
|
|
135
|
+
x86-linux-musl
|
|
136
|
+
x86_64-darwin
|
|
137
|
+
x86_64-linux
|
|
138
|
+
x86_64-linux-gnu
|
|
139
|
+
x86_64-linux-musl
|
|
140
|
+
|
|
141
|
+
DEPENDENCIES
|
|
142
|
+
bundler (~> 2.0)
|
|
143
|
+
minitest (~> 5.20)
|
|
144
|
+
nvoi!
|
|
145
|
+
rake (~> 13.0)
|
|
146
|
+
rubocop (~> 1.57)
|
|
147
|
+
rubocop-rails-omakase
|
|
148
|
+
webmock (~> 3.19)
|
|
149
|
+
|
|
150
|
+
BUNDLED WITH
|
|
151
|
+
2.6.5
|
data/Makefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
NVOI = ruby -I$(PWD)/lib $(PWD)/exe/nvoi
|
|
2
|
+
EXAMPLES = $(PWD)/examples
|
|
3
|
+
|
|
4
|
+
deploy-golang:
|
|
5
|
+
cd $(EXAMPLES)/golang && $(NVOI) deploy
|
|
6
|
+
|
|
7
|
+
exec-golang:
|
|
8
|
+
cd $(EXAMPLES)/golang && $(NVOI) exec -i
|
|
9
|
+
|
|
10
|
+
show-golang:
|
|
11
|
+
cd $(EXAMPLES)/golang && $(NVOI) credentials show
|
|
12
|
+
|
|
13
|
+
delete-golang:
|
|
14
|
+
cd $(EXAMPLES)/golang && $(NVOI) delete
|
|
15
|
+
|
|
16
|
+
deploy-rails:
|
|
17
|
+
cd $(EXAMPLES)/rails-single && $(NVOI) deploy
|
|
18
|
+
|
|
19
|
+
delete-rails:
|
|
20
|
+
cd $(EXAMPLES)/rails-single && $(NVOI) delete
|
|
21
|
+
|
|
22
|
+
test:
|
|
23
|
+
bundle exec rake test
|
|
24
|
+
|
|
25
|
+
lint:
|
|
26
|
+
bundle exec rubocop
|
data/Rakefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
require "rubocop/rake_task"
|
|
6
|
+
|
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
|
8
|
+
t.libs << "test"
|
|
9
|
+
t.libs << "lib"
|
|
10
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
11
|
+
t.warning = false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
RuboCop::RakeTask.new
|
|
15
|
+
|
|
16
|
+
task default: %i[test]
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
info:
|
|
3
|
+
title: NVOI Configuration Schema
|
|
4
|
+
version: 0.1.2
|
|
5
|
+
description: |
|
|
6
|
+
OpenAPI 3.1 / JSON Schema definition for NVOI deployment configuration.
|
|
7
|
+
This schema defines the structure of deploy.yml / deploy.enc files.
|
|
8
|
+
|
|
9
|
+
components:
|
|
10
|
+
schemas:
|
|
11
|
+
DeployConfig:
|
|
12
|
+
type: object
|
|
13
|
+
description: Root deployment configuration
|
|
14
|
+
required:
|
|
15
|
+
- application
|
|
16
|
+
properties:
|
|
17
|
+
application:
|
|
18
|
+
$ref: "#/components/schemas/Application"
|
|
19
|
+
|
|
20
|
+
Application:
|
|
21
|
+
type: object
|
|
22
|
+
description: Application-level configuration
|
|
23
|
+
required:
|
|
24
|
+
- name
|
|
25
|
+
properties:
|
|
26
|
+
name:
|
|
27
|
+
type: string
|
|
28
|
+
description: Application name (used for resource naming)
|
|
29
|
+
example: myapp
|
|
30
|
+
environment:
|
|
31
|
+
type: string
|
|
32
|
+
description: Deployment environment
|
|
33
|
+
default: production
|
|
34
|
+
example: production
|
|
35
|
+
domain_provider:
|
|
36
|
+
$ref: "#/components/schemas/DomainProviderConfig"
|
|
37
|
+
compute_provider:
|
|
38
|
+
$ref: "#/components/schemas/ComputeProviderConfig"
|
|
39
|
+
keep_count:
|
|
40
|
+
type: integer
|
|
41
|
+
description: Number of old deployments to keep for rollback
|
|
42
|
+
minimum: 0
|
|
43
|
+
example: 3
|
|
44
|
+
servers:
|
|
45
|
+
type: object
|
|
46
|
+
description: Server group definitions (key is group name)
|
|
47
|
+
additionalProperties:
|
|
48
|
+
$ref: "#/components/schemas/ServerConfig"
|
|
49
|
+
example:
|
|
50
|
+
master:
|
|
51
|
+
type: cx32
|
|
52
|
+
location: fsn1
|
|
53
|
+
workers:
|
|
54
|
+
count: 2
|
|
55
|
+
type: cx22
|
|
56
|
+
app:
|
|
57
|
+
type: object
|
|
58
|
+
description: Application services (key is service name)
|
|
59
|
+
additionalProperties:
|
|
60
|
+
$ref: "#/components/schemas/AppServiceConfig"
|
|
61
|
+
example:
|
|
62
|
+
web:
|
|
63
|
+
port: 3000
|
|
64
|
+
domain: example.com
|
|
65
|
+
database:
|
|
66
|
+
$ref: "#/components/schemas/DatabaseConfig"
|
|
67
|
+
services:
|
|
68
|
+
type: object
|
|
69
|
+
description: Additional services like Redis, etc. (key is service name)
|
|
70
|
+
additionalProperties:
|
|
71
|
+
$ref: "#/components/schemas/ServiceConfig"
|
|
72
|
+
example:
|
|
73
|
+
redis:
|
|
74
|
+
image: redis:7-alpine
|
|
75
|
+
env:
|
|
76
|
+
type: object
|
|
77
|
+
description: Global environment variables
|
|
78
|
+
additionalProperties:
|
|
79
|
+
type: string
|
|
80
|
+
example:
|
|
81
|
+
RAILS_ENV: production
|
|
82
|
+
LOG_LEVEL: info
|
|
83
|
+
secrets:
|
|
84
|
+
type: object
|
|
85
|
+
description: Secret environment variables (stored encrypted)
|
|
86
|
+
additionalProperties:
|
|
87
|
+
type: string
|
|
88
|
+
example:
|
|
89
|
+
DATABASE_URL: postgres://user:pass@host/db
|
|
90
|
+
ssh_keys:
|
|
91
|
+
$ref: "#/components/schemas/SSHKeyConfig"
|
|
92
|
+
|
|
93
|
+
DomainProviderConfig:
|
|
94
|
+
type: object
|
|
95
|
+
description: Domain/DNS provider configuration
|
|
96
|
+
properties:
|
|
97
|
+
cloudflare:
|
|
98
|
+
$ref: "#/components/schemas/CloudflareConfig"
|
|
99
|
+
|
|
100
|
+
ComputeProviderConfig:
|
|
101
|
+
type: object
|
|
102
|
+
description: Compute provider configuration (one of hetzner or aws)
|
|
103
|
+
properties:
|
|
104
|
+
hetzner:
|
|
105
|
+
$ref: "#/components/schemas/HetznerConfig"
|
|
106
|
+
aws:
|
|
107
|
+
$ref: "#/components/schemas/AWSConfig"
|
|
108
|
+
|
|
109
|
+
CloudflareConfig:
|
|
110
|
+
type: object
|
|
111
|
+
description: Cloudflare provider configuration
|
|
112
|
+
required:
|
|
113
|
+
- api_token
|
|
114
|
+
- account_id
|
|
115
|
+
properties:
|
|
116
|
+
api_token:
|
|
117
|
+
type: string
|
|
118
|
+
description: Cloudflare API token with tunnel and DNS permissions
|
|
119
|
+
example: xxxxx
|
|
120
|
+
account_id:
|
|
121
|
+
type: string
|
|
122
|
+
description: Cloudflare account ID
|
|
123
|
+
example: xxxxx
|
|
124
|
+
|
|
125
|
+
HetznerConfig:
|
|
126
|
+
type: object
|
|
127
|
+
description: Hetzner Cloud provider configuration
|
|
128
|
+
required:
|
|
129
|
+
- api_token
|
|
130
|
+
properties:
|
|
131
|
+
api_token:
|
|
132
|
+
type: string
|
|
133
|
+
description: Hetzner Cloud API token
|
|
134
|
+
example: xxxxx
|
|
135
|
+
server_type:
|
|
136
|
+
type: string
|
|
137
|
+
description: Default server type for all server groups
|
|
138
|
+
example: cx22
|
|
139
|
+
server_location:
|
|
140
|
+
type: string
|
|
141
|
+
description: Default datacenter location
|
|
142
|
+
enum: [fsn1, nbg1, hel1, ash, hil]
|
|
143
|
+
example: fsn1
|
|
144
|
+
|
|
145
|
+
AWSConfig:
|
|
146
|
+
type: object
|
|
147
|
+
description: AWS provider configuration
|
|
148
|
+
required:
|
|
149
|
+
- access_key_id
|
|
150
|
+
- secret_access_key
|
|
151
|
+
- region
|
|
152
|
+
properties:
|
|
153
|
+
access_key_id:
|
|
154
|
+
type: string
|
|
155
|
+
description: AWS access key ID
|
|
156
|
+
secret_access_key:
|
|
157
|
+
type: string
|
|
158
|
+
description: AWS secret access key
|
|
159
|
+
region:
|
|
160
|
+
type: string
|
|
161
|
+
description: AWS region
|
|
162
|
+
example: us-east-1
|
|
163
|
+
instance_type:
|
|
164
|
+
type: string
|
|
165
|
+
description: Default EC2 instance type
|
|
166
|
+
example: t3.medium
|
|
167
|
+
|
|
168
|
+
ServerConfig:
|
|
169
|
+
type: object
|
|
170
|
+
description: Server group configuration
|
|
171
|
+
properties:
|
|
172
|
+
master:
|
|
173
|
+
type: boolean
|
|
174
|
+
description: Whether this group contains the K3s master node
|
|
175
|
+
default: false
|
|
176
|
+
type:
|
|
177
|
+
type: string
|
|
178
|
+
description: Server type (overrides compute_provider default)
|
|
179
|
+
example: cx32
|
|
180
|
+
location:
|
|
181
|
+
type: string
|
|
182
|
+
description: Datacenter location (overrides compute_provider default)
|
|
183
|
+
example: fsn1
|
|
184
|
+
count:
|
|
185
|
+
type: integer
|
|
186
|
+
description: Number of servers in this group
|
|
187
|
+
minimum: 1
|
|
188
|
+
default: 1
|
|
189
|
+
example: 2
|
|
190
|
+
|
|
191
|
+
AppServiceConfig:
|
|
192
|
+
type: object
|
|
193
|
+
description: Application service configuration (web, worker, etc.)
|
|
194
|
+
properties:
|
|
195
|
+
servers:
|
|
196
|
+
type: array
|
|
197
|
+
description: Server groups this service runs on
|
|
198
|
+
items:
|
|
199
|
+
type: string
|
|
200
|
+
example: [master]
|
|
201
|
+
domain:
|
|
202
|
+
type: string
|
|
203
|
+
description: Domain for this service (must be on Cloudflare)
|
|
204
|
+
example: example.com
|
|
205
|
+
subdomain:
|
|
206
|
+
type: string
|
|
207
|
+
description: Subdomain for this service (use @ for apex)
|
|
208
|
+
example: www
|
|
209
|
+
port:
|
|
210
|
+
type: integer
|
|
211
|
+
description: Container port to expose
|
|
212
|
+
minimum: 1
|
|
213
|
+
maximum: 65535
|
|
214
|
+
example: 3000
|
|
215
|
+
healthcheck:
|
|
216
|
+
$ref: "#/components/schemas/HealthCheckConfig"
|
|
217
|
+
command:
|
|
218
|
+
type: string
|
|
219
|
+
description: Override container command
|
|
220
|
+
example: bundle exec puma -C config/puma.rb
|
|
221
|
+
pre_run_command:
|
|
222
|
+
type: string
|
|
223
|
+
description: Command to run before deployment (e.g., migrations)
|
|
224
|
+
example: bundle exec rails db:migrate
|
|
225
|
+
env:
|
|
226
|
+
type: object
|
|
227
|
+
description: Service-specific environment variables
|
|
228
|
+
additionalProperties:
|
|
229
|
+
type: string
|
|
230
|
+
volumes:
|
|
231
|
+
type: object
|
|
232
|
+
description: Volume mounts (key is volume name, value is mount path)
|
|
233
|
+
additionalProperties:
|
|
234
|
+
type: string
|
|
235
|
+
example:
|
|
236
|
+
data: /app/data
|
|
237
|
+
uploads: /app/public/uploads
|
|
238
|
+
|
|
239
|
+
HealthCheckConfig:
|
|
240
|
+
type: object
|
|
241
|
+
description: Health check configuration for readiness/liveness probes
|
|
242
|
+
properties:
|
|
243
|
+
type:
|
|
244
|
+
type: string
|
|
245
|
+
description: Health check type
|
|
246
|
+
enum: [http, tcp, exec]
|
|
247
|
+
example: http
|
|
248
|
+
path:
|
|
249
|
+
type: string
|
|
250
|
+
description: HTTP path for health check (type=http)
|
|
251
|
+
example: /health
|
|
252
|
+
port:
|
|
253
|
+
type: integer
|
|
254
|
+
description: Port for health check (defaults to service port)
|
|
255
|
+
example: 3000
|
|
256
|
+
command:
|
|
257
|
+
type: string
|
|
258
|
+
description: Command for exec health check (type=exec)
|
|
259
|
+
example: /bin/healthcheck
|
|
260
|
+
interval:
|
|
261
|
+
type: string
|
|
262
|
+
description: Time between health checks
|
|
263
|
+
example: 10s
|
|
264
|
+
timeout:
|
|
265
|
+
type: string
|
|
266
|
+
description: Health check timeout
|
|
267
|
+
example: 5s
|
|
268
|
+
retries:
|
|
269
|
+
type: integer
|
|
270
|
+
description: Number of retries before marking unhealthy
|
|
271
|
+
minimum: 1
|
|
272
|
+
example: 3
|
|
273
|
+
|
|
274
|
+
DatabaseConfig:
|
|
275
|
+
type: object
|
|
276
|
+
description: Database configuration
|
|
277
|
+
properties:
|
|
278
|
+
servers:
|
|
279
|
+
type: array
|
|
280
|
+
description: Server groups to run database on
|
|
281
|
+
items:
|
|
282
|
+
type: string
|
|
283
|
+
example: [master]
|
|
284
|
+
adapter:
|
|
285
|
+
type: string
|
|
286
|
+
description: Database adapter type
|
|
287
|
+
enum: [postgresql, postgres, mysql, sqlite3]
|
|
288
|
+
example: postgres
|
|
289
|
+
url:
|
|
290
|
+
type: string
|
|
291
|
+
description: Database connection URL (for external databases)
|
|
292
|
+
example: postgres://user:pass@host:5432/dbname
|
|
293
|
+
image:
|
|
294
|
+
type: string
|
|
295
|
+
description: Docker image for database (managed databases only)
|
|
296
|
+
example: postgres:15-alpine
|
|
297
|
+
volume:
|
|
298
|
+
type: string
|
|
299
|
+
description: Volume mount path for data persistence
|
|
300
|
+
example: /var/lib/postgresql/data
|
|
301
|
+
secrets:
|
|
302
|
+
type: object
|
|
303
|
+
description: Database secrets (POSTGRES_PASSWORD, etc.)
|
|
304
|
+
additionalProperties:
|
|
305
|
+
type: string
|
|
306
|
+
example:
|
|
307
|
+
POSTGRES_USER: app
|
|
308
|
+
POSTGRES_PASSWORD: secretpassword
|
|
309
|
+
POSTGRES_DB: app_production
|
|
310
|
+
|
|
311
|
+
ServiceConfig:
|
|
312
|
+
type: object
|
|
313
|
+
description: Additional service configuration (Redis, etc.)
|
|
314
|
+
properties:
|
|
315
|
+
servers:
|
|
316
|
+
type: array
|
|
317
|
+
description: Server groups to run service on
|
|
318
|
+
items:
|
|
319
|
+
type: string
|
|
320
|
+
example: [master]
|
|
321
|
+
image:
|
|
322
|
+
type: string
|
|
323
|
+
description: Docker image for service
|
|
324
|
+
example: redis:7-alpine
|
|
325
|
+
command:
|
|
326
|
+
type: string
|
|
327
|
+
description: Override container command
|
|
328
|
+
example: redis-server --appendonly yes
|
|
329
|
+
env:
|
|
330
|
+
type: object
|
|
331
|
+
description: Service environment variables
|
|
332
|
+
additionalProperties:
|
|
333
|
+
type: string
|
|
334
|
+
volume:
|
|
335
|
+
type: string
|
|
336
|
+
description: Volume mount path for data persistence
|
|
337
|
+
example: /data
|
|
338
|
+
|
|
339
|
+
SSHKeyConfig:
|
|
340
|
+
type: object
|
|
341
|
+
description: SSH key content for server access (auto-generated on first run)
|
|
342
|
+
required:
|
|
343
|
+
- private_key
|
|
344
|
+
- public_key
|
|
345
|
+
properties:
|
|
346
|
+
private_key:
|
|
347
|
+
type: string
|
|
348
|
+
description: Private SSH key content (Ed25519 format, auto-generated)
|
|
349
|
+
example: |
|
|
350
|
+
-----BEGIN OPENSSH PRIVATE KEY-----
|
|
351
|
+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
|
352
|
+
...
|
|
353
|
+
-----END OPENSSH PRIVATE KEY-----
|
|
354
|
+
public_key:
|
|
355
|
+
type: string
|
|
356
|
+
description: Public SSH key content (OpenSSH format, auto-generated)
|
|
357
|
+
example: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... nvoi-deploy
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Example: Apex domain and wildcard subdomain support
|
|
2
|
+
#
|
|
3
|
+
# This example demonstrates three subdomain patterns:
|
|
4
|
+
# - "@" or "" : Apex domain (example.com)
|
|
5
|
+
# - "*" : Wildcard (*.example.com)
|
|
6
|
+
# - "app" : Standard subdomain (app.example.com)
|
|
7
|
+
|
|
8
|
+
application:
|
|
9
|
+
name: apex-wildcard-demo
|
|
10
|
+
environment: production
|
|
11
|
+
|
|
12
|
+
domain_provider:
|
|
13
|
+
cloudflare:
|
|
14
|
+
api_token: $CLOUDFLARE_API_TOKEN
|
|
15
|
+
account_id: $CLOUDFLARE_ACCOUNT_ID
|
|
16
|
+
|
|
17
|
+
compute_provider:
|
|
18
|
+
hetzner:
|
|
19
|
+
api_token: $HETZNER_API_TOKEN
|
|
20
|
+
server_type: cx22
|
|
21
|
+
server_location: fsn1
|
|
22
|
+
|
|
23
|
+
servers:
|
|
24
|
+
master:
|
|
25
|
+
type: cx22
|
|
26
|
+
location: fsn1
|
|
27
|
+
|
|
28
|
+
keep_count: 2
|
|
29
|
+
|
|
30
|
+
app:
|
|
31
|
+
# Apex domain: accessible at example.com (no subdomain)
|
|
32
|
+
# Use "@" or "" for apex/root domain
|
|
33
|
+
main:
|
|
34
|
+
servers: [master]
|
|
35
|
+
domain: example.com
|
|
36
|
+
subdomain: "@" # or use: subdomain: ""
|
|
37
|
+
port: 3000
|
|
38
|
+
healthcheck:
|
|
39
|
+
type: http
|
|
40
|
+
path: /health
|
|
41
|
+
port: 3000
|
|
42
|
+
|
|
43
|
+
# Wildcard subdomain: accessible at *.example.com
|
|
44
|
+
# Catches all subdomains not explicitly defined
|
|
45
|
+
wildcard:
|
|
46
|
+
servers: [master]
|
|
47
|
+
domain: example.com
|
|
48
|
+
subdomain: "*"
|
|
49
|
+
port: 3001
|
|
50
|
+
healthcheck:
|
|
51
|
+
type: http
|
|
52
|
+
path: /health
|
|
53
|
+
port: 3001
|
|
54
|
+
|
|
55
|
+
# Standard subdomain: accessible at api.example.com
|
|
56
|
+
api:
|
|
57
|
+
servers: [master]
|
|
58
|
+
domain: example.com
|
|
59
|
+
subdomain: api
|
|
60
|
+
port: 3002
|
|
61
|
+
healthcheck:
|
|
62
|
+
type: http
|
|
63
|
+
path: /health
|
|
64
|
+
port: 3002
|
|
65
|
+
|
|
66
|
+
env:
|
|
67
|
+
APP_NAME: apex-wildcard-demo
|
|
68
|
+
LOG_LEVEL: info
|