fly-rails 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +100 -0
- data/Rakefile +3 -0
- data/lib/fly-rails/actions.rb +652 -0
- data/lib/fly-rails/deploy.rb +42 -0
- data/lib/fly-rails/dsl.rb +92 -0
- data/lib/fly-rails/generators.rb +3 -0
- data/lib/fly-rails/hcl.rb +99 -0
- data/lib/fly-rails/machines.rb +209 -0
- data/lib/fly-rails/platforms.rb +10 -0
- data/lib/fly-rails/scanner.rb +68 -0
- data/lib/fly-rails/utils.rb +66 -0
- data/lib/fly-rails/version.rb +3 -0
- data/lib/fly-rails.rb +27 -0
- data/lib/generators/fly/app_generator.rb +72 -0
- data/lib/generators/fly/config_generator.rb +19 -0
- data/lib/generators/fly/terraform_generator.rb +36 -0
- data/lib/generators/templates/Dockerfile.erb +270 -0
- data/lib/generators/templates/Procfile.fly.erb +3 -0
- data/lib/generators/templates/dockerignore.erb +16 -0
- data/lib/generators/templates/fly.rake.erb +101 -0
- data/lib/generators/templates/fly.rb.erb +27 -0
- data/lib/generators/templates/fly.toml.erb +81 -0
- data/lib/generators/templates/hook_detached_process.erb +7 -0
- data/lib/generators/templates/litefs.yml.erb +14 -0
- data/lib/generators/templates/main.tf.erb +101 -0
- data/lib/generators/templates/nginx.conf.erb +77 -0
- data/lib/generators/templates/patches/action_cable.rb +20 -0
- data/lib/tasks/fly.rake +178 -0
- data/lib/tasks/mock.rake +17 -0
- metadata +87 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fly-rails/actions'
|
2
|
+
|
3
|
+
module Fly::Generators
|
4
|
+
class TerraformGenerator < Rails::Generators::Base
|
5
|
+
include FlyIoRails::Utils
|
6
|
+
|
7
|
+
class_option :name, type: :string, required: false
|
8
|
+
class_option :org, type: :string, default: 'personal'
|
9
|
+
class_option :region, type: :array, repeatable: true, default: []
|
10
|
+
|
11
|
+
class_option :litefs, type: :boolean, default: false
|
12
|
+
class_option :passenger, type: :boolean, default: false
|
13
|
+
class_option :serverless, type: :boolean, default: false
|
14
|
+
|
15
|
+
def terraform
|
16
|
+
source_paths.push File.expand_path('../templates', __dir__)
|
17
|
+
|
18
|
+
create_app(**options.symbolize_keys)
|
19
|
+
|
20
|
+
action = Fly::Actions.new(@app, options)
|
21
|
+
|
22
|
+
action.generate_toml
|
23
|
+
action.generate_dockerfile
|
24
|
+
action.generate_dockerignore
|
25
|
+
action.generate_nginx_conf
|
26
|
+
action.generate_terraform
|
27
|
+
action.generate_raketask
|
28
|
+
action.generate_procfile
|
29
|
+
action.generate_patches
|
30
|
+
|
31
|
+
action.generate_key
|
32
|
+
|
33
|
+
tee 'terraform init'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
# syntax = docker/dockerfile:1
|
2
|
+
|
3
|
+
FROM <%= @image %> as base
|
4
|
+
LABEL fly_launch_runtime="rails"
|
5
|
+
|
6
|
+
ENV RAILS_ENV=production
|
7
|
+
<% if @anycable or not @passenger -%>
|
8
|
+
ENV RAILS_LOG_TO_STDOUT true
|
9
|
+
<% end -%>
|
10
|
+
<% unless @passenger -%>
|
11
|
+
ENV RAILS_SERVE_STATIC_FILES true
|
12
|
+
<% end -%>
|
13
|
+
ENV PORT 8080
|
14
|
+
|
15
|
+
RUN mkdir /app
|
16
|
+
WORKDIR /app
|
17
|
+
|
18
|
+
<% if @node -%>
|
19
|
+
RUN curl https://get.volta.sh | bash
|
20
|
+
ENV VOLTA_HOME /root/.volta
|
21
|
+
ENV PATH $VOLTA_HOME/bin:/usr/local/bin:$PATH
|
22
|
+
RUN volta install node@<%= @node_version %> yarn@<%= @yarn_version %> && \
|
23
|
+
gem update --system --no-document && \
|
24
|
+
gem install --no-document bundler --version <%= @bundler_version %>
|
25
|
+
|
26
|
+
<% else -%>
|
27
|
+
RUN gem update --system --no-document && \
|
28
|
+
gem install --no-document bundler --version <%= @bundler_version %>
|
29
|
+
|
30
|
+
<% end -%>
|
31
|
+
#######################################################################
|
32
|
+
|
33
|
+
# install packages only needed at build time
|
34
|
+
|
35
|
+
FROM base as build_deps
|
36
|
+
|
37
|
+
<%
|
38
|
+
@build_packages = %w(git build-essential wget curl gzip xz-utils)
|
39
|
+
@build_packages << 'libpq-dev' if @postgresql
|
40
|
+
@build_packages << 'libsqlite3-dev' if @sqlite3
|
41
|
+
@build_packages << 'default-libmysqlclient-dev' if @mysql
|
42
|
+
@build_packages += %w[pkg-config libmagickwand-dev] if @rmagick
|
43
|
+
-%>
|
44
|
+
RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
|
45
|
+
--mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
|
46
|
+
apt-get update -qq && \
|
47
|
+
apt-get install --no-install-recommends --yes \
|
48
|
+
<%= @build_packages.join(' ') %>
|
49
|
+
|
50
|
+
#######################################################################
|
51
|
+
|
52
|
+
# install gems
|
53
|
+
|
54
|
+
FROM build_deps as gems
|
55
|
+
|
56
|
+
COPY Gemfile* ./
|
57
|
+
RUN --mount=type=cache,id=dev-gem-cache,sharing=locked,target=/srv/vendor \
|
58
|
+
bundle config set app_config .bundle && \
|
59
|
+
bundle config set without 'development test' && \
|
60
|
+
bundle lock --add-platform x86_64-linux && \
|
61
|
+
bundle config set path /srv/vendor && \
|
62
|
+
bundle install && \
|
63
|
+
mkdir -p vendor && \
|
64
|
+
bundle config set path vendor && \
|
65
|
+
cp -ar /srv/vendor .
|
66
|
+
|
67
|
+
<% if @node -%>
|
68
|
+
#######################################################################
|
69
|
+
|
70
|
+
# install node modules
|
71
|
+
|
72
|
+
FROM build_deps as node_modules
|
73
|
+
|
74
|
+
<% if @puppeteer -%>
|
75
|
+
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
|
76
|
+
|
77
|
+
<% end -%>
|
78
|
+
COPY package*json ./
|
79
|
+
<% if @yarn -%>
|
80
|
+
COPY yarn.* ./
|
81
|
+
RUN yarn install
|
82
|
+
<% else -%>
|
83
|
+
RUN npm install
|
84
|
+
<% end -%>
|
85
|
+
|
86
|
+
<% end -%>
|
87
|
+
#######################################################################
|
88
|
+
<% if @litefs -%>
|
89
|
+
|
90
|
+
# Fetch the LiteFS binary
|
91
|
+
FROM flyio/litefs:pr-109 AS litefs
|
92
|
+
|
93
|
+
#######################################################################
|
94
|
+
<% end -%>
|
95
|
+
<% if @anycable -%>
|
96
|
+
|
97
|
+
# Build anycable
|
98
|
+
FROM golang:1.18 as go
|
99
|
+
RUN GOBIN=/usr/local/bin/ go install github.com/anycable/anycable-go/cmd/anycable-go@latest
|
100
|
+
|
101
|
+
#######################################################################
|
102
|
+
<% end -%>
|
103
|
+
|
104
|
+
# install deployment packages
|
105
|
+
|
106
|
+
FROM base
|
107
|
+
|
108
|
+
<% if @passenger -%>
|
109
|
+
# add passenger repository
|
110
|
+
RUN apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl && \
|
111
|
+
curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | \
|
112
|
+
gpg --dearmor > /etc/apt/trusted.gpg.d/phusion.gpg && \
|
113
|
+
sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger $(sed -n 's/VERSION_CODENAME=\(.*\)$/\1/p' /etc/os-release) main > /etc/apt/sources.list.d/passenger.list'
|
114
|
+
|
115
|
+
<% end -%>
|
116
|
+
<% if @puppeteer -%>
|
117
|
+
# add google chrome repository
|
118
|
+
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
|
119
|
+
&& echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
|
120
|
+
|
121
|
+
<% end -%>
|
122
|
+
<% if @postgresql -%>
|
123
|
+
# add postgres repository
|
124
|
+
RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
|
125
|
+
&& echo "deb http://apt.postgresql.org/pub/repos/apt/ $(sed -n 's/VERSION_CODENAME=\(.*\)$/\1/p' /etc/os-release)-pgdg main" 14 > /etc/apt/sources.list.d/pgdg.list
|
126
|
+
<% end -%>
|
127
|
+
# nginx: <%= @nginx.inspect %>
|
128
|
+
<%
|
129
|
+
@deploy_packages = []
|
130
|
+
@deploy_packages << 'nginx' if @nginx
|
131
|
+
@deploy_packages += %w(passenger libnginx-mod-http-passenger) if @passenger
|
132
|
+
@deploy_packages << 'postgresql-client-14' if @postgresql
|
133
|
+
@deploy_packages << 'libsqlite3-0' if @sqlite3
|
134
|
+
@deploy_packages << 'default-mysql-client' if @mysql
|
135
|
+
@deploy_packages << 'google-chrome-stable' if @puppeteer
|
136
|
+
@deploy_packages << 'imagemagick' if @rmagick
|
137
|
+
@deploy_packages << 'libvips42' if @image_processing
|
138
|
+
@deploy_packages << 'nodejs' if not @node and @bootstrap
|
139
|
+
@deploy_packages << 'fuse' if @litefs
|
140
|
+
@deploy_packages << 'ruby-foreman' if @procs.length > 1
|
141
|
+
@deploy_packages << 'redis-server' if @redis == :internal
|
142
|
+
@deploy_packages << 'gettext-base' if @nats
|
143
|
+
@deploy_packages += %w(avahi-daemon avahi-utils libnss-mdns) if @avahi
|
144
|
+
-%>
|
145
|
+
RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
|
146
|
+
--mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \
|
147
|
+
apt-get update -qq && \
|
148
|
+
apt-get install --no-install-recommends --yes \
|
149
|
+
<%= @deploy_packages.join(' ') %>
|
150
|
+
|
151
|
+
<% if @redis == :internal -%>
|
152
|
+
# configure redis
|
153
|
+
RUN sed -i 's/^daemonize yes/daemonize no/' /etc/redis/redis.conf &&\
|
154
|
+
sed -i 's/^bind/# bind/' /etc/redis/redis.conf &&\
|
155
|
+
sed -i 's/^protected-mode yes/protected-mode no/' /etc/redis/redis.conf &&\
|
156
|
+
sed -i 's/^logfile/# logfile/' /etc/redis/redis.conf
|
157
|
+
|
158
|
+
<% end -%>
|
159
|
+
# copy installed gems
|
160
|
+
COPY --from=gems /app /app
|
161
|
+
COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions
|
162
|
+
COPY --from=gems /usr/local/bundle /usr/local/bundle
|
163
|
+
|
164
|
+
<% if @node -%>
|
165
|
+
# copy installed node modules
|
166
|
+
COPY --from=node_modules /app/node_modules /app/node_modules
|
167
|
+
|
168
|
+
<% end -%>
|
169
|
+
<% if @anycable -%>
|
170
|
+
# copy anycable-go
|
171
|
+
COPY --from=go /usr/local/bin/anycable-go /usr/local/bin/anycable-go
|
172
|
+
|
173
|
+
<% end -%>
|
174
|
+
<% if @litefs -%>
|
175
|
+
# copy litefs binary
|
176
|
+
COPY --from=litefs /usr/local/bin/litefs /usr/local/bin/litefs
|
177
|
+
|
178
|
+
# Copy our LiteFS configuration.
|
179
|
+
ADD config/litefs.yml /etc/litefs.yml
|
180
|
+
|
181
|
+
# Create mount point
|
182
|
+
RUN mkdir /data
|
183
|
+
|
184
|
+
<% end -%>
|
185
|
+
<% if @nats -%>
|
186
|
+
# install nats
|
187
|
+
RUN mkdir /etc/nats
|
188
|
+
COPY --from=nats:latest /nats-server /usr/local/bin/nats-server
|
189
|
+
COPY --from=nats:latest /nats-server.conf /etc/nats/nats-server.conf
|
190
|
+
|
191
|
+
<% end -%>
|
192
|
+
#######################################################################
|
193
|
+
<% if @avahi -%>
|
194
|
+
|
195
|
+
# configure avahi for ipv6
|
196
|
+
RUN sed -i 's/mdns4_minimal/mdns_minimal/' /etc/nsswitch.conf
|
197
|
+
<% end -%>
|
198
|
+
<% if @nginx -%>
|
199
|
+
<% if @passenger -%>
|
200
|
+
|
201
|
+
# configure nginx/passenger
|
202
|
+
<% if @passenger -%>
|
203
|
+
<% unless @avahi or @nats -%>
|
204
|
+
COPY config/nginx.conf /etc/nginx/sites-available/rails.conf
|
205
|
+
<% end -%>
|
206
|
+
RUN rm /etc/nginx/sites-enabled/default && \
|
207
|
+
ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/ && \
|
208
|
+
sed -i 's/user .*;/user root;/' /etc/nginx/nginx.conf && \
|
209
|
+
sed -i '/^include/i include /etc/nginx/main.d/*.conf;' /etc/nginx/nginx.conf && \
|
210
|
+
mkdir /etc/nginx/main.d && \
|
211
|
+
echo 'env RAILS_MASTER_KEY;' >> /etc/nginx/main.d/env.conf &&\
|
212
|
+
<% if @redis -%>
|
213
|
+
echo 'env REDIS_URL;' >> /etc/nginx/main.d/env.conf &&\
|
214
|
+
<% end -%>
|
215
|
+
<% if @anycable -%>
|
216
|
+
echo 'env ANYCABLE_RPC_HOST;' >> /etc/nginx/main.d/env.conf &&\
|
217
|
+
echo 'env CABLE_URL;' >> /etc/nginx/main.d/env.conf &&\
|
218
|
+
<% end -%>
|
219
|
+
echo 'env RAILS_LOG_TO_STDOUT;' >> /etc/nginx/main.d/env.conf
|
220
|
+
<% if @serverless -%>
|
221
|
+
COPY config/hook_detached_process /etc/nginx/
|
222
|
+
<% end -%>
|
223
|
+
<% end -%>
|
224
|
+
<% else -%>
|
225
|
+
|
226
|
+
# configure nginx/passenger
|
227
|
+
COPY <<-"EOF" /etc/nginx/sites-available/rails.conf
|
228
|
+
<%= render 'nginx.conf.erb' %>
|
229
|
+
EOF
|
230
|
+
RUN rm /etc/nginx/sites-enabled/default && \
|
231
|
+
ln -s /etc/nginx/sites-available/rails.conf /etc/nginx/sites-enabled/
|
232
|
+
<% end -%>
|
233
|
+
<% end -%>
|
234
|
+
|
235
|
+
<% if @procs.length > 1 and not @eject -%>
|
236
|
+
# Define processes
|
237
|
+
COPY <<-"EOF" ./Procfile.fly
|
238
|
+
<%= render 'Procfile.fly.erb' %>
|
239
|
+
EOF
|
240
|
+
|
241
|
+
<% end -%>
|
242
|
+
<% unless @eject -%>
|
243
|
+
# Define tasks
|
244
|
+
COPY <<-"EOF" ./lib/tasks/fly.rake
|
245
|
+
<%= render 'fly.rake.erb' %>
|
246
|
+
EOF
|
247
|
+
|
248
|
+
<% end -%>
|
249
|
+
# Deploy your application
|
250
|
+
COPY . .
|
251
|
+
<% if @bundle_add -%>
|
252
|
+
COPY --from=gems /app/Gemfile* ./
|
253
|
+
<% end -%>
|
254
|
+
|
255
|
+
# Adjust binstubs to run on Linux and set current working directory
|
256
|
+
RUN chmod +x /app/bin/* && \
|
257
|
+
sed -i 's/ruby.exe/ruby\r*/' /app/bin/* && \
|
258
|
+
sed -i '/^#!/aDir.chdir File.expand_path("..", __dir__)' /app/bin/*
|
259
|
+
|
260
|
+
# Run build task defined in config/fly.rb
|
261
|
+
RUN SECRET_KEY_BASE=1 bin/rails fly:build
|
262
|
+
|
263
|
+
# Start server
|
264
|
+
<% if @litefs
|
265
|
+
@server_command="litefs"
|
266
|
+
else
|
267
|
+
@server_command="bin/rails fly:server"
|
268
|
+
end
|
269
|
+
-%>
|
270
|
+
CMD <%= @server_command.split(' ').inspect %>
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# commands used to deploy a Rails application
|
2
|
+
namespace :fly do
|
3
|
+
# BUILD step:
|
4
|
+
# - changes to the filesystem made here DO get deployed
|
5
|
+
# - NO access to secrets, volumes, databases
|
6
|
+
# - Failures here prevent deployment
|
7
|
+
task :build => 'assets:precompile'
|
8
|
+
|
9
|
+
<% unless @litefs -%>
|
10
|
+
# RELEASE step:
|
11
|
+
# - changes to the filesystem made here are DISCARDED
|
12
|
+
# - full access to secrets, databases
|
13
|
+
# - failures here prevent deployment
|
14
|
+
<%- if @sqlite3 -%>
|
15
|
+
task :release
|
16
|
+
<%- else -%>
|
17
|
+
task :release => 'db:migrate'
|
18
|
+
<%- end -%>
|
19
|
+
|
20
|
+
<% end -%>
|
21
|
+
<% if @avahi or @nats -%>
|
22
|
+
task :env do
|
23
|
+
<% if @redis -%>
|
24
|
+
if ENV['NATS_SERVER']
|
25
|
+
redis_host = "#{ENV['FLY_REGION']}-redis.local"
|
26
|
+
else
|
27
|
+
redis_host = 'localhost'
|
28
|
+
end
|
29
|
+
|
30
|
+
ENV['REDIS_URL'] = "redis://#{redis_host}:6379/1"
|
31
|
+
<% end -%>
|
32
|
+
<% if @anycable -%>
|
33
|
+
ENV['ANYCABLE_GO_RPC_HOST'] = "#{ENV['FLY_REGION']}-anycable-rpc.local:50051"
|
34
|
+
<% end -%>
|
35
|
+
end
|
36
|
+
|
37
|
+
<% end -%>
|
38
|
+
# SERVER step:
|
39
|
+
# - changes to the filesystem made here are deployed
|
40
|
+
# - full access to secrets, databases
|
41
|
+
# - failures here result in VM being stated, shutdown, and rolled back
|
42
|
+
# to last successful deploy (if any).
|
43
|
+
<%= begin
|
44
|
+
deps = [:swapfile]
|
45
|
+
deps << 'db:migrate' if @sqlite3
|
46
|
+
deps = deps.first if deps.length == 1
|
47
|
+
|
48
|
+
if @procs.length > 1 and (@avahi or @nats)
|
49
|
+
"task :server, [:formation] => #{deps.inspect} do |task, args|"
|
50
|
+
else
|
51
|
+
"task :server => #{deps.inspect} do"
|
52
|
+
end
|
53
|
+
end %>
|
54
|
+
rm_f 'tmp/pids/server.pid' if File.exist? 'tmp/pids/server.pid'
|
55
|
+
<%- if @procs.length > 1 -%>
|
56
|
+
<%- if @avahi or @nats -%>
|
57
|
+
<%- if @passenger -%>
|
58
|
+
sh 'envsubst < config/nginx.conf > /etc/nginx/sites-available/rails.conf'
|
59
|
+
<%- end -%>
|
60
|
+
formation = args[:formation].gsub!(';', ',')
|
61
|
+
<%- if @avahi -%>
|
62
|
+
Rake::Task['fly:avahi_publish'].invoke(formation)
|
63
|
+
<%- end -%>
|
64
|
+
<%- if @nats -%>
|
65
|
+
Rake::Task['fly:nats_publish'].invoke(formation) if ENV['NATS_SERVER']
|
66
|
+
<%- end -%>
|
67
|
+
Bundler.with_original_env do
|
68
|
+
Rake::Task['fly:env'].invoke
|
69
|
+
sh "foreman start --procfile=Procfile.fly --formation=#{formation}"
|
70
|
+
end
|
71
|
+
<%- else -%>
|
72
|
+
Bundler.with_original_env do
|
73
|
+
sh "foreman start --procfile=Procfile.fly"
|
74
|
+
end
|
75
|
+
<%- end -%>
|
76
|
+
<%- else -%>
|
77
|
+
sh <%= @procs.values.first.inspect %>
|
78
|
+
<%- end -%>
|
79
|
+
end
|
80
|
+
|
81
|
+
# optional SWAPFILE task:
|
82
|
+
# - adjust fallocate size as needed
|
83
|
+
# - performance critical applications should scale memory to the
|
84
|
+
# point where swap is rarely used. 'fly scale help' for details.
|
85
|
+
# - disable by removing dependency on the :server task, thus:
|
86
|
+
<%- if @sqlite3 -%>
|
87
|
+
# task :server => 'db:migrate' do
|
88
|
+
<%- else -%>
|
89
|
+
# task :server do
|
90
|
+
<%- end -%>
|
91
|
+
task :swapfile do
|
92
|
+
sh 'fallocate -l 512M /swapfile'
|
93
|
+
sh 'chmod 0600 /swapfile'
|
94
|
+
sh 'mkswap /swapfile'
|
95
|
+
sh 'echo 10 > /proc/sys/vm/swappiness'
|
96
|
+
sh 'swapon /swapfile'
|
97
|
+
<% if @redis == :internal -%>
|
98
|
+
sh 'echo 1 > /proc/sys/vm/overcommit_memory'
|
99
|
+
<% end -%>
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
image <%= @image.inspect %>
|
2
|
+
|
3
|
+
machine do
|
4
|
+
cpus 1
|
5
|
+
cpu_kind 'shared'
|
6
|
+
memory_mb 256
|
7
|
+
end
|
8
|
+
<% if @sqlite3 -%>
|
9
|
+
|
10
|
+
sqlite3 do
|
11
|
+
size 3
|
12
|
+
end
|
13
|
+
<% end -%>
|
14
|
+
<% if @postgresql -%>
|
15
|
+
|
16
|
+
postgres do
|
17
|
+
vm_size 'shared-cpu-1x'
|
18
|
+
volume_size 1
|
19
|
+
initial_cluster_size 1
|
20
|
+
end
|
21
|
+
<% end -%>
|
22
|
+
<% if @redis -%>
|
23
|
+
|
24
|
+
redis do
|
25
|
+
plan "Free"
|
26
|
+
end
|
27
|
+
<% end -%>
|
@@ -0,0 +1,81 @@
|
|
1
|
+
app = "<%= @app %>"
|
2
|
+
<% if @nomad -%>
|
3
|
+
kill_signal = "SIGINT"
|
4
|
+
kill_timeout = 5
|
5
|
+
<% unless @avahi or @nats -%>
|
6
|
+
processes = []
|
7
|
+
<% end -%>
|
8
|
+
|
9
|
+
[build]
|
10
|
+
[build.args]
|
11
|
+
BUILD_COMMAND = "bin/rails fly:build"
|
12
|
+
<% if @litefs -%>
|
13
|
+
SERVER_COMMAND = "litefs"
|
14
|
+
<% else -%>
|
15
|
+
SERVER_COMMAND = "bin/rails fly:server"
|
16
|
+
|
17
|
+
[deploy]
|
18
|
+
release_command = "bin/rails fly:release"
|
19
|
+
<% end -%>
|
20
|
+
|
21
|
+
[env]
|
22
|
+
PORT = "8080"
|
23
|
+
<% if @sqlite3 -%>
|
24
|
+
<% if @litefs -%>
|
25
|
+
DATABASE_URL = "sqlite3:///data/production.sqlite3"
|
26
|
+
<% else -%>
|
27
|
+
DATABASE_URL = "sqlite3:///mnt/volume/production.sqlite3"
|
28
|
+
<% end -%>
|
29
|
+
<% if @avahi or @nats -%>
|
30
|
+
|
31
|
+
[processes]
|
32
|
+
app = "bin/rails fly:server[<%= @procs.keys.map {|key| "#{key}=1"}.join(';') %>]"
|
33
|
+
<% end -%>
|
34
|
+
|
35
|
+
[mounts]
|
36
|
+
source = <%= "#{app.gsub('-', '_')}_volume".inspect %>
|
37
|
+
destination = "/mnt/volume"
|
38
|
+
<% end -%>
|
39
|
+
|
40
|
+
[experimental]
|
41
|
+
allowed_public_ports = []
|
42
|
+
auto_rollback = true
|
43
|
+
<% if @litefs -%>
|
44
|
+
enable_consul = true
|
45
|
+
<% end -%>
|
46
|
+
|
47
|
+
[[services]]
|
48
|
+
http_checks = []
|
49
|
+
internal_port = 8080
|
50
|
+
processes = ["app"]
|
51
|
+
protocol = "tcp"
|
52
|
+
script_checks = []
|
53
|
+
[services.concurrency]
|
54
|
+
<% if @cable -%>
|
55
|
+
hard_limit = 2500
|
56
|
+
soft_limit = 2000
|
57
|
+
<% else -%>
|
58
|
+
hard_limit = 25
|
59
|
+
soft_limit = 20
|
60
|
+
<% end -%>
|
61
|
+
type = "connections"
|
62
|
+
|
63
|
+
[[services.ports]]
|
64
|
+
force_https = true
|
65
|
+
handlers = ["http"]
|
66
|
+
port = 80
|
67
|
+
|
68
|
+
[[services.ports]]
|
69
|
+
handlers = ["tls", "http"]
|
70
|
+
port = 443
|
71
|
+
|
72
|
+
[[services.tcp_checks]]
|
73
|
+
grace_period = "1s"
|
74
|
+
interval = "15s"
|
75
|
+
restart_limit = 0
|
76
|
+
timeout = "2s"
|
77
|
+
|
78
|
+
[[statics]]
|
79
|
+
guest_path = "/app/public"
|
80
|
+
url_prefix = "/"
|
81
|
+
<% end -%>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# The path to where the SQLite database will be accessed.
|
2
|
+
mount-dir: "/data"
|
3
|
+
|
4
|
+
# The path to where the underlying volume mount is.
|
5
|
+
data-dir: "/mnt/volume"
|
6
|
+
|
7
|
+
# Execute this subprocess once LiteFS connects to the cluster.
|
8
|
+
exec: "bin/rails fly:server"
|
9
|
+
|
10
|
+
# These environment variables will be available in your Fly.io application.
|
11
|
+
# You must specify "experiement.enable_consul" for FLY_CONSUL_URL to be available.
|
12
|
+
consul:
|
13
|
+
url: "${FLY_CONSUL_URL}"
|
14
|
+
advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
|
@@ -0,0 +1,101 @@
|
|
1
|
+
terraform {
|
2
|
+
required_providers {
|
3
|
+
fly = {
|
4
|
+
source = "fly-apps/fly"
|
5
|
+
version = "0.0.20"
|
6
|
+
}
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
variable "image_ref" {
|
11
|
+
type = string
|
12
|
+
description = "docker images containing the application"
|
13
|
+
}
|
14
|
+
|
15
|
+
/* uncomment if you want an internal tunnel
|
16
|
+
provider "fly" {
|
17
|
+
useinternaltunnel = true
|
18
|
+
internaltunnelorg = <%= (@org || "personal").inspect %>
|
19
|
+
internaltunnelregion = <%= (@regions.first || 'iad').inspect %>
|
20
|
+
}
|
21
|
+
*/
|
22
|
+
|
23
|
+
# Allocate an IPv4 address
|
24
|
+
resource "fly_ip" "<%= @appName %>Ipv4" {
|
25
|
+
app = <%= @app.inspect %>
|
26
|
+
type = "v4"
|
27
|
+
}
|
28
|
+
|
29
|
+
# Allocate an IPv6 address
|
30
|
+
resource "fly_ip" "<%= @appName %>Ipv6" {
|
31
|
+
app = <%= @app.inspect %>
|
32
|
+
type = "v6"
|
33
|
+
}
|
34
|
+
|
35
|
+
<% unless @sqlite3 -%>
|
36
|
+
/* Uncomment this if you want a volume
|
37
|
+
<% end -%>
|
38
|
+
resource "fly_volume" "<%= @appName %>Volume" {
|
39
|
+
for_each = toset(<%= @regions.inspect %>)
|
40
|
+
region = each.value
|
41
|
+
|
42
|
+
name = "<%= @appName %>Volume"
|
43
|
+
app = <%= @app.inspect %>
|
44
|
+
size = 3
|
45
|
+
}
|
46
|
+
<% unless @sqlite3 -%>
|
47
|
+
*/
|
48
|
+
<% end -%>
|
49
|
+
|
50
|
+
# Start a fly machine
|
51
|
+
resource "fly_machine" "<%= @appName %>Machine" {
|
52
|
+
for_each = toset(<%= @regions.inspect %>)
|
53
|
+
region = each.value
|
54
|
+
|
55
|
+
app = <%= @app.inspect %>
|
56
|
+
name = "<%= @app %>-${each.value}"
|
57
|
+
image = var.image_ref
|
58
|
+
|
59
|
+
# Scale application resources
|
60
|
+
cpus = 1
|
61
|
+
cputype = "shared"
|
62
|
+
memorymb = 256
|
63
|
+
|
64
|
+
# map http[s] external ports 443 and 80 to internal port 8080
|
65
|
+
services = [
|
66
|
+
{
|
67
|
+
ports = [
|
68
|
+
{
|
69
|
+
port = 443
|
70
|
+
handlers = ["tls", "http"]
|
71
|
+
},
|
72
|
+
{
|
73
|
+
port = 80
|
74
|
+
handlers = ["http"]
|
75
|
+
}
|
76
|
+
]
|
77
|
+
|
78
|
+
protocol = "tcp"
|
79
|
+
internal_port = 8080
|
80
|
+
}
|
81
|
+
]
|
82
|
+
|
83
|
+
<%- if @sqlite3 -%>
|
84
|
+
env = {
|
85
|
+
DATABASE_URL = "sqlite3:///mnt/db/production.sqlite3"
|
86
|
+
}
|
87
|
+
|
88
|
+
mounts = [
|
89
|
+
{
|
90
|
+
volume = "<%= @appName %>Volume"
|
91
|
+
path = "/mnt/db"
|
92
|
+
}
|
93
|
+
]
|
94
|
+
|
95
|
+
depends_on = [fly_volume.<%= @appName %>Volume]
|
96
|
+
<%- else -%>
|
97
|
+
/* Uncomment this if you want a volume
|
98
|
+
depends_on = [fly_volume.<%= @appName %>Volume]
|
99
|
+
*/
|
100
|
+
<%- end -%>
|
101
|
+
}
|