standard-procedure-anvil 0.1.1
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/.rspec +3 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +139 -0
- data/Rakefile +10 -0
- data/exe/anvil +5 -0
- data/lib/anvil/cli.rb +35 -0
- data/lib/anvil/installer.rb +17 -0
- data/lib/anvil/logger.rb +13 -0
- data/lib/anvil/server_installer/configure_docker.rb +10 -0
- data/lib/anvil/server_installer/configure_dokku.rb +11 -0
- data/lib/anvil/server_installer/configure_firewall.rb +10 -0
- data/lib/anvil/server_installer/configure_ssh_server.rb +12 -0
- data/lib/anvil/server_installer/create_users.rb +20 -0
- data/lib/anvil/server_installer/install_packages.rb +40 -0
- data/lib/anvil/server_installer/install_plugins.rb +14 -0
- data/lib/anvil/server_installer/set_hostname.rb +12 -0
- data/lib/anvil/server_installer/set_timezone.rb +10 -0
- data/lib/anvil/server_installer.rb +60 -0
- data/lib/anvil/ssh_executor.rb +19 -0
- data/lib/anvil/version.rb +5 -0
- data/lib/anvil.rb +8 -0
- data/sig/standard/procedure/anvil.rbs +8 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 47f486a924f5bdee358e37587a81182f20578c61180508124ed2cef551b1fd62
|
4
|
+
data.tar.gz: 87f4d8498543db8f3aefd10ddd5e288bed1d9db89c47e84c82de2745bdd61a4a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 92a3dbc97db730b1a55d31bdae8cae9b607f36070b2cee53b6dc386b1cfc755b13f57b90f6874c885882f4d08fd9cc6057dc5e520d9d8dcce7750339124ca518
|
7
|
+
data.tar.gz: b378044a88edce05a58234c9cca4c7878d7ed7ed25255e57b544392286d18458afffd5b709e51fe70e5e237df0a876111eb3cf4ed529ff2042ac2d8051aa6abd
|
data/.rspec
ADDED
data/.standard.yml
ADDED
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Rahoul Baruah
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Standard::Procedure::Anvil
|
2
|
+
|
3
|
+
Some simple scripts for installing [Dokku](https://dokku.com) applications on Ubuntu servers.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem install standard-procedure-anvil
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
### To build a new server
|
14
|
+
|
15
|
+
Coming soon (plan is to use [Fog](https://github.com/fog/fog) to handle building servers)
|
16
|
+
|
17
|
+
### To install an application onto a blank server
|
18
|
+
|
19
|
+
Move to your application's root folder and create the anvil.yml file (see below).
|
20
|
+
|
21
|
+
Then run `anvil host --user=user --use-sudo --identity=~/.ssh/my_key`.
|
22
|
+
|
23
|
+
This will SSH into each server and:
|
24
|
+
|
25
|
+
- Sets the server hostname and timezone
|
26
|
+
- Installs various necessary packages, plus dokku itself
|
27
|
+
- Sets up the firewall
|
28
|
+
- Creates unix users for each app, adding them to the sudo and docker groups, and setting their authorized_keys files with the given public key
|
29
|
+
- Schedule a `docker system prune` once per week to clean up any dangling images or containers
|
30
|
+
- Configure nginx
|
31
|
+
- Install dokku plugins and run any configuration you have defined
|
32
|
+
- Sets the dokku deployment branch to `main`
|
33
|
+
- Disallows root and passwordless logins over SSH
|
34
|
+
|
35
|
+
For each app it will then:
|
36
|
+
|
37
|
+
- Create the dokku app
|
38
|
+
- Set the environment variables to those defined in your configuration and secrets files
|
39
|
+
- Set the app's domain and set up a proxy from nginx to the app's port
|
40
|
+
- Sets resource limits for the app
|
41
|
+
- Disables checks for workers
|
42
|
+
|
43
|
+
Then a git remote for each app is created on your local machine and then pushed. This performs the initial dokku deployment. Once complete:
|
44
|
+
|
45
|
+
- The app is scaled to the correct number of workers
|
46
|
+
- Plugins are configured for the app
|
47
|
+
|
48
|
+
### Configuration Files
|
49
|
+
|
50
|
+
An Anvil configuration file specifies the configuration for multiple servers and multiple apps. Each server is configured, then each app is installed onto each server.
|
51
|
+
|
52
|
+
So you could have one app on two servers (and, we assume, a load-balancer set up in front of them). Or two apps on one server. Or even two apps on two servers (again, using a load-balancer)
|
53
|
+
|
54
|
+
|
55
|
+
```yml
|
56
|
+
version: 0.1
|
57
|
+
servers:
|
58
|
+
hosts:
|
59
|
+
- server1.example.com
|
60
|
+
user: user
|
61
|
+
public_key: /home/local-user/.ssh/my-key.pub
|
62
|
+
timezone: Europe/London
|
63
|
+
ports:
|
64
|
+
- 22/tcp
|
65
|
+
- 80/tcp
|
66
|
+
- 443/tcp
|
67
|
+
nginx:
|
68
|
+
forward_proxy_headers: false
|
69
|
+
client_max_body_size: 512m
|
70
|
+
proxy_read_timeout: 60s
|
71
|
+
plugins:
|
72
|
+
cron-restart:
|
73
|
+
url: https://github.com/dokku/dokku-cron-restart.git
|
74
|
+
maintenance:
|
75
|
+
url: https://github.com/dokku/dokku-maintenance.git
|
76
|
+
redis:
|
77
|
+
url: https://github.com/dokku/dokku-redis.git
|
78
|
+
memcached:
|
79
|
+
url: https://github.com/dokku/dokku-memcached.git
|
80
|
+
letsencrypt:
|
81
|
+
url: https://github.com/dokku/dokku-letsencrypt.git
|
82
|
+
config:
|
83
|
+
- set --global email ssl-admin@mycompany.com
|
84
|
+
- cronjob --add
|
85
|
+
apps:
|
86
|
+
first_app:
|
87
|
+
hostname: first_app.example.com
|
88
|
+
port: 3000
|
89
|
+
environment:
|
90
|
+
- ENV_VAR=value
|
91
|
+
- ENV_VAR2=value2
|
92
|
+
- RAILS_ENV=production
|
93
|
+
secrets: secrets.yml
|
94
|
+
resource_limit: 2048m
|
95
|
+
scale: web=2 worker=1
|
96
|
+
plugins:
|
97
|
+
cron-restart:
|
98
|
+
- set first_app schedule '0 3 * * *'
|
99
|
+
redis:
|
100
|
+
- create first_app_redis_db
|
101
|
+
- link first_app_redis_db first_app
|
102
|
+
memcached:
|
103
|
+
- create first_app_memcached
|
104
|
+
- link first_app_memcached first_app
|
105
|
+
letsencrypt:
|
106
|
+
- set first_app email ssl-admin@mycompany.com
|
107
|
+
- enable first_app
|
108
|
+
second_app:
|
109
|
+
hostname: second_app.example.com
|
110
|
+
port: 3000
|
111
|
+
environment:
|
112
|
+
- ENV_VAR=value
|
113
|
+
- ENV_VAR2=value2
|
114
|
+
- RAILS_ENV=production
|
115
|
+
secrets: secrets.yml
|
116
|
+
resource_limit: 2048m
|
117
|
+
scale: web=2 worker=1
|
118
|
+
plugins:
|
119
|
+
cron-restart:
|
120
|
+
- set second_app schedule '0 3 * * *'
|
121
|
+
letsencrypt:
|
122
|
+
- set second_app email ssl-admin@mycompany.com
|
123
|
+
- enable second_app
|
124
|
+
```
|
125
|
+
`secrets.yml` is an optional additional file containing environment variables that you do not want to check into your source code repository. It is a simple KEY=VALUE format:
|
126
|
+
|
127
|
+
```
|
128
|
+
DB_PASSWORD=letmein
|
129
|
+
ENCRYPTION_KEY=secretstuff
|
130
|
+
```
|
131
|
+
|
132
|
+
|
133
|
+
## Contributing
|
134
|
+
|
135
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/standard-procedure-anvil.
|
136
|
+
|
137
|
+
## License
|
138
|
+
|
139
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/exe/anvil
ADDED
data/lib/anvil/cli.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require_relative "installer"
|
5
|
+
class Anvil::Cli < Thor
|
6
|
+
desc "anvil install", "Perform an installation of dokku on a server"
|
7
|
+
long_desc <<-DESC
|
8
|
+
Perform an installation of dokku on a server in preparation for deploying apps.
|
9
|
+
|
10
|
+
Example:
|
11
|
+
`anvil install CONFIG`
|
12
|
+
|
13
|
+
The default CONFIG file is `anvil.yml` in the current directory.
|
14
|
+
|
15
|
+
Options:
|
16
|
+
--private_key, -k: The path to the key certificate file to use when connecting to the server.
|
17
|
+
--passphrase, -p: The passphrase to use when connecting to the server.
|
18
|
+
DESC
|
19
|
+
option :private_key, type: :string, default: nil, aliases: "-k"
|
20
|
+
option :passphrase, type: :string, default: nil, aliases: "-p"
|
21
|
+
|
22
|
+
def install config = "anvil.yml", private_key = nil, passphrase = nil
|
23
|
+
Anvil::Installer.new(configuration_from(config), private_key, passphrase).call
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.exit_on_failure?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def configuration_from(file_name)
|
33
|
+
@configuration ||= YAML.load_file(file_name)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require_relative "server_installer"
|
5
|
+
|
6
|
+
# The Installer reads the configuration and runs the ServerInstaller for each host.
|
7
|
+
class Anvil::Installer < Struct.new(:configuration, :private_key, :passphrase)
|
8
|
+
def call
|
9
|
+
hosts.each do |host|
|
10
|
+
Anvil::ServerInstaller.new(host, configuration, private_key, passphrase).call
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def hosts
|
15
|
+
configuration["hosts"]
|
16
|
+
end
|
17
|
+
end
|
data/lib/anvil/logger.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::Logger < Struct.new(:prefix)
|
4
|
+
def info message, category = nil
|
5
|
+
puts [timestamp, category, message].compact.join(" ")
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def timestamp
|
11
|
+
"#{Time.now.strftime("%H:%M:%S")} #{prefix}".rjust(40)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::ConfigureDocker < Struct.new(:ssh_connection)
|
4
|
+
def call
|
5
|
+
script = <<~SCRIPT
|
6
|
+
echo "15 0 3 * * /usr/bin/docker system prune -f" | crontab
|
7
|
+
SCRIPT
|
8
|
+
ssh_connection.exec! script, "ConfigureDocker"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::ConfigureDokku < Struct.new(:ssh_connection, :hostname)
|
4
|
+
def call
|
5
|
+
script = <<~SCRIPT
|
6
|
+
dokku domains:set-global #{hostname}
|
7
|
+
dokku git:set --global deploy-branch main
|
8
|
+
SCRIPT
|
9
|
+
ssh_connection.exec! script, "ConfigureDokku"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::ConfigureFirewall < Struct.new(:ssh_connection, :ports)
|
4
|
+
def call
|
5
|
+
ports.collect do |port|
|
6
|
+
ssh_connection.exec! "ufw allow #{port}", "ConfigureFirewall"
|
7
|
+
end
|
8
|
+
ssh_connection.exec! "ufw --force enable", "ConfigureFirewall"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::ConfigureSshServer < Struct.new(:ssh_connection)
|
4
|
+
def call
|
5
|
+
script = <<-SCRIPT
|
6
|
+
sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config
|
7
|
+
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config
|
8
|
+
service sshd restart
|
9
|
+
SCRIPT
|
10
|
+
ssh_connection.exec! script, "ConfigureSshServer"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::CreateUsers < Struct.new(:ssh_connection, :names)
|
4
|
+
def call
|
5
|
+
names.collect do |name|
|
6
|
+
script = <<~SCRIPT
|
7
|
+
if id -u #{name} >/dev/null 2>&1; then
|
8
|
+
echo "#{name} already exists"
|
9
|
+
else
|
10
|
+
echo "Adding #{name}"
|
11
|
+
adduser --disabled-password --gecos "" #{name}
|
12
|
+
usermod -aG sudo #{name}
|
13
|
+
usermod -aG docker #{name}
|
14
|
+
echo "#{name} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
15
|
+
fi
|
16
|
+
SCRIPT
|
17
|
+
ssh_connection.exec! script, "CreateUsers"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::InstallPackages < Struct.new(:ssh_connection, :public_key_file)
|
4
|
+
def call
|
5
|
+
public_key = File.read public_key_file
|
6
|
+
script = <<~SCRIPT
|
7
|
+
mkdir -p /root/.ssh
|
8
|
+
echo "#{public_key}" > /root/.ssh/id_rsa.pub
|
9
|
+
mkdir -p /etc/skel/.ssh
|
10
|
+
cp /root/.ssh/id_rsa.pub /etc/skel/.ssh/authorized_keys
|
11
|
+
|
12
|
+
echo "Installing packages"
|
13
|
+
apt-get update -qq >/dev/null
|
14
|
+
apt-get -qq -y --no-install-recommends install apt-transport-https
|
15
|
+
|
16
|
+
if command -v "$@" > /dev/null 2>&1; then
|
17
|
+
echo "Docker is already installed"
|
18
|
+
else
|
19
|
+
echo "Installing docker"
|
20
|
+
wget -nv -O - https://get.docker.com/ | sh
|
21
|
+
|
22
|
+
wget -qO- https://packagecloud.io/dokku/dokku/gpgkey | tee /etc/apt/trusted.gpg.d/dokku.asc
|
23
|
+
DISTRO="$(awk -F= '$1=="ID" { print tolower($2) ;}' /etc/os-release)"
|
24
|
+
OS_ID="$(awk -F= '$1=="VERSION_CODENAME" { print tolower($2) ;}' /etc/os-release)"
|
25
|
+
echo "deb https://packagecloud.io/dokku/dokku/${DISTRO}/ ${OS_ID} main" | tee /etc/apt/sources.list.d/dokku.list
|
26
|
+
fi
|
27
|
+
|
28
|
+
echo "Installing dokku"
|
29
|
+
apt-get update -qq >/dev/null
|
30
|
+
apt-get -qq -y install dokku
|
31
|
+
|
32
|
+
echo "Installing dependencies"
|
33
|
+
dokku plugin:install-dependencies --core
|
34
|
+
|
35
|
+
cat /root/.ssh/id_rsa.pub | dokku ssh-keys:add admin
|
36
|
+
SCRIPT
|
37
|
+
|
38
|
+
ssh_connection.exec! script, "InstallPackages"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::InstallPlugins < Struct.new(:ssh_connection, :plugins)
|
4
|
+
def call
|
5
|
+
plugins.each do |name, config|
|
6
|
+
scripts = ["dokku plugin:install #{config["url"]} #{name}"]
|
7
|
+
plugin_config = config["config"] || []
|
8
|
+
scripts += plugin_config.collect do |cmd|
|
9
|
+
"dokku #{name}:#{cmd}"
|
10
|
+
end
|
11
|
+
ssh_connection.exec! scripts.join("\n"), "InstallPlugins"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Anvil::ServerInstaller::SetHostname < Struct.new(:ssh_connection, :hostname)
|
4
|
+
def call
|
5
|
+
script = <<-SCRIPT
|
6
|
+
hostnamectl set-hostname #{hostname}
|
7
|
+
mkdir -p /etc/environment.d
|
8
|
+
echo "HOSTNAME=#{hostname}" > /etc/environment.d/99-hostname
|
9
|
+
SCRIPT
|
10
|
+
ssh_connection.exec! script, "SetHostname"
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "ssh_executor"
|
4
|
+
require_relative "logger"
|
5
|
+
|
6
|
+
# The server installer uses Net::SSH to connect to the server and then run the following steps:
|
7
|
+
# - Sets the server hostname and timezone
|
8
|
+
# - Installs various necessary packages, plus dokku itself
|
9
|
+
# - Sets up the firewall
|
10
|
+
# - Creates unix users for each app, adding them to the sudo and docker groups, and setting their authorized_keys files with the given public key
|
11
|
+
# - Sets the dokku deployment branch to `main`
|
12
|
+
# - Schedule a `docker system prune` once per week to clean up any dangling images or containers
|
13
|
+
# - Configure nginx
|
14
|
+
# - Install dokku plugins and run any configuration you have defined
|
15
|
+
# - Disallows root and passwordless logins over SSH
|
16
|
+
class Anvil::ServerInstaller < Struct.new(:hostname, :configuration, :private_key, :passphrase)
|
17
|
+
require_relative "server_installer/set_hostname"
|
18
|
+
require_relative "server_installer/set_timezone"
|
19
|
+
require_relative "server_installer/install_packages"
|
20
|
+
require_relative "server_installer/create_users"
|
21
|
+
require_relative "server_installer/configure_dokku"
|
22
|
+
require_relative "server_installer/configure_docker"
|
23
|
+
require_relative "server_installer/install_plugins"
|
24
|
+
require_relative "server_installer/configure_firewall"
|
25
|
+
require_relative "server_installer/configure_ssh_server"
|
26
|
+
def call
|
27
|
+
Anvil::SshExecutor.new(hostname, server_configuration["user"], logger).call do |ssh_connection|
|
28
|
+
logger.info "SetHostname"
|
29
|
+
Anvil::ServerInstaller::SetHostname.new(ssh_connection, hostname).call
|
30
|
+
logger.info "SetTimezone"
|
31
|
+
Anvil::ServerInstaller::SetTimezone.new(ssh_connection, server_configuration["timezone"]).call
|
32
|
+
logger.info "InstallPackages"
|
33
|
+
Anvil::ServerInstaller::InstallPackages.new(ssh_connection, server_configuration["public_key"]).call
|
34
|
+
logger.info "ConfigureDokku"
|
35
|
+
Anvil::ServerInstaller::ConfigureDokku.new(ssh_connection, hostname).call
|
36
|
+
logger.info "CreateUsers"
|
37
|
+
Anvil::ServerInstaller::CreateUsers.new(ssh_connection, app_names).call
|
38
|
+
logger.info "InstallPlugins"
|
39
|
+
Anvil::ServerInstaller::InstallPlugins.new(ssh_connection, server_configuration["plugins"]).call
|
40
|
+
logger.info "ConfigureDocker"
|
41
|
+
Anvil::ServerInstaller::ConfigureDocker.new(ssh_connection).call
|
42
|
+
logger.info "ConfigureFirewall"
|
43
|
+
Anvil::ServerInstaller::ConfigureFirewall.new(ssh_connection, server_configuration["ports"]).call
|
44
|
+
logger.info "ConfigureSshServer"
|
45
|
+
Anvil::ServerInstaller::ConfigureSshServer.new(ssh_connection).call
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def server_configuration
|
50
|
+
configuration["server_config"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def app_names
|
54
|
+
configuration["apps"].keys
|
55
|
+
end
|
56
|
+
|
57
|
+
def logger
|
58
|
+
Anvil::Logger.new(hostname)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/ssh"
|
4
|
+
|
5
|
+
# The Installer reads the configuration and runs the ServerInstaller for each host.
|
6
|
+
class Anvil::SshExecutor < Struct.new(:hostname, :user, :logger)
|
7
|
+
def call &block
|
8
|
+
@connection = Net::SSH.start hostname, user, use_agent: true
|
9
|
+
block.call self
|
10
|
+
end
|
11
|
+
|
12
|
+
def exec! script, category = ""
|
13
|
+
@connection.exec! script do |channel, stream, data|
|
14
|
+
data.to_s.split("\n") do |line|
|
15
|
+
logger.info line, category
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/anvil.rb
ADDED
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: standard-procedure-anvil
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rahoul Baruah
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-06-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ed25519
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bcrypt_pbkdf
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: net-ssh
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Tools for managing servers and apps built using dokku
|
70
|
+
email:
|
71
|
+
- rahoulb@standardprocedure.app
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".rspec"
|
77
|
+
- ".standard.yml"
|
78
|
+
- CHANGELOG.md
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- exe/anvil
|
83
|
+
- lib/anvil.rb
|
84
|
+
- lib/anvil/cli.rb
|
85
|
+
- lib/anvil/installer.rb
|
86
|
+
- lib/anvil/logger.rb
|
87
|
+
- lib/anvil/server_installer.rb
|
88
|
+
- lib/anvil/server_installer/configure_docker.rb
|
89
|
+
- lib/anvil/server_installer/configure_dokku.rb
|
90
|
+
- lib/anvil/server_installer/configure_firewall.rb
|
91
|
+
- lib/anvil/server_installer/configure_ssh_server.rb
|
92
|
+
- lib/anvil/server_installer/create_users.rb
|
93
|
+
- lib/anvil/server_installer/install_packages.rb
|
94
|
+
- lib/anvil/server_installer/install_plugins.rb
|
95
|
+
- lib/anvil/server_installer/set_hostname.rb
|
96
|
+
- lib/anvil/server_installer/set_timezone.rb
|
97
|
+
- lib/anvil/ssh_executor.rb
|
98
|
+
- lib/anvil/version.rb
|
99
|
+
- sig/standard/procedure/anvil.rbs
|
100
|
+
homepage: https://github.com/standard-procedure/anvil
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata:
|
104
|
+
allowed_push_host: https://rubygems.org
|
105
|
+
homepage_uri: https://github.com/standard-procedure/anvil
|
106
|
+
source_code_uri: https://github.com/standard-procedure/anvil
|
107
|
+
changelog_uri: https://github.com/standard-procedure/anvil
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2.6.0
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubygems_version: 3.4.14
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Tools for managing servers and apps built using dokku
|
127
|
+
test_files: []
|