fly.io-rails 0.1.7-x86_64-darwin → 0.1.9-x86_64-darwin
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 +4 -4
- data/README.md +19 -0
- data/exe/x86_64-darwin/flyctl +0 -0
- data/lib/fly.io-rails/actions.rb +116 -71
- data/lib/fly.io-rails/scanner.rb +3 -1
- data/lib/fly.io-rails/utils.rb +2 -0
- data/lib/fly.io-rails/version.rb +1 -1
- data/lib/generators/fly/app_generator.rb +3 -0
- data/lib/generators/fly/terraform_generator.rb +3 -0
- data/lib/generators/templates/Dockerfile.erb +46 -14
- data/lib/generators/templates/fly.rake.erb +35 -6
- data/lib/generators/templates/fly.toml.erb +7 -0
- data/lib/generators/templates/hook_detached_process.erb +1 -5
- data/lib/generators/templates/main.tf.erb +7 -2
- data/lib/generators/templates/nginx.conf.erb +28 -10
- data/lib/tasks/fly.rake +36 -0
- data/lib/tasks/mock.rake +17 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e21d219815cad34716d1d4dc5d9e48eea66c60a68c7bf7f4a3f7865214be5bb
|
4
|
+
data.tar.gz: 1158bbf8df8f47383070cabab7cbd3a6212139a5f52100ec4d9c1695cd097ec9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bc2e74ec196734a511d791c59ddea29c9c4b2121265729f7bfef5a0f5a9e608841137e4ef4510d2f24c74372ff66dada52aad2aecd2d3eed3daf10c2103797a
|
7
|
+
data.tar.gz: 390e7bb1f74ce4cf093182764198f396becff0ed93befab3fbce6ae28fdf0fd92ea0e4c00c0805069609e3704c3f3b6d99af5684c68564f741683cf8954d0090
|
data/README.md
CHANGED
@@ -10,6 +10,25 @@ For usage instructions, see the following guides:
|
|
10
10
|
* [Lite FS](https://fly.io/docs/rails/advanced-guides/litefs/)
|
11
11
|
* [Terraform](https://fly.io/docs/rails/advanced-guides/terraform/)
|
12
12
|
|
13
|
+
## Generator options
|
14
|
+
|
15
|
+
* `--name` name of the application. If a name is not provided, one will be generated for you.
|
16
|
+
* `--org` the organization to operate on. Defaults to `personal`.
|
17
|
+
* `--region` region to launch the application in. Accepts multiple values, and can be specified multiple times.
|
18
|
+
* `--nomad` generates a nomad application instead of a machines application.
|
19
|
+
* `--litefs` adds support for replicated sqlite3 databases via [litefs](https://fly.io/blog/introducing-litefs/). Only works on nomad machines currently.
|
20
|
+
* `--passenger` run your Rails application with [nginx](https://www.nginx.com/) and [Phusion Passenger](https://www.phusionpassenger.com/).
|
21
|
+
* `--serverless` configures your application to exit after 5 minutes of inactivity. Machines will automatically restart when next accessed. Only works with passenger currently.
|
22
|
+
|
23
|
+
## Automatically detected features
|
24
|
+
|
25
|
+
* _ruby_: the deployed application will use the same version of ruby and bundler as your development environment.
|
26
|
+
* _node_: if the use of node is detected, node, yarn, and your npm packages will be installed.
|
27
|
+
* _sqlite3_: if the production database is sqlite3 a volume will be allocated and the database will be put there.
|
28
|
+
* _postgres_: if the production database is postgres a postgres machine will be allocated
|
29
|
+
* _redis_: if redis is used for action cable, caching, or sidekiq your redis database will be added to this application. If you don't currently have a redis database, one will be allocated. If redis is used for caching, eviction will be turned on.
|
30
|
+
* _sidekiq_: if sidekiq is used it will be launched along side of your rails application.
|
31
|
+
|
13
32
|
## Key files
|
14
33
|
|
15
34
|
* Entrypoints: [lib/tasks/fly.rake](./lib/tasks/fly.rake), [lib/generators/app_generator.rb](./lib/generators/app_generator.rb), [lib/generators/terraform_generator.rb](.lib/generators/terraform_generator.rb) contain the deploy task, fly:app generator and
|
data/exe/x86_64-darwin/flyctl
CHANGED
Binary file
|
data/lib/fly.io-rails/actions.rb
CHANGED
@@ -24,6 +24,7 @@ module Fly
|
|
24
24
|
# extract options
|
25
25
|
self.app = app
|
26
26
|
regions = options[:region]&.flatten || []
|
27
|
+
@avahi = options[:avahi]
|
27
28
|
@litefs = options[:litefs]
|
28
29
|
@nomad = options[:nomad]
|
29
30
|
@passenger = options[:passenger]
|
@@ -58,11 +59,43 @@ module Fly
|
|
58
59
|
|
59
60
|
# set additional variables based on application source
|
60
61
|
scan_rails_app
|
62
|
+
@redis = :internal if options[:redis]
|
63
|
+
if File.exist? 'Procfile.fly'
|
64
|
+
@redis = :internal if IO.read('Procfile.fly') =~ /^redis/
|
65
|
+
end
|
66
|
+
|
67
|
+
if options[:anycable] and not @anycable
|
68
|
+
# read and remove original config
|
69
|
+
original_config = YAML.load_file 'config/cable.yml'
|
70
|
+
File.unlink 'config/cable.yml'
|
71
|
+
|
72
|
+
# add and configure anycable-rails
|
73
|
+
say_status :run, 'bundle add anycable-rails'
|
74
|
+
Bundler.with_original_env do
|
75
|
+
system 'bundle add anycable-rails'
|
76
|
+
system 'bin/rails generate anycable:setup --skip-heroku --skip-procfile-dev --skip-jwt --devenv=skip'
|
77
|
+
end
|
78
|
+
|
79
|
+
# insert action_cable_meta_tag
|
80
|
+
insert_into_file 'app/views/layouts/application.html.erb',
|
81
|
+
" <%= action_cable_meta_tag %>\n",
|
82
|
+
after: "<%= csp_meta_tag %>\n"
|
83
|
+
|
84
|
+
# copy production environment to original config
|
85
|
+
anycable_config = YAML.load_file 'config/cable.yml'
|
86
|
+
original_config['production'] = anycable_config['production']
|
87
|
+
File.write 'config/cable.yml', YAML.dump(original_config)
|
88
|
+
|
89
|
+
@anycable = true
|
90
|
+
end
|
61
91
|
|
62
92
|
# determine processes
|
63
93
|
@procs = {web: 'bin/rails server'}
|
64
94
|
@procs[:web] = "nginx -g 'daemon off;'" if @passenger
|
65
95
|
@procs[:worker] = 'bundle exec sidekiq' if @sidekiq
|
96
|
+
@procs[:redis] = 'redis-server /etc/redis/redis.conf' if @redis
|
97
|
+
@procs.merge! 'anycable-rpc': 'bundle exec anycable',
|
98
|
+
'anycable-go': '/usr/local/bin/anycable-go --port=8082' if @anycable
|
66
99
|
end
|
67
100
|
|
68
101
|
def app
|
@@ -143,7 +176,9 @@ module Fly
|
|
143
176
|
end
|
144
177
|
|
145
178
|
def generate_patches
|
146
|
-
if @redis_cable and not
|
179
|
+
if @redis_cable and not @anycable and @redis != :internal and
|
180
|
+
not File.exist? 'config/initializers/action_cable.rb'
|
181
|
+
|
147
182
|
app
|
148
183
|
template 'patches/action_cable.rb', 'config/initializers/action_cable.rb'
|
149
184
|
end
|
@@ -204,7 +239,7 @@ module Fly
|
|
204
239
|
start = Fly::Machines.create_and_start_machine(app, config: config)
|
205
240
|
machine = start[:id]
|
206
241
|
|
207
|
-
if
|
242
|
+
if not machine
|
208
243
|
STDERR.puts 'Error starting release machine'
|
209
244
|
PP.pp start, STDERR
|
210
245
|
exit 1
|
@@ -214,24 +249,27 @@ module Fly
|
|
214
249
|
timeout: 60, state: 'started'
|
215
250
|
|
216
251
|
# wait for release to copmlete
|
217
|
-
status = nil
|
218
252
|
5.times do
|
219
253
|
status = Fly::Machines.wait_for_machine app, machine,
|
220
|
-
timeout: 60, state: 'stopped'
|
221
|
-
|
254
|
+
instance_id: start[:instance_id], timeout: 60, state: 'stopped'
|
255
|
+
break if status[:ok]
|
222
256
|
end
|
223
257
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
258
|
+
if status and status[:ok]
|
259
|
+
event = nil
|
260
|
+
300.times do
|
261
|
+
status = Fly::Machines.get_a_machine app, start[:id]
|
262
|
+
event = status[:events]&.first
|
263
|
+
break if event[:type] == 'exit'
|
264
|
+
sleep 0.2
|
265
|
+
end
|
232
266
|
|
233
|
-
|
234
|
-
|
267
|
+
exit_code = event&.dig(:request, :exit_event, :exit_code)
|
268
|
+
Fly::Machines.delete_machine app, machine if machine
|
269
|
+
return event, exit_code, machine
|
270
|
+
else
|
271
|
+
return status, nil, nil
|
272
|
+
end
|
235
273
|
end
|
236
274
|
|
237
275
|
def launch(app)
|
@@ -263,7 +301,7 @@ module Fly
|
|
263
301
|
end
|
264
302
|
end
|
265
303
|
|
266
|
-
if @redis and not secrets.include? 'REDIS_URL'
|
304
|
+
if @redis and @redis != :internal and not secrets.include? 'REDIS_URL'
|
267
305
|
# Set eviction policy to true if a cache provider, else false.
|
268
306
|
eviction = @redis_cache ? '--enable-eviction' : '--disable-eviction'
|
269
307
|
|
@@ -313,22 +351,30 @@ module Fly
|
|
313
351
|
|
314
352
|
# perform release
|
315
353
|
say_status :fly, release_config[:env]['SERVER_COMMAND']
|
316
|
-
machine = release(app, release_config)
|
317
|
-
Fly::Machines.delete_machine app, machine if machine
|
318
|
-
|
319
|
-
# start proxy, if necessary
|
320
|
-
endpoint = Fly::Machines::fly_api_hostname!
|
354
|
+
event, exit_code, machine = release(app, release_config)
|
321
355
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
system "fly machines remove --force #{list['id']}"
|
328
|
-
end
|
356
|
+
if exit_code != 0
|
357
|
+
STDERR.puts 'Error performing release'
|
358
|
+
STDERR.puts (exit_code ? {exit_code: exit_code} : event).inspect
|
359
|
+
STDERR.puts "run 'flyctl logs --instance #{machine}' for more information"
|
360
|
+
exit 1
|
329
361
|
end
|
330
362
|
end
|
331
363
|
|
364
|
+
# start proxy, if necessary
|
365
|
+
endpoint = Fly::Machines::fly_api_hostname!
|
366
|
+
|
367
|
+
# stop previous instances - list will fail on first run
|
368
|
+
stdout, stderr, status = Open3.capture3('fly machines list --json')
|
369
|
+
unless stdout.empty?
|
370
|
+
JSON.parse(stdout).each do |list|
|
371
|
+
next if list['id'] == machine or list['state'] == 'destroyed'
|
372
|
+
cmd = "fly machines remove --force #{list['id']}"
|
373
|
+
say_status :run, cmd
|
374
|
+
system cmd
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
332
378
|
# configure sqlite3 (can be overridden by fly.toml)
|
333
379
|
if @sqlite3
|
334
380
|
config[:mounts] = [
|
@@ -354,38 +400,52 @@ module Fly
|
|
354
400
|
end
|
355
401
|
|
356
402
|
# start app
|
403
|
+
machines = {}
|
357
404
|
say_status :fly, "start #{app}"
|
358
|
-
|
359
|
-
|
405
|
+
if not toml['processes']
|
406
|
+
start = Fly::Machines.create_and_start_machine(app, config: config)
|
407
|
+
machines['app'] = start[:id]
|
408
|
+
else
|
409
|
+
config[:env] ||= {}
|
410
|
+
toml['processes'].each do |name, entrypoint|
|
411
|
+
config[:env]['SERVER_COMMAND'] = entrypoint
|
412
|
+
start = Fly::Machines.create_and_start_machine(app, config: config)
|
413
|
+
machines[name] = start[:id]
|
414
|
+
end
|
415
|
+
end
|
360
416
|
|
361
|
-
if
|
417
|
+
if machines.empty?
|
362
418
|
STDERR.puts 'Error starting application'
|
363
419
|
PP.pp start, STDERR
|
364
420
|
exit 1
|
365
421
|
end
|
366
422
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
423
|
+
timeout = Time.now + 300
|
424
|
+
while Time.now < timeout and not machines.empty?
|
425
|
+
machines.each do |name, machine|
|
426
|
+
status = Fly::Machines.wait_for_machine app, machine,
|
427
|
+
timeout: 10, status: 'started'
|
428
|
+
machines.delete name if status[:ok]
|
429
|
+
end
|
371
430
|
end
|
372
431
|
|
373
|
-
|
432
|
+
unless machines.empty?
|
433
|
+
STDERR.puts 'Timeout waiting for application to start'
|
434
|
+
end
|
374
435
|
end
|
375
436
|
|
376
437
|
def terraform(app, image)
|
377
|
-
#
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
block.values.first.keys.first == 'fly_machine'}
|
438
|
+
# find first machine using the image ref in terraform config file
|
439
|
+
machine = Fly::HCL.parse(IO.read('main.tf')).
|
440
|
+
map {|block| block.dig(:resource, 'fly_machine')}.compact.
|
441
|
+
find {|machine| machine.values.first[:image] == 'var.image_ref'}
|
442
|
+
if not machine
|
443
|
+
STDERR.puts 'unable to find fly_machine with image = var.image_ref in main.rf'
|
444
|
+
exit 1
|
445
|
+
end
|
386
446
|
|
387
447
|
# extract HCL configuration for the machine
|
388
|
-
config =
|
448
|
+
config = machine.values.first
|
389
449
|
|
390
450
|
# delete HCL specific configuration items
|
391
451
|
%i(services for_each region app name depends_on).each do |key|
|
@@ -407,40 +467,25 @@ module Fly
|
|
407
467
|
config[:env] ||= {}
|
408
468
|
config[:env]['SERVER_COMMAND'] = 'bin/rails fly:release'
|
409
469
|
|
470
|
+
# fill in image
|
471
|
+
config[:image] = image
|
472
|
+
|
410
473
|
# start proxy, if necessary
|
411
474
|
endpoint = Fly::Machines::fly_api_hostname!
|
412
475
|
|
413
|
-
#
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
STDERR.puts 'Error starting release machine'
|
420
|
-
PP.pp start, STDERR
|
421
|
-
exit 1
|
422
|
-
end
|
423
|
-
|
424
|
-
# wait for release to copmlete
|
425
|
-
event = nil
|
426
|
-
90.times do
|
427
|
-
sleep 1
|
428
|
-
status = Fly::Machines.get_a_machine app, machine
|
429
|
-
event = status[:events]&.first
|
430
|
-
break if event && event[:type] == 'exit'
|
476
|
+
# perform release, if necessary
|
477
|
+
if (IO.read('lib/tasks/fly.rake') rescue '') =~ /^\s*task[ \t]*+:?release"?[ \t]*\S/
|
478
|
+
say_status :fly, config[:env]['SERVER_COMMAND']
|
479
|
+
event, exit_code, machine = release(app, config)
|
480
|
+
else
|
481
|
+
exit_code = 0
|
431
482
|
end
|
432
483
|
|
433
|
-
# extract exit code
|
434
|
-
exit_code = event.dig(:request, :exit_event, :exit_code)
|
435
|
-
|
436
484
|
if exit_code == 0
|
437
|
-
# delete release machine
|
438
|
-
Fly::Machines.delete_machine app, machine
|
439
|
-
|
440
485
|
# use terraform apply to deploy
|
441
486
|
ENV['FLY_API_TOKEN'] = `flyctl auth token`.chomp
|
442
487
|
ENV['FLY_HTTP_ENDPOINT'] = endpoint if endpoint
|
443
|
-
system
|
488
|
+
system "terraform apply -auto-approve -var=\"image_ref=#{image}\""
|
444
489
|
else
|
445
490
|
STDERR.puts 'Error performing release'
|
446
491
|
STDERR.puts (exit_code ? {exit_code: exit_code} : event).inspect
|
data/lib/fly.io-rails/scanner.rb
CHANGED
@@ -12,7 +12,9 @@ module Fly
|
|
12
12
|
@postgresql = true
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
gemfile = IO.read('Gemfile') rescue ''
|
16
|
+
@sidekiq = gemfile.include? 'sidekiq'
|
17
|
+
@anycable = gemfile.include? 'anycable'
|
16
18
|
|
17
19
|
@cable = ! Dir['app/channels/*.rb'].empty?
|
18
20
|
|
data/lib/fly.io-rails/utils.rb
CHANGED
data/lib/fly.io-rails/version.rb
CHANGED
@@ -9,7 +9,10 @@ class AppGenerator < Rails::Generators::Base
|
|
9
9
|
class_option :region, type: :array, repeatable: true, default: []
|
10
10
|
class_option :nomad, type: :boolean, default: false
|
11
11
|
|
12
|
+
class_option :anycable, type: :boolean, default: false
|
13
|
+
class_option :avahi, type: :boolean, default: false
|
12
14
|
class_option :litefs, type: :boolean, default: false
|
15
|
+
class_option :redis, type: :boolean, default: false
|
13
16
|
class_option :passenger, type: :boolean, default: false
|
14
17
|
class_option :serverless, type: :boolean, default: false
|
15
18
|
|
@@ -9,6 +9,8 @@ class TerraformGenerator < Rails::Generators::Base
|
|
9
9
|
class_option :region, type: :array, repeatable: true, default: []
|
10
10
|
|
11
11
|
class_option :litefs, type: :boolean, default: false
|
12
|
+
class_option :passenger, type: :boolean, default: false
|
13
|
+
class_option :serverless, type: :boolean, default: false
|
12
14
|
|
13
15
|
def terraform
|
14
16
|
source_paths.push File.expand_path('../templates', __dir__)
|
@@ -20,6 +22,7 @@ class TerraformGenerator < Rails::Generators::Base
|
|
20
22
|
action.generate_toml
|
21
23
|
action.generate_dockerfile
|
22
24
|
action.generate_dockerignore
|
25
|
+
action.generate_nginx_conf
|
23
26
|
action.generate_terraform
|
24
27
|
action.generate_raketask
|
25
28
|
action.generate_procfile
|
@@ -30,9 +30,12 @@ ARG BUNDLER_VERSION=<%= @bundler_version %>
|
|
30
30
|
|
31
31
|
ARG RAILS_ENV=production
|
32
32
|
ENV RAILS_ENV=${RAILS_ENV}
|
33
|
-
|
34
|
-
ENV RAILS_SERVE_STATIC_FILES true
|
33
|
+
<% if @anycable or not @passenger -%>
|
35
34
|
ENV RAILS_LOG_TO_STDOUT true
|
35
|
+
<% end -%>
|
36
|
+
<% unless @passenger -%>
|
37
|
+
ENV RAILS_SERVE_STATIC_FILES true
|
38
|
+
<% end -%>
|
36
39
|
|
37
40
|
ARG BUNDLE_WITHOUT=development:test
|
38
41
|
ARG BUNDLE_PATH=vendor/bundle
|
@@ -81,9 +84,6 @@ RUN gem update --system --no-document && \
|
|
81
84
|
|
82
85
|
COPY Gemfile* ./
|
83
86
|
RUN bundle install && rm -rf vendor/bundle/ruby/*/cache
|
84
|
-
<% if @procs.length > 1 -%>
|
85
|
-
RUN gem install foreman
|
86
|
-
<% end -%>
|
87
87
|
|
88
88
|
<% if @node -%>
|
89
89
|
#######################################################################
|
@@ -113,23 +113,27 @@ FROM flyio/litefs:pr-109 AS litefs
|
|
113
113
|
|
114
114
|
FROM base
|
115
115
|
|
116
|
+
<% if @passenger -%>
|
117
|
+
# add passenger repository
|
118
|
+
RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl && \
|
119
|
+
curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
|
120
|
+
gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg && \
|
121
|
+
sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bullseye main > /etc/apt/sources.list.d/passenger.list'
|
122
|
+
|
123
|
+
<% end -%>
|
116
124
|
<%
|
117
125
|
@deploy_packages = %w(file vim curl gzip)
|
118
126
|
@deploy_packages += %w(nginx passenger libnginx-mod-http-passenger) if @passenger
|
119
127
|
@deploy_packages << 'postgresql-client' if @postgresql
|
120
128
|
@deploy_packages << 'libsqlite3-0' if @sqlite3
|
121
129
|
@deploy_packages << 'fuse' if @litefs
|
130
|
+
@deploy_packages << 'ruby-foreman' if @procs.length > 1
|
131
|
+
@deploy_packages << 'redis-server' if @redis == :internal
|
132
|
+
@deploy_packages += %w(avahi-daemon avahi-utils libnss-mdns) if @avahi
|
122
133
|
-%>
|
123
134
|
ARG DEPLOY_PACKAGES=<%= @deploy_packages.join(' ').inspect %>
|
124
135
|
ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES}
|
125
136
|
|
126
|
-
<% if @passenger -%>
|
127
|
-
RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl && \
|
128
|
-
curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
|
129
|
-
gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg && \
|
130
|
-
sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bullseye main > /etc/apt/sources.list.d/passenger.list'
|
131
|
-
|
132
|
-
<% end -%>
|
133
137
|
RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
|
134
138
|
--mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \
|
135
139
|
apt-get update -qq && \
|
@@ -137,6 +141,17 @@ RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
|
|
137
141
|
${DEPLOY_PACKAGES} \
|
138
142
|
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
139
143
|
|
144
|
+
<% if @anycable -%>
|
145
|
+
# install anycable
|
146
|
+
RUN curl -L https://github.com/anycable/anycable-go/releases/download/v1.2.1/anycable-go-linux-amd64 -o /usr/local/bin/anycable-go && chmod 755 /usr/local/bin/anycable-go
|
147
|
+
|
148
|
+
<% end -%>
|
149
|
+
<% if @redis == :internal -%>
|
150
|
+
# configure redis
|
151
|
+
RUN sed -i 's/^daemonize yes/daemonize no/' /etc/redis/redis.conf &&\
|
152
|
+
sed -i 's/^logfile/# logfile/' /etc/redis/redis.conf
|
153
|
+
|
154
|
+
<% end -%>
|
140
155
|
# copy installed gems
|
141
156
|
COPY --from=gems /app /app
|
142
157
|
COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions
|
@@ -158,15 +173,32 @@ ADD config/litefs.yml /etc/litefs.yml
|
|
158
173
|
RUN mkdir /data
|
159
174
|
<% end -%>
|
160
175
|
#######################################################################
|
176
|
+
<% if @avahi -%>
|
177
|
+
|
178
|
+
# configure avahi for ipv6
|
179
|
+
RUN sed -i 's/mdns4_minimal/mdns_minimal/' /etc/nsswitch.conf
|
180
|
+
<% end -%>
|
161
181
|
<% if @passenger -%>
|
162
182
|
|
163
183
|
# configure nginx/passenger
|
164
184
|
COPY config/nginx.conf /etc/nginx/sites-available/rails.conf
|
165
185
|
RUN rm /etc/nginx/sites-enabled/default && \
|
166
|
-
ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/
|
186
|
+
ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/ && \
|
187
|
+
sed -i 's/user .*;/user root;/' /etc/nginx/nginx.conf && \
|
188
|
+
sed -i '/^include/i include /etc/nginx/main.d/*.conf;' /etc/nginx/nginx.conf && \
|
189
|
+
mkdir /etc/nginx/main.d && \
|
190
|
+
echo 'env RAILS_MASTER_KEY;' >> /etc/nginx/main.d/env.conf &&\
|
191
|
+
<% if @redis -%>
|
192
|
+
echo 'env REDIS_URL;' >> /etc/nginx/main.d/env.conf &&\
|
193
|
+
<% end -%>
|
194
|
+
<% if @anycable -%>
|
195
|
+
echo 'env ANYCABLE_RPC_HOST;' >> /etc/nginx/main.d/env.conf &&\
|
196
|
+
echo 'env CABLE_URL;' >> /etc/nginx/main.d/env.conf &&\
|
197
|
+
<% end -%>
|
198
|
+
echo 'env RAILS_LOG_TO_STDOUT;' >> /etc/nginx/main.d/env.conf
|
167
199
|
<% if @serverless -%>
|
168
200
|
COPY config/hook_detached_process /etc/nginx/
|
169
|
-
<% end -%>
|
201
|
+
<% end -%>
|
170
202
|
<% end -%>
|
171
203
|
|
172
204
|
# Deploy your application
|
@@ -17,20 +17,46 @@ namespace :fly do
|
|
17
17
|
task :release => 'db:migrate'
|
18
18
|
<%- end -%>
|
19
19
|
|
20
|
+
<% end -%>
|
21
|
+
<% if @avahi -%>
|
22
|
+
task :env do
|
23
|
+
<% if @redis -%>
|
24
|
+
ENV['REDIS_URL'] = "redis://#{ENV['FLY_REGION']}-redis.local:6379/1"
|
25
|
+
<% end -%>
|
26
|
+
<% if @anycable -%>
|
27
|
+
ENV['ANYCABLE_RPC_HOST'] = "#{ENV['FLY_REGION']}-anycable-rpc.local:50051"
|
28
|
+
ENV['CABLE_URL'] = "#{ENV['FLY_REGION']}-anycable-go.local"
|
29
|
+
<% end -%>
|
30
|
+
end
|
31
|
+
|
20
32
|
<% end -%>
|
21
33
|
# SERVER step:
|
22
34
|
# - changes to the filesystem made here are deployed
|
23
35
|
# - full access to secrets, databases
|
24
36
|
# - failures here result in VM being stated, shutdown, and rolled back
|
25
37
|
# to last successful deploy (if any).
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
38
|
+
<%= begin
|
39
|
+
deps = [:swapfile]
|
40
|
+
deps << 'db:migrate' if @sqlite3
|
41
|
+
deps = deps.first if deps.length == 1
|
42
|
+
|
43
|
+
if @procs.length > 1 ? ':server, [:formation]' : ':server'
|
44
|
+
"task :server, [:formation] => #{deps.inspect} do |task, args|"
|
45
|
+
else
|
46
|
+
"task :server => #{deps.inspect} do"
|
47
|
+
end
|
48
|
+
end %>
|
31
49
|
<%- if @procs.length > 1 -%>
|
50
|
+
formation = args[:formation] || <%= @procs.keys.map {|key| "#{key}=1"}.join(';').inspect %>
|
51
|
+
formation.gsub! ';', ','
|
52
|
+
<%- if @avahi -%>
|
53
|
+
Rake::Task['fly:avahi_publish'].invoke(formation)
|
54
|
+
<%- end -%>
|
32
55
|
Bundler.with_original_env do
|
33
|
-
|
56
|
+
<%- if @avahi -%>
|
57
|
+
# Rake::Task['fly:env'].invoke
|
58
|
+
<%- end -%>
|
59
|
+
sh "foreman start --procfile=Procfile.fly --formation=#{formation}"
|
34
60
|
end
|
35
61
|
<%- else -%>
|
36
62
|
sh <%= @procs.values.first.inspect %>
|
@@ -53,5 +79,8 @@ namespace :fly do
|
|
53
79
|
sh 'mkswap /swapfile'
|
54
80
|
sh 'echo 10 > /proc/sys/vm/swappiness'
|
55
81
|
sh 'swapon /swapfile'
|
82
|
+
<% if @redis == :internal -%>
|
83
|
+
sh 'echo 1 > /proc/sys/vm/overcommit_memory'
|
84
|
+
<% end -%>
|
56
85
|
end
|
57
86
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
app = "<%= @app %>"
|
2
2
|
kill_signal = "SIGINT"
|
3
3
|
kill_timeout = 5
|
4
|
+
<% unless @avahi -%>
|
4
5
|
processes = []
|
6
|
+
<% end -%>
|
5
7
|
|
6
8
|
[build]
|
7
9
|
[build.args]
|
@@ -23,6 +25,11 @@ processes = []
|
|
23
25
|
<% else -%>
|
24
26
|
DATABASE_URL = "sqlite3:///mnt/volume/production.sqlite3"
|
25
27
|
<% end -%>
|
28
|
+
<% if @avahi -%>
|
29
|
+
|
30
|
+
[processes]
|
31
|
+
app = "bin/rails fly:server[<%= @procs.keys.map {|key| "#{key}=1"}.join(';') %>]"
|
32
|
+
<% end -%>
|
26
33
|
|
27
34
|
[mounts]
|
28
35
|
source = <%= "#{app.gsub('-', '_')}_volume".inspect %>
|
@@ -3,9 +3,5 @@
|
|
3
3
|
status = `passenger-status`
|
4
4
|
|
5
5
|
processes = status[/^Processes\s*:\s*(\d*)/, 1].to_i
|
6
|
-
<% if @cable -%>
|
7
|
-
cable = status[/^<%= @app %>-cable.*?\n\n/m]
|
8
|
-
processes -= 1 if cable and cable =~ /Sessions:\s*[1-9]/
|
9
|
-
<% end -%>
|
10
6
|
|
11
|
-
system 'nginx -s stop' if processes == 0
|
7
|
+
system 'nginx -s stop' if processes == 0
|
@@ -2,11 +2,16 @@ terraform {
|
|
2
2
|
required_providers {
|
3
3
|
fly = {
|
4
4
|
source = "fly-apps/fly"
|
5
|
-
version = "0.0.
|
5
|
+
version = "0.0.20"
|
6
6
|
}
|
7
7
|
}
|
8
8
|
}
|
9
9
|
|
10
|
+
variable "image_ref" {
|
11
|
+
type = string
|
12
|
+
description = "docker images containing the application"
|
13
|
+
}
|
14
|
+
|
10
15
|
/* uncomment if you want an internal tunnel
|
11
16
|
provider "fly" {
|
12
17
|
useinternaltunnel = true
|
@@ -49,7 +54,7 @@ resource "fly_machine" "<%= @appName %>Machine" {
|
|
49
54
|
|
50
55
|
app = <%= @app.inspect %>
|
51
56
|
name = "<%= @app %>-${each.value}"
|
52
|
-
image =
|
57
|
+
image = var.image_ref
|
53
58
|
|
54
59
|
# Scale application resources
|
55
60
|
cpus = 1
|
@@ -4,26 +4,44 @@ passenger_min_instances 0;
|
|
4
4
|
passenger_pool_idle_time 300;
|
5
5
|
|
6
6
|
<% end -%>
|
7
|
+
passenger_log_file /dev/stdout;
|
8
|
+
passenger_default_user root;
|
9
|
+
|
7
10
|
server {
|
8
|
-
listen 8080;
|
11
|
+
listen 8080 default_server;
|
12
|
+
listen [::]:8080 default_server;
|
9
13
|
server_name <%= @app %>.fly.dev;
|
10
14
|
root /app/public;
|
11
15
|
|
16
|
+
access_log /dev/stdout;
|
17
|
+
error_log /dev/stdout info;
|
18
|
+
|
12
19
|
passenger_enabled on;
|
13
20
|
passenger_ruby /usr/lib/fullstaq-ruby/versions/<%= @ruby_version %>-jemalloc/bin/ruby;
|
14
21
|
|
15
|
-
<% if @
|
16
|
-
location / {
|
17
|
-
|
18
|
-
|
22
|
+
<% if @anycable -%>
|
23
|
+
location /cable {
|
24
|
+
proxy_pass http://localhost:8082/cable;
|
25
|
+
proxy_http_version 1.1;
|
26
|
+
proxy_set_header Upgrade $http_upgrade;
|
27
|
+
proxy_set_header Connection "Upgrade";
|
28
|
+
proxy_set_header Host $host;
|
29
|
+
}
|
19
30
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
31
|
+
<% elsif @cable -%>
|
32
|
+
location /cable {
|
33
|
+
passenger_app_group_name <%= @app %>-cable;
|
34
|
+
passenger_force_max_concurrent_requests_per_process 0;
|
35
|
+
}
|
24
36
|
|
25
37
|
<% end -%>
|
38
|
+
location / {
|
39
|
+
passenger_app_group_name <%= @app %>;
|
40
|
+
passenger_env_var RAILS_SERVE_STATIC_FILES true;
|
41
|
+
passenger_env_var RAILS_LOG_TO_STDOUT true;
|
42
|
+
}
|
43
|
+
|
26
44
|
# Nginx has a default limit of 1 MB for request bodies, which also applies
|
27
45
|
# to file uploads. The following line enables uploads of up to 50 MB:
|
28
46
|
client_max_body_size 50M;
|
29
|
-
}
|
47
|
+
}
|
data/lib/tasks/fly.rake
CHANGED
@@ -37,6 +37,42 @@ namespace :fly do
|
|
37
37
|
action.generate_ipv6 if @app
|
38
38
|
action.deploy(app, image)
|
39
39
|
end
|
40
|
+
|
41
|
+
JSON.parse(`fly apps list --json`).each do |info|
|
42
|
+
if info['Name'] == app
|
43
|
+
60.times do
|
44
|
+
response = Net::HTTP.get_response(URI::HTTPS.build(host: info['Hostname']))
|
45
|
+
puts "Server status: #{response.code} #{response.message}"
|
46
|
+
break
|
47
|
+
rescue Errno::ECONNRESET
|
48
|
+
sleep 0.5
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'dbus daemon - used for IPC'
|
55
|
+
task :dbus_deamon do
|
56
|
+
IO.write '/var/lib/dbus/machine-id', `hostname`
|
57
|
+
mkdir_p '/var/run/dbus'
|
58
|
+
sh 'dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address'
|
59
|
+
end
|
60
|
+
|
61
|
+
desc 'Zeroconf/avahi/bonjour discovery'
|
62
|
+
task :avahi_publish, [:formation] => :dbus_deamon do |task, args|
|
63
|
+
pids = []
|
64
|
+
pids << spawn('avahi-daemon')
|
65
|
+
sleep 0.1
|
66
|
+
|
67
|
+
ip = IPSocket.getaddress(Socket.gethostname)
|
68
|
+
args[:formation].scan(/([-\w]+)=(\d+)/).each do |name, count|
|
69
|
+
next if count.to_i == 0
|
70
|
+
pids << spawn("avahi-publish -a -R #{ENV['FLY_REGION']}-#{name}.local #{ip}")
|
71
|
+
end
|
72
|
+
|
73
|
+
at_exit do
|
74
|
+
pids.each {|pid| Process.kill 7, pid}
|
75
|
+
end
|
40
76
|
end
|
41
77
|
end
|
42
78
|
|
data/lib/tasks/mock.rake
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/handler/puma'
|
3
|
+
|
4
|
+
namespace :mock do
|
5
|
+
desc 'Mock server - useful for debugging startup issues'
|
6
|
+
task :server do
|
7
|
+
handler = Rack::Handler::Puma
|
8
|
+
|
9
|
+
class RackApp
|
10
|
+
def call(env)
|
11
|
+
[200, {"Content-Type" => "text/plain"}, ["Hello from Fly.io"]]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
handler.run RackApp.new, Port: ENV['PORT'] || 8080
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fly.io-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Sam Ruby
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fly-ruby
|
@@ -74,11 +74,12 @@ files:
|
|
74
74
|
- lib/generators/templates/nginx.conf.erb
|
75
75
|
- lib/generators/templates/patches/action_cable.rb
|
76
76
|
- lib/tasks/fly.rake
|
77
|
-
|
77
|
+
- lib/tasks/mock.rake
|
78
|
+
homepage: https://github.com/rubys/fly.io-rails
|
78
79
|
licenses:
|
79
80
|
- Apache-2.0
|
80
81
|
metadata:
|
81
|
-
homepage_uri: https://github.com/rubys/fly-
|
82
|
+
homepage_uri: https://github.com/rubys/fly.io-rails
|
82
83
|
post_install_message:
|
83
84
|
rdoc_options: []
|
84
85
|
require_paths:
|