vps 0.1.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/VERSION +1 -1
- data/lib/vps.rb +1 -0
- data/lib/vps/cli.rb +1 -0
- data/lib/vps/cli/domain.rb +1 -1
- data/lib/vps/cli/playbook/state.rb +1 -1
- data/lib/vps/cli/upstream.rb +37 -21
- data/lib/vps/core_ext/ostruct.rb +17 -0
- data/lib/vps/version.rb +2 -2
- data/playbooks/deploy/docker.yml +2 -2
- data/templates/docker/data/nginx/app.conf.erb +21 -4
- data/templates/docker/docker-compose.yml.erb +15 -12
- data/templates/docker/upstream/Dockerfile.node.erb +15 -0
- data/templates/docker/upstream/Dockerfile.phoenix.erb +4 -1
- data/templates/docker/upstream/Dockerfile.plug.erb +4 -1
- data/templates/docker/upstream/Dockerfile.rack.erb +6 -2
- data/templates/docker/upstream/Dockerfile.rails.erb +8 -1
- data/templates/docker/upstream/init-letsencrypt.sh.erb +3 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0715c15db0c61c43f427cde770c38cde3f65e677
|
4
|
+
data.tar.gz: 62fbbc6d56af47c025031dd5125ab7a4072d546d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0850d9d9a5888d1162e7cb491906f0afea445f82535a68ae03014b6304cb594c7c81f765f14325bf0b1d295a1a88a7e07ac009859f6d5c0ba727d3fee34988a8
|
7
|
+
data.tar.gz: 7c6dfffa4ce37dc82012bf13865cc03f9feb6367c1565305f5a7461f88fe73d951fccd502fbfc6544df7505f50fb1de15feabdef5ec29bffd682cfc0a768f1be
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
## VPS CHANGELOG
|
2
2
|
|
3
|
+
### Version 0.2.3 (January 2, 2020)
|
4
|
+
|
5
|
+
* Support upstreams without domains
|
6
|
+
|
7
|
+
### Version 0.2.2 (January 2, 2020)
|
8
|
+
|
9
|
+
* Automatically add container names for upstreams and services
|
10
|
+
* Add opportunity to add lines to the generated Dockerfile
|
11
|
+
|
12
|
+
### Version 0.2.1 (January 2, 2020)
|
13
|
+
|
14
|
+
* Support NodeJS based applications
|
15
|
+
* Clean up default upstream specs
|
16
|
+
* Set container name when adding upstream
|
17
|
+
|
18
|
+
### Version 0.2.0 (December 31, 2019)
|
19
|
+
|
20
|
+
* Provide ability to add both custom HTTP and HTTPS Nginx configs
|
21
|
+
|
22
|
+
### Version 0.1.2 (September 29, 2019)
|
23
|
+
|
24
|
+
* Run postload tasks at the end of deployment
|
25
|
+
* Fix generating Rails and Rack Dockerfile (installing the correct Bundler version)
|
26
|
+
* Include configured :services in the generated docker-compose.yml file
|
27
|
+
|
3
28
|
### Version 0.1.1 (August 12, 2019)
|
4
29
|
|
5
30
|
* Initial release
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.3
|
data/lib/vps.rb
CHANGED
data/lib/vps/cli.rb
CHANGED
data/lib/vps/cli/domain.rb
CHANGED
@@ -11,7 +11,7 @@ module VPS
|
|
11
11
|
|
12
12
|
if (upstream = config[:upstreams].detect{|upstream| upstream[:name] == name})
|
13
13
|
upstream[:email] = email if email
|
14
|
-
upstream[:domains].push(domain).uniq!
|
14
|
+
(upstream[:domains] ||= []).push(domain).uniq!
|
15
15
|
VPS.write_config(host, config)
|
16
16
|
end
|
17
17
|
end
|
data/lib/vps/cli/upstream.rb
CHANGED
@@ -9,18 +9,11 @@ module VPS
|
|
9
9
|
path = File.expand_path(path)
|
10
10
|
|
11
11
|
unless config[:upstreams].any?{|upstream| upstream[:name] == name}
|
12
|
-
|
13
|
-
config[:upstreams].push({
|
12
|
+
spec = derive_upstream(path)
|
13
|
+
config[:upstreams].push(spec.merge({
|
14
14
|
:name => name || File.basename(path),
|
15
|
-
:path => path
|
16
|
-
|
17
|
-
:tool_version => tool_version,
|
18
|
-
:port => port,
|
19
|
-
:domains => [],
|
20
|
-
:email => nil,
|
21
|
-
:compose => nil,
|
22
|
-
:nginx => nil
|
23
|
-
})
|
15
|
+
:path => path
|
16
|
+
}))
|
24
17
|
VPS.write_config(host, config)
|
25
18
|
end
|
26
19
|
end
|
@@ -65,19 +58,42 @@ module VPS
|
|
65
58
|
|> IO.puts()
|
66
59
|
ELIXIR
|
67
60
|
type = `cd #{path} && mix run -e "#{elixir.strip.gsub(/\n\s+/, " ")}" | tail -n 1`.strip
|
68
|
-
|
69
|
-
type,
|
70
|
-
`cd #{path} && mix run -e "System.version() |> IO.puts()" | tail -n 1`.strip,
|
71
|
-
(type == "phoenix") ? 4000 : `cd #{path} && mix run -e ":ranch.info |> hd() |> elem(0) |> :ranch.get_port() |> IO.puts()" | tail -n 1`.strip.to_i
|
72
|
-
|
61
|
+
{
|
62
|
+
type: type,
|
63
|
+
elixir_version: `cd #{path} && mix run -e "System.version() |> IO.puts()" | tail -n 1`.strip,
|
64
|
+
port: (type == "phoenix") ? 4000 : `cd #{path} && mix run -e ":ranch.info |> hd() |> elem(0) |> :ranch.get_port() |> IO.puts()" | tail -n 1`.strip.to_i
|
65
|
+
}
|
73
66
|
elsif Dir["#{path}/Gemfile"].any?
|
74
67
|
lines = `cd #{path} && BUNDLE_GEMFILE=#{path}/Gemfile bundle list`.split("\n")
|
75
68
|
type = %w(rails rack).detect{|gem| lines.any?{|line| line.include?("* #{gem} (")}}
|
76
|
-
|
77
|
-
type,
|
78
|
-
`$SHELL -l -c 'cd #{path} && ruby -e "puts RUBY_VERSION"'`.strip,
|
79
|
-
|
80
|
-
|
69
|
+
{
|
70
|
+
type: type,
|
71
|
+
ruby_version: `$SHELL -l -c 'cd #{path} && ruby -e "puts RUBY_VERSION"'`.strip,
|
72
|
+
bundler_version: `$SHELL -l -c 'cd #{path} && bundle -v'`.split.last,
|
73
|
+
port: (type == "rails" ? 3000 : 9292) # :'(
|
74
|
+
}.tap do |spec|
|
75
|
+
if type == "rails"
|
76
|
+
spec[:nginx] = {
|
77
|
+
root: "/opt/app/public",
|
78
|
+
try_files: true,
|
79
|
+
proxy_redirect: "off"
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
elsif Dir["#{path}/package.json"].any?
|
84
|
+
tmpfile = "#{Dir.tmpdir}/vps-debug.log"
|
85
|
+
pid = spawn("cd #{path} && npm start", :out => tmpfile, :err => "/dev/null")
|
86
|
+
Process.detach(pid)
|
87
|
+
sleep 5
|
88
|
+
`ps aux | grep -e "no[d]e #{path}"`.strip.split("\n").collect do |line|
|
89
|
+
`kill -9 #{line.split(" ")[1]}`
|
90
|
+
end
|
91
|
+
port = File.read(tmpfile).match(/on port (\d+)/).captures.first.to_i
|
92
|
+
{
|
93
|
+
type: "node",
|
94
|
+
node_version: `$SHELL -l -c 'cd #{path} && node -v'`.match(/[\d\.?]+/).to_s,
|
95
|
+
port: port
|
96
|
+
}
|
81
97
|
end
|
82
98
|
end
|
83
99
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class OpenStruct
|
2
|
+
def self.to_hash(object, hash = {})
|
3
|
+
case object
|
4
|
+
when OpenStruct then
|
5
|
+
object.each_pair do |key, value|
|
6
|
+
hash[key.to_s] = to_hash(value)
|
7
|
+
end
|
8
|
+
hash
|
9
|
+
when Array then
|
10
|
+
object.collect do |value|
|
11
|
+
to_hash(value)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
object
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/vps/version.rb
CHANGED
data/playbooks/deploy/docker.yml
CHANGED
@@ -86,11 +86,11 @@ tasks:
|
|
86
86
|
command:
|
87
87
|
- chmod +x {{ release_path }}/init-letsencrypt/{{ upstream.name }}.sh
|
88
88
|
- cd {{ release_path }} && if [ ! -d "data/certbot/conf/live/{{ domain:upstream }}" ]; then yes Y | sudo ./init-letsencrypt/{{ upstream.name }}.sh; fi
|
89
|
-
- task: run_tasks
|
90
|
-
tasks: << postload >>
|
91
89
|
- description: Starting containers
|
92
90
|
task: remote_execute
|
93
91
|
command: cd {{ release_path }} && docker-compose up {{ up }} -d
|
94
92
|
- description: Checking running docker images
|
95
93
|
task: remote_execute
|
96
94
|
command: docker ps
|
95
|
+
- task: run_tasks
|
96
|
+
tasks: << postload >>
|
@@ -3,19 +3,26 @@
|
|
3
3
|
upstream <%= upstream[:name] %> {
|
4
4
|
server <%= upstream[:name] %>:<%= upstream[:port] %>;
|
5
5
|
}
|
6
|
-
<%- upstream[:domains].partition{|domain| domain.include?("http://")}.reject(&:empty?).each do |domains| %>
|
6
|
+
<%- (upstream[:domains] || []).partition{|domain| domain.include?("http://")}.reject(&:empty?).each do |domains| %>
|
7
7
|
<%-
|
8
8
|
https = domains.first.include?("https://")
|
9
9
|
domains = domains.collect{|domain| domain.gsub(/https?:\/\//, "")}.join(" ")
|
10
10
|
domain = domains.split(" ")[0]
|
11
|
+
nginx = upstream[:nginx] || {}
|
11
12
|
proxy_pass = "http://#{ upstream[:name] }"
|
12
13
|
%>
|
13
14
|
|
14
15
|
server {
|
16
|
+
<%- unless domains.empty? %>
|
15
17
|
listen 80;
|
16
18
|
server_name <%= domains %>;
|
17
19
|
server_tokens off;
|
18
20
|
|
21
|
+
<%- end %>
|
22
|
+
<%- if nginx[:http] %>
|
23
|
+
<%= nginx[:http].gsub("PROXY_PASS", proxy_pass).indent(2) %>
|
24
|
+
|
25
|
+
<%- end %>
|
19
26
|
<%- if https %>
|
20
27
|
location /.well-known/acme-challenge/ {
|
21
28
|
root /var/www/certbot;
|
@@ -37,15 +44,25 @@ server {
|
|
37
44
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
38
45
|
|
39
46
|
<%- end %>
|
40
|
-
<%- if
|
41
|
-
<%=
|
47
|
+
<%- if nginx[:root] %>
|
48
|
+
root <%= nginx[:root] %>;
|
49
|
+
<%- end %>
|
50
|
+
<%- if nginx[:try_files] %>
|
51
|
+
try_files $uri @app;
|
42
52
|
|
43
53
|
<%- end %>
|
44
|
-
|
54
|
+
<%- if nginx[:https] %>
|
55
|
+
<%= nginx[:https].gsub("PROXY_PASS", proxy_pass).indent(2) %>
|
56
|
+
|
57
|
+
<%- end %>
|
58
|
+
location <%= nginx[:try_files] ? "@app" : "/" %> {
|
45
59
|
proxy_pass <%= proxy_pass %>;
|
46
60
|
proxy_set_header Host $http_host;
|
47
61
|
proxy_set_header X-Real-IP $remote_addr;
|
48
62
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
63
|
+
<%- if nginx[:proxy_redirect] %>
|
64
|
+
proxy_redirect <%= nginx[:proxy_redirect] %>;
|
65
|
+
<%- end %>
|
49
66
|
}
|
50
67
|
}
|
51
68
|
<%- end %>
|
@@ -1,10 +1,5 @@
|
|
1
1
|
version: "3"
|
2
|
-
<%
|
3
|
-
https = upstreams.any?{|upstream| upstream[:domains].any?{|domain| domain.include?("https://")}}
|
4
|
-
to_yaml = proc do |struct|
|
5
|
-
struct.to_h.inject({}){|h, (k, v)| h[k.to_s] = v; h}.to_yaml
|
6
|
-
end
|
7
|
-
%>
|
2
|
+
<% https = upstreams.any?{|upstream| upstream[:domains].any?{|domain| domain.include?("https://")}} %>
|
8
3
|
services:
|
9
4
|
|
10
5
|
nginx:
|
@@ -28,7 +23,7 @@ services:
|
|
28
23
|
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
|
29
24
|
|
30
25
|
certbot:
|
31
|
-
image: certbot/certbot
|
26
|
+
image: certbot/certbot:v0.27.1
|
32
27
|
container_name: certbot
|
33
28
|
restart: unless-stopped
|
34
29
|
volumes:
|
@@ -36,21 +31,29 @@ services:
|
|
36
31
|
- ./data/certbot/www:/var/www/certbot
|
37
32
|
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
|
38
33
|
<%- end %>
|
34
|
+
<%- services.to_h.each do |name, spec| %>
|
35
|
+
|
36
|
+
<%= name %>:
|
37
|
+
<%= OpenStruct.to_hash(spec).to_yaml.sub(/^.*?\n/, "").sub("\n", "\ncontainer_name: #{name}\n").indent(4) %>
|
38
|
+
<%- end %>
|
39
39
|
<%- upstreams.each do |upstream| %>
|
40
40
|
|
41
41
|
<%= upstream.name %>:
|
42
42
|
image: <%= upstream.name %>
|
43
|
+
container_name: <%= upstream.name %>
|
43
44
|
restart: always
|
44
45
|
<%- unless upstream[:compose].inspect.match(/\bports\b/) %>
|
45
46
|
ports:
|
46
47
|
- <%= upstream.port %>
|
47
48
|
<%- end %>
|
48
49
|
<%- if upstream[:compose] %>
|
49
|
-
<%=
|
50
|
+
<%= OpenStruct.to_hash(upstream[:compose]).to_yaml.sub(/^.*?\n/, "").indent(4) %>
|
50
51
|
<%- end %>
|
51
52
|
<%- end %>
|
52
|
-
|
53
|
+
<%- unless (volumes || []).empty? %>
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
volumes:
|
56
|
+
<%- volumes.each do |volume| %>
|
57
|
+
<%= volume %>:
|
58
|
+
<%- end %>
|
59
|
+
<%- end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FROM node:<%= upstream.node_version %>-alpine
|
2
|
+
|
3
|
+
RUN apk update \
|
4
|
+
&& apk --no-cache --update add \
|
5
|
+
build-base nodejs tzdata
|
6
|
+
|
7
|
+
WORKDIR /opt/app
|
8
|
+
COPY . .
|
9
|
+
|
10
|
+
ENV NODE_ENV=production
|
11
|
+
<%- if upstream.dockerfile %>
|
12
|
+
<%= upstream.dockerfile.strip %>
|
13
|
+
<%- end %>
|
14
|
+
RUN npm install
|
15
|
+
CMD ["npm", "start"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM elixir:<%= upstream.
|
1
|
+
FROM elixir:<%= upstream.elixir_version %>-alpine
|
2
2
|
|
3
3
|
RUN apk update \
|
4
4
|
&& apk --no-cache --update add alpine-sdk \
|
@@ -9,5 +9,8 @@ WORKDIR /opt/app
|
|
9
9
|
COPY . .
|
10
10
|
|
11
11
|
ENV MIX_ENV=prod
|
12
|
+
<%- if upstream.dockerfile %>
|
13
|
+
<%= upstream.dockerfile.strip %>
|
14
|
+
<%- end %>
|
12
15
|
RUN mix do deps.get --only prod, deps.compile
|
13
16
|
CMD ["sh", "-c", "mix phx.server"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM elixir:<%= upstream.
|
1
|
+
FROM elixir:<%= upstream.elixir_version %>-alpine
|
2
2
|
|
3
3
|
RUN apk update \
|
4
4
|
&& apk --no-cache --update add alpine-sdk \
|
@@ -9,5 +9,8 @@ WORKDIR /opt/app
|
|
9
9
|
COPY . .
|
10
10
|
|
11
11
|
ENV MIX_ENV=prod
|
12
|
+
<%- if upstream.dockerfile %>
|
13
|
+
<%= upstream.dockerfile.strip %>
|
14
|
+
<%- end %>
|
12
15
|
RUN mix do deps.get --only prod, deps.compile
|
13
16
|
CMD ["sh", "-c", "mix run --no-halt"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM ruby:<%= upstream.
|
1
|
+
FROM ruby:<%= upstream.ruby_version %>-alpine
|
2
2
|
|
3
3
|
RUN apk update \
|
4
4
|
&& apk --no-cache --update add \
|
@@ -11,5 +11,9 @@ WORKDIR /opt/app
|
|
11
11
|
COPY . .
|
12
12
|
|
13
13
|
ENV RACK_ENV=production
|
14
|
+
<%- if upstream.dockerfile %>
|
15
|
+
<%= upstream.dockerfile.strip %>
|
16
|
+
<%- end %>
|
17
|
+
RUN gem install bundler -v <%= upstream.bundler_version %>
|
14
18
|
RUN bundle install --without development test
|
15
|
-
CMD ["rackup", "config.ru", "-o", "0.0.0.0"]
|
19
|
+
CMD ["bundle", "exec", "rackup", "config.ru", "-o", "0.0.0.0"]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM ruby:<%= upstream.
|
1
|
+
FROM ruby:<%= upstream.ruby_version %>-alpine
|
2
2
|
|
3
3
|
RUN apk update \
|
4
4
|
&& apk --no-cache --update add \
|
@@ -10,6 +10,13 @@ RUN apk update \
|
|
10
10
|
WORKDIR /opt/app
|
11
11
|
COPY . .
|
12
12
|
|
13
|
+
EXPOSE <%= upstream.port %>
|
14
|
+
|
13
15
|
ENV RAILS_ENV=production
|
16
|
+
<%- if upstream.dockerfile %>
|
17
|
+
<%= upstream.dockerfile.strip %>
|
18
|
+
<%- end %>
|
19
|
+
RUN gem install bundler -v <%= upstream.bundler_version %>
|
14
20
|
RUN bundle install --without development test
|
21
|
+
CMD ["rm", "-f", "tmp/pids/server.pid"]
|
15
22
|
CMD ["rails", "server", "-b", "0.0.0.0"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
|
3
|
-
<%- if (domains = upstream[:domains].collect{|domain| domain.dup.gsub!("https://", "")}.compact).any? %>
|
3
|
+
<%- if (domains = (upstream[:domains] || []).collect{|domain| domain.dup.gsub!("https://", "")}.compact).any? %>
|
4
4
|
domains=(<%= domains.join(" ") %>)
|
5
5
|
email="<%= upstream[:email] || "noreply@#{domains.first}" %>" # Adding a valid address is strongly recommended
|
6
6
|
data_path="./data/certbot"
|
@@ -17,8 +17,8 @@ fi
|
|
17
17
|
if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
|
18
18
|
echo "### Downloading recommended TLS parameters ..."
|
19
19
|
mkdir -p "$data_path/conf"
|
20
|
-
curl -s https://raw.githubusercontent.com/certbot/certbot/
|
21
|
-
curl -s https://raw.githubusercontent.com/certbot/certbot/
|
20
|
+
curl -s https://raw.githubusercontent.com/certbot/certbot/v0.40.1/certbot-nginx/certbot_nginx/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
|
21
|
+
curl -s https://raw.githubusercontent.com/certbot/certbot/v0.40.1/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
|
22
22
|
echo
|
23
23
|
fi
|
24
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vps
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Engel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -162,6 +162,7 @@ files:
|
|
162
162
|
- lib/vps/cli/playbook/tasks.rb
|
163
163
|
- lib/vps/cli/service.rb
|
164
164
|
- lib/vps/cli/upstream.rb
|
165
|
+
- lib/vps/core_ext/ostruct.rb
|
165
166
|
- lib/vps/core_ext/string.rb
|
166
167
|
- lib/vps/version.rb
|
167
168
|
- playbooks/deploy.yml
|
@@ -173,6 +174,7 @@ files:
|
|
173
174
|
- script/console
|
174
175
|
- templates/docker/data/nginx/app.conf.erb
|
175
176
|
- templates/docker/docker-compose.yml.erb
|
177
|
+
- templates/docker/upstream/Dockerfile.node.erb
|
176
178
|
- templates/docker/upstream/Dockerfile.phoenix.erb
|
177
179
|
- templates/docker/upstream/Dockerfile.plug.erb
|
178
180
|
- templates/docker/upstream/Dockerfile.rack.erb
|