kitsune-kit 0.2.1 โ 0.3.0
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 +2 -1
- data/lib/kitsune/blueprints/.env.template +7 -3
- data/lib/kitsune/blueprints/docker/redis.yml +23 -0
- data/lib/kitsune/kit/cli.rb +15 -1
- data/lib/kitsune/kit/commands/init.rb +2 -2
- data/lib/kitsune/kit/commands/setup_do_metrics.rb +3 -3
- data/lib/kitsune/kit/commands/setup_postgres_docker.rb +30 -32
- data/lib/kitsune/kit/commands/setup_redis_docker.rb +241 -0
- data/lib/kitsune/kit/defaults.rb +13 -1
- data/lib/kitsune/kit/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 508f86259061cf1c767fc1a1678aeb8195aaf174214c2c7f9be5557aa1b73c2a
|
4
|
+
data.tar.gz: 38f6179c02ad9a59608bb3e3d3f62bd7b23648bb0bb24a6cdbd9fba179af3255
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65b84489d96cc8228afe78113dcd08065d3297957b77fcece8dfb9fe1d5722695086f18cc6387c400a9888342ac82ce56feaa7d2f9d67c780bf6abedb4c7da3e
|
7
|
+
data.tar.gz: 59a28feaca900d703eb9ebe9943993cb1709b66784d7160425dc50f682bf7e93296408f8cdaedac04f3b2583a7757e74e69f7538515cc83abf3bf0f7088a1411
|
data/README.md
CHANGED
@@ -19,7 +19,8 @@
|
|
19
19
|
- ๐พ Configures swap space for better performance
|
20
20
|
- ๐ Installs [DigitalOcean monitoring agent](https://docs.digitalocean.com/products/monitoring/how-to/install-agent/)
|
21
21
|
- ๐ณ Installs and configures Docker Engine and private networking
|
22
|
-
- ๐ Deploys PostgreSQL via Docker Compose with healthcheck
|
22
|
+
- ๐ Deploys PostgreSQL via Docker Compose with healthcheck
|
23
|
+
- ๐๏ธ Deploys Redis via Docker Compose with healthcheck
|
23
24
|
- ๐ All steps can be rolled back (`--rollback`)
|
24
25
|
- โก Fast, reproducible and without relying on YAML or complex external tools
|
25
26
|
|
@@ -17,6 +17,10 @@ SWAP_SIZE_GB=2
|
|
17
17
|
DISABLE_SWAP=false
|
18
18
|
|
19
19
|
# PostgreSQL Docker
|
20
|
-
POSTGRES_DB=
|
21
|
-
POSTGRES_USER=
|
22
|
-
POSTGRES_PASSWORD=
|
20
|
+
POSTGRES_DB=myapp_db
|
21
|
+
POSTGRES_USER=postgres
|
22
|
+
POSTGRES_PASSWORD=secret
|
23
|
+
|
24
|
+
# Redis Docker
|
25
|
+
REDIS_PORT=6379
|
26
|
+
REDIS_PASSWORD=secret
|
@@ -0,0 +1,23 @@
|
|
1
|
+
services:
|
2
|
+
redis:
|
3
|
+
image: redis:7.2
|
4
|
+
restart: always
|
5
|
+
ports:
|
6
|
+
- "${REDIS_PORT:-6379}:6379"
|
7
|
+
command: redis-server --requirepass ${REDIS_PASSWORD}
|
8
|
+
networks:
|
9
|
+
- private
|
10
|
+
volumes:
|
11
|
+
- redisdata:/data
|
12
|
+
healthcheck:
|
13
|
+
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
14
|
+
interval: 30s
|
15
|
+
timeout: 10s
|
16
|
+
retries: 5
|
17
|
+
|
18
|
+
volumes:
|
19
|
+
redisdata:
|
20
|
+
|
21
|
+
networks:
|
22
|
+
private:
|
23
|
+
driver: bridge
|
data/lib/kitsune/kit/cli.rb
CHANGED
@@ -15,18 +15,29 @@ require_relative "commands/install_docker_engine"
|
|
15
15
|
require_relative "commands/postinstall_docker"
|
16
16
|
require_relative "commands/bootstrap_docker"
|
17
17
|
require_relative "commands/setup_postgres_docker"
|
18
|
+
require_relative "commands/setup_redis_docker"
|
18
19
|
|
19
20
|
module Kitsune
|
20
21
|
module Kit
|
21
22
|
class CLI < Thor
|
22
23
|
def self.dispatch(m, args, options, config)
|
23
|
-
|
24
|
+
if args.include?("-v") || args.include?("--version")
|
25
|
+
puts "Kitsune Kit v#{Kitsune::Kit::VERSION}"
|
26
|
+
exit(0)
|
27
|
+
end
|
28
|
+
|
29
|
+
unless ["version", "init", "switch_env", "help", nil].include?(args.first)
|
24
30
|
Kitsune::Kit::EnvLoader.load!
|
25
31
|
end
|
26
32
|
|
27
33
|
super
|
28
34
|
end
|
29
35
|
|
36
|
+
desc "version", "Show Kitsune Kit version"
|
37
|
+
def version
|
38
|
+
say "Kitsune Kit v#{Kitsune::Kit::VERSION}", :green
|
39
|
+
end
|
40
|
+
|
30
41
|
desc "init", "Initialize Kitsune Kit project structure"
|
31
42
|
subcommand "init", Kitsune::Kit::Commands::Init
|
32
43
|
|
@@ -68,6 +79,9 @@ module Kitsune
|
|
68
79
|
|
69
80
|
desc "setup_postgres_docker SUBCOMMAND", "Setup PostgreSQL via Docker Compose on remote server"
|
70
81
|
subcommand "setup_postgres_docker", Kitsune::Kit::Commands::SetupPostgresDocker
|
82
|
+
|
83
|
+
desc "setup_redis_docker SUBCOMMAND", "Setup Redis via Docker Compose on remote server"
|
84
|
+
subcommand "setup_redis_docker", Kitsune::Kit::Commands::SetupRedisDocker
|
71
85
|
end
|
72
86
|
end
|
73
87
|
end
|
@@ -124,8 +124,8 @@ module Kitsune
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def copy_docker_templates
|
127
|
-
|
128
|
-
copy_with_prompt(blueprint_path("docker/
|
127
|
+
copy_with_prompt(blueprint_path("docker/postgres.yml"), ".kitsune/docker/postgres.yml")
|
128
|
+
copy_with_prompt(blueprint_path("docker/redis.yml"), ".kitsune/docker/redis.yml")
|
129
129
|
end
|
130
130
|
|
131
131
|
def copy_with_prompt(source, destination)
|
@@ -26,7 +26,7 @@ module Kitsune
|
|
26
26
|
defaults: Kitsune::Kit::Defaults.ssh
|
27
27
|
)
|
28
28
|
|
29
|
-
|
29
|
+
with_ssh_connection(filled_options) do |ssh|
|
30
30
|
install_agent(ssh)
|
31
31
|
end
|
32
32
|
end
|
@@ -39,13 +39,13 @@ module Kitsune
|
|
39
39
|
defaults: Kitsune::Kit::Defaults.ssh
|
40
40
|
)
|
41
41
|
|
42
|
-
|
42
|
+
with_ssh_connection(filled_options) do |ssh|
|
43
43
|
uninstall_agent(ssh)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
no_commands do
|
48
|
-
def
|
48
|
+
def with_ssh_connection(filled_options)
|
49
49
|
Net::SSH.start(
|
50
50
|
filled_options[:server_ip],
|
51
51
|
"deploy",
|
@@ -36,11 +36,7 @@ module Kitsune
|
|
36
36
|
)
|
37
37
|
|
38
38
|
with_ssh_connection(filled_options) do |ssh|
|
39
|
-
perform_setup(ssh, postgres_defaults)
|
40
|
-
|
41
|
-
database_url = build_database_url(filled_options, postgres_defaults)
|
42
|
-
say "๐ Your DATABASE_URL is:\t", :cyan
|
43
|
-
say database_url, :green
|
39
|
+
perform_setup(ssh, postgres_defaults, filled_options)
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
@@ -71,26 +67,21 @@ module Kitsune
|
|
71
67
|
end
|
72
68
|
end
|
73
69
|
|
74
|
-
def perform_setup(ssh, postgres_defaults)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
70
|
+
def perform_setup(ssh, postgres_defaults, filled_options)
|
71
|
+
local_compose = ".kitsune/docker/postgres.yml"
|
72
|
+
remote_dir = "$HOME/docker/postgres"
|
73
|
+
compose_remote = "#{remote_dir}/docker-compose.yml"
|
74
|
+
env_remote = "#{remote_dir}/.env"
|
75
|
+
marker = "/usr/local/backups/setup_postgres_docker.after"
|
80
76
|
|
81
|
-
|
82
|
-
docker_compose_remote = "#{docker_dir_remote}/docker-compose.yml"
|
83
|
-
docker_env_remote = "#{docker_dir_remote}/.env"
|
84
|
-
backup_marker = "/usr/local/backups/setup_postgres_docker.after"
|
77
|
+
abort "โ Missing #{local_compose}" unless File.exist?(local_compose)
|
85
78
|
|
86
79
|
# 1. Create base directory securely
|
87
|
-
ssh.exec!("mkdir -p #{
|
88
|
-
ssh.exec!("chmod 700 #{docker_dir_remote}")
|
80
|
+
ssh.exec!("mkdir -p #{remote_dir} && chmod 700 #{remote_dir}")
|
89
81
|
|
90
82
|
# 2. Upload docker-compose.yml
|
91
|
-
say "๐ฆ Uploading docker-compose.yml to
|
92
|
-
|
93
|
-
upload_file(ssh, content_compose, docker_compose_remote)
|
83
|
+
say "๐ฆ Uploading docker-compose.yml to #{remote_dir}", :cyan
|
84
|
+
upload_file(ssh, File.read(local_compose), compose_remote)
|
94
85
|
|
95
86
|
# 3. Create .env file for docker-compose based on postgres_defaults
|
96
87
|
say "๐ฆ Creating .env file for Docker Compose...", :cyan
|
@@ -101,17 +92,17 @@ module Kitsune
|
|
101
92
|
POSTGRES_PORT=#{postgres_defaults[:postgres_port]}
|
102
93
|
POSTGRES_IMAGE=#{postgres_defaults[:postgres_image]}
|
103
94
|
ENVFILE
|
104
|
-
upload_file(ssh, env_content,
|
95
|
+
upload_file(ssh, env_content, env_remote)
|
105
96
|
|
106
97
|
# 4. Secure file permissions
|
107
|
-
ssh.exec!("chmod 600 #{
|
98
|
+
ssh.exec!("chmod 600 #{compose_remote} #{env_remote}")
|
108
99
|
|
109
100
|
# 5. Create backup marker
|
110
|
-
ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{
|
101
|
+
ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{marker}")
|
111
102
|
|
112
103
|
# 6. Validate docker-compose.yml
|
113
104
|
say "๐ Validating docker-compose.yml...", :cyan
|
114
|
-
validation_output = ssh.exec!("cd #{
|
105
|
+
validation_output = ssh.exec!("cd #{remote_dir} && docker compose config")
|
115
106
|
say validation_output, :cyan
|
116
107
|
|
117
108
|
# 7. Check if container is running
|
@@ -119,19 +110,20 @@ module Kitsune
|
|
119
110
|
|
120
111
|
if container_status.empty?
|
121
112
|
say "โถ๏ธ No running container. Running docker compose up...", :cyan
|
122
|
-
ssh.exec!("cd #{
|
113
|
+
ssh.exec!("cd #{remote_dir} && docker compose up -d")
|
123
114
|
else
|
124
115
|
say "โ ๏ธ PostgreSQL container is already running.", :yellow
|
125
116
|
if yes?("๐ Recreate the container with updated configuration? [y/N]", :yellow)
|
126
117
|
say "๐ Recreating container...", :cyan
|
127
|
-
ssh.exec!("cd #{
|
118
|
+
ssh.exec!("cd #{remote_dir} && docker compose down -v && docker compose up -d")
|
128
119
|
else
|
129
120
|
say "โฉ Keeping existing container.", :cyan
|
130
121
|
end
|
131
122
|
end
|
132
123
|
|
124
|
+
# 8. Check container status
|
133
125
|
say "๐ Final container status (docker compose ps):", :cyan
|
134
|
-
docker_ps_output = ssh.exec!("cd #{
|
126
|
+
docker_ps_output = ssh.exec!("cd #{remote_dir} && docker compose ps --format json")
|
135
127
|
|
136
128
|
if docker_ps_output.nil? || docker_ps_output.strip.empty? || docker_ps_output.include?("no configuration file")
|
137
129
|
say "โ ๏ธ docker compose ps returned no valid output.", :yellow
|
@@ -168,9 +160,13 @@ module Kitsune
|
|
168
160
|
if healthcheck.include?("accepting connections")
|
169
161
|
say "โ
PostgreSQL is up and accepting connections! (attempt #{attempt})", :green
|
170
162
|
success = true
|
163
|
+
|
164
|
+
database_url = build_database_url(filled_options, postgres_defaults)
|
165
|
+
say "๐ Your DATABASE_URL is:\t", :cyan
|
166
|
+
say database_url, :green
|
171
167
|
break
|
172
168
|
else
|
173
|
-
say "โณ PostgreSQL not ready yet, retrying in 5 seconds... (#{attempt
|
169
|
+
say "โณ PostgreSQL not ready yet, retrying in 5 seconds... (#{attempt}/#{max_attempts})", :yellow
|
174
170
|
sleep 5
|
175
171
|
end
|
176
172
|
end
|
@@ -181,7 +177,7 @@ module Kitsune
|
|
181
177
|
|
182
178
|
# 10. Allow PostgreSQL port through firewall (ufw)
|
183
179
|
say "๐ก๏ธ Configuring firewall to allow PostgreSQL (port #{postgres_defaults[:postgres_port]})...", :cyan
|
184
|
-
|
180
|
+
output = ssh.exec! <<~EOH
|
185
181
|
if command -v ufw >/dev/null; then
|
186
182
|
if ! sudo ufw status | grep -q "#{postgres_defaults[:postgres_port]}"; then
|
187
183
|
sudo ufw allow #{postgres_defaults[:postgres_port]}
|
@@ -192,7 +188,9 @@ module Kitsune
|
|
192
188
|
echo "โ ๏ธ ufw not found. Skipping firewall configuration."
|
193
189
|
fi
|
194
190
|
EOH
|
195
|
-
|
191
|
+
say output
|
192
|
+
|
193
|
+
say "โ
PostgreSQL setup completed successfully!", :green
|
196
194
|
end
|
197
195
|
|
198
196
|
def perform_rollback(ssh, postgres_defaults)
|
@@ -227,9 +225,9 @@ module Kitsune
|
|
227
225
|
end
|
228
226
|
|
229
227
|
def upload_file(ssh, content, remote_path)
|
230
|
-
|
228
|
+
escaped = Shellwords.escape(content)
|
231
229
|
ssh.exec!("mkdir -p #{File.dirname(remote_path)}")
|
232
|
-
ssh.exec!("echo #{
|
230
|
+
ssh.exec!("echo #{escaped} > #{remote_path}")
|
233
231
|
end
|
234
232
|
|
235
233
|
def build_database_url(filled_options, postgres_defaults)
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "net/ssh"
|
3
|
+
require "fileutils"
|
4
|
+
require "shellwords"
|
5
|
+
require_relative "../defaults"
|
6
|
+
require_relative "../options_builder"
|
7
|
+
require "pry"
|
8
|
+
module Kitsune
|
9
|
+
module Kit
|
10
|
+
module Commands
|
11
|
+
class SetupRedisDocker < Thor
|
12
|
+
namespace "setup_redis_docker"
|
13
|
+
|
14
|
+
class_option :server_ip, aliases: "-s", required: true, desc: "Server IP address or hostname"
|
15
|
+
class_option :ssh_port, aliases: "-p", desc: "SSH port"
|
16
|
+
class_option :ssh_key_path, aliases: "-k", desc: "Path to SSH private key"
|
17
|
+
|
18
|
+
desc "create", "Setup Redis using Docker Compose on remote server"
|
19
|
+
def create
|
20
|
+
redis_defaults = Kitsune::Kit::Defaults.redis
|
21
|
+
|
22
|
+
if redis_defaults[:redis_password] == "secret"
|
23
|
+
say "โ ๏ธ Warning: You are using the default Redis password ('secret').", :yellow
|
24
|
+
if ENV.fetch("KIT_ENV", "development") == "production"
|
25
|
+
abort "โ Production environment requires a secure Redis password!"
|
26
|
+
else
|
27
|
+
say "๐ Please change REDIS_PASSWORD in your .env if needed.", :yellow
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
32
|
+
options,
|
33
|
+
required: [:server_ip],
|
34
|
+
defaults: Kitsune::Kit::Defaults.ssh
|
35
|
+
)
|
36
|
+
|
37
|
+
with_ssh_connection(filled_options) do |ssh|
|
38
|
+
perform_setup(ssh, redis_defaults, filled_options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "rollback", "Remove Redis Docker setup from remote server"
|
43
|
+
def rollback
|
44
|
+
redis_defaults = Kitsune::Kit::Defaults.redis
|
45
|
+
|
46
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
47
|
+
options,
|
48
|
+
required: [:server_ip],
|
49
|
+
defaults: Kitsune::Kit::Defaults.ssh
|
50
|
+
)
|
51
|
+
|
52
|
+
with_ssh_connection(filled_options) do |ssh|
|
53
|
+
perform_rollback(ssh, redis_defaults)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
no_commands do
|
58
|
+
def with_ssh_connection(filled_options)
|
59
|
+
server = filled_options[:server_ip]
|
60
|
+
port = filled_options[:ssh_port]
|
61
|
+
key = File.expand_path(filled_options[:ssh_key_path])
|
62
|
+
|
63
|
+
say "๐ Connecting as deploy@#{server}:#{port}", :green
|
64
|
+
Net::SSH.start(server, "deploy", port: port, keys: [key], non_interactive: true, timeout: 5) do |ssh|
|
65
|
+
yield ssh
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def perform_setup(ssh, redis_defaults, filled_options)
|
70
|
+
local_compose = ".kitsune/docker/redis.yml"
|
71
|
+
remote_dir = "$HOME/docker/redis"
|
72
|
+
compose_remote = "#{remote_dir}/docker-compose.yml"
|
73
|
+
env_remote = "#{remote_dir}/.env"
|
74
|
+
marker = "/usr/local/backups/setup_redis_docker.after"
|
75
|
+
|
76
|
+
abort "โ Missing #{local_compose}" unless File.exist?(local_compose)
|
77
|
+
|
78
|
+
# 1. Create base directory securely
|
79
|
+
ssh.exec!("mkdir -p #{remote_dir} && chmod 700 #{remote_dir}")
|
80
|
+
|
81
|
+
# 2. Upload docker-compose.yml
|
82
|
+
say "๐ฆ Uploading docker-compose.yml to #{remote_dir}", :cyan
|
83
|
+
upload_file(ssh, File.read(local_compose), compose_remote)
|
84
|
+
|
85
|
+
# 3. Create .env file for docker-compose based on redis_defaults
|
86
|
+
env_content = <<~ENVFILE
|
87
|
+
REDIS_PORT=#{redis_defaults[:redis_port]}
|
88
|
+
REDIS_PASSWORD=#{redis_defaults[:redis_password]}
|
89
|
+
ENVFILE
|
90
|
+
upload_file(ssh, env_content, env_remote)
|
91
|
+
|
92
|
+
# 4. Secure file permissions
|
93
|
+
ssh.exec!("chmod 600 #{compose_remote} #{env_remote}")
|
94
|
+
|
95
|
+
# 5. Create a backup marker
|
96
|
+
ssh.exec!("sudo mkdir -p /usr/local/backups && sudo touch #{marker}")
|
97
|
+
|
98
|
+
# 6. Validate docker-compose.yml
|
99
|
+
say "๐ Validating docker-compose.yml...", :cyan
|
100
|
+
validation_output = ssh.exec!("cd #{remote_dir} && docker compose config")
|
101
|
+
say validation_output, :cyan
|
102
|
+
|
103
|
+
# 7. Check if container is running
|
104
|
+
container_status = ssh.exec!("docker ps --filter 'name=redis' --format '{{.Status}}'").strip
|
105
|
+
|
106
|
+
if container_status.empty?
|
107
|
+
say "โถ๏ธ No running container. Running docker compose up...", :cyan
|
108
|
+
ssh.exec!("cd #{remote_dir} && docker compose up -d")
|
109
|
+
else
|
110
|
+
say "โ ๏ธ Redis container is already running.", :yellow
|
111
|
+
if yes?("๐ Recreate the container with updated configuration? [y/N]", :yellow)
|
112
|
+
say "๐ Recreating container...", :cyan
|
113
|
+
ssh.exec!("cd #{remote_dir} && docker compose down -v && docker compose up -d")
|
114
|
+
else
|
115
|
+
say "โฉ Keeping existing container.", :cyan
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# 8. Check container status
|
120
|
+
say "๐ Final container status (docker compose ps):", :cyan
|
121
|
+
docker_ps_output = ssh.exec!("cd #{remote_dir} && docker compose ps --format json")
|
122
|
+
|
123
|
+
if docker_ps_output.nil? || docker_ps_output.strip.empty? || docker_ps_output.include?("no configuration file")
|
124
|
+
say "โ ๏ธ docker compose ps returned no valid output.", :yellow
|
125
|
+
else
|
126
|
+
begin
|
127
|
+
services = JSON.parse(docker_ps_output)
|
128
|
+
services = [services] if services.is_a?(Hash)
|
129
|
+
|
130
|
+
redis = services.find { |svc| svc["Service"] == "redis" }
|
131
|
+
status = redis && redis["State"]
|
132
|
+
health = redis && redis["Health"]
|
133
|
+
|
134
|
+
if (status == "running" && health == "healthy") || (health == "healthy")
|
135
|
+
say "โ
Redis container is running and healthy.", :green
|
136
|
+
else
|
137
|
+
say "โ ๏ธ Redis container is not healthy yet.", :yellow
|
138
|
+
end
|
139
|
+
rescue JSON::ParserError => e
|
140
|
+
say "๐จ Failed to parse docker compose ps output as JSON: #{e.message}", :red
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# 9. Check Redis readiness with retries
|
145
|
+
say "๐ Checking Redis health with retries...", :cyan
|
146
|
+
|
147
|
+
max_attempts = 10
|
148
|
+
attempt = 0
|
149
|
+
success = false
|
150
|
+
|
151
|
+
while attempt < max_attempts
|
152
|
+
attempt += 1
|
153
|
+
healthcheck = ssh.exec!("docker exec $(docker ps -qf name=redis) redis-cli --no-auth-warning -a #{redis_defaults[:redis_password]} PING")
|
154
|
+
|
155
|
+
if healthcheck.strip == "PONG"
|
156
|
+
say "โ
Redis is up and responding to PING! (attempt #{attempt})", :green
|
157
|
+
success = true
|
158
|
+
|
159
|
+
redis_url = build_redis_url(filled_options, redis_defaults)
|
160
|
+
say "๐ Your REDIS_URL is:\t", :cyan
|
161
|
+
say redis_url, :green
|
162
|
+
break
|
163
|
+
else
|
164
|
+
say "โณ Redis not ready yet, retrying in 5 seconds... (#{attempt}/#{max_attempts})", :yellow
|
165
|
+
sleep 5
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
unless success
|
170
|
+
say "โ Redis did not become ready after #{max_attempts} attempts.", :red
|
171
|
+
end
|
172
|
+
|
173
|
+
# 10. Allow Redis port through firewall (ufw)
|
174
|
+
say "๐ก๏ธ Configuring firewall to allow Redis (port #{redis_defaults[:redis_port]})...", :cyan
|
175
|
+
output = ssh.exec! <<~EOH
|
176
|
+
if command -v ufw >/dev/null; then
|
177
|
+
if ! sudo ufw status | grep -q "#{redis_defaults[:redis_port]}"; then
|
178
|
+
sudo ufw allow #{redis_defaults[:redis_port]}
|
179
|
+
else
|
180
|
+
echo "๐ก Port #{redis_defaults[:redis_port]} is already allowed in ufw."
|
181
|
+
fi
|
182
|
+
else
|
183
|
+
echo "โ ๏ธ ufw not found. Skipping firewall configuration."
|
184
|
+
fi
|
185
|
+
EOH
|
186
|
+
say output
|
187
|
+
|
188
|
+
say "โ
Redis setup completed successfully!", :green
|
189
|
+
end
|
190
|
+
|
191
|
+
def perform_rollback(ssh, defaults)
|
192
|
+
output = ssh.exec! <<~EOH
|
193
|
+
set -e
|
194
|
+
|
195
|
+
BASE_DIR="$HOME/docker/redis"
|
196
|
+
BACKUP_DIR="/usr/local/backups"
|
197
|
+
SCRIPT_ID="setup_redis_docker"
|
198
|
+
AFTER_FILE="${BACKUP_DIR}/${SCRIPT_ID}.after"
|
199
|
+
|
200
|
+
if [ -f "$AFTER_FILE" ]; then
|
201
|
+
echo "๐ Stopping and removing docker containers..."
|
202
|
+
cd "$BASE_DIR"
|
203
|
+
docker compose down -v || true
|
204
|
+
|
205
|
+
echo "๐งน Cleaning up files..."
|
206
|
+
rm -rf "$BASE_DIR"
|
207
|
+
sudo rm -f "$AFTER_FILE"
|
208
|
+
|
209
|
+
if command -v ufw >/dev/null; then
|
210
|
+
echo "๐ก๏ธ Removing Redis port from firewall..."
|
211
|
+
sudo ufw delete allow #{defaults[:redis_port]} || true
|
212
|
+
fi
|
213
|
+
else
|
214
|
+
echo "๐ก Nothing to rollback"
|
215
|
+
fi
|
216
|
+
|
217
|
+
echo "โ
Rollback completed"
|
218
|
+
EOH
|
219
|
+
|
220
|
+
say output
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def upload_file(ssh, content, remote_path)
|
225
|
+
escaped = Shellwords.escape(content)
|
226
|
+
ssh.exec!("mkdir -p #{File.dirname(remote_path)}")
|
227
|
+
ssh.exec!("echo #{escaped} > #{remote_path}")
|
228
|
+
end
|
229
|
+
|
230
|
+
def build_redis_url(filled_options, redis_defaults)
|
231
|
+
password = redis_defaults[:redis_password]
|
232
|
+
host = filled_options[:server_ip]
|
233
|
+
port = redis_defaults[:redis_port]
|
234
|
+
|
235
|
+
"redis://:#{password}@#{host}:#{port}/0"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
data/lib/kitsune/kit/defaults.rb
CHANGED
@@ -19,7 +19,7 @@ module Kitsune
|
|
19
19
|
user: "postgres",
|
20
20
|
password: "secret",
|
21
21
|
port: "5432",
|
22
|
-
image: "postgres:
|
22
|
+
image: "postgres:17"
|
23
23
|
}.freeze
|
24
24
|
|
25
25
|
SYSTEM = {
|
@@ -32,6 +32,11 @@ module Kitsune
|
|
32
32
|
enable_do_metrics: true
|
33
33
|
}.freeze
|
34
34
|
|
35
|
+
REDIS = {
|
36
|
+
port: "6379",
|
37
|
+
password: "redis:7.2"
|
38
|
+
}.freeze
|
39
|
+
|
35
40
|
def self.infra
|
36
41
|
{
|
37
42
|
droplet_name: ENV.fetch('DROPLET_NAME', DROPLET[:droplet_name]),
|
@@ -62,6 +67,13 @@ module Kitsune
|
|
62
67
|
}
|
63
68
|
end
|
64
69
|
|
70
|
+
def self.redis
|
71
|
+
{
|
72
|
+
redis_port: ENV.fetch("REDIS_PORT", REDIS[:port]),
|
73
|
+
redis_password: ENV.fetch("REDIS_PASSWORD", REDIS[:password])
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
65
77
|
def self.system
|
66
78
|
{
|
67
79
|
swap_size_gb: ENV.fetch("SWAP_SIZE_GB", SYSTEM[:swap_size_gb]).to_i,
|
data/lib/kitsune/kit/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitsune-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Omar Herrera
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
@@ -184,6 +184,7 @@ files:
|
|
184
184
|
- kitsune-kit-logo.jpg
|
185
185
|
- lib/kitsune/blueprints/.env.template
|
186
186
|
- lib/kitsune/blueprints/docker/postgres.yml
|
187
|
+
- lib/kitsune/blueprints/docker/redis.yml
|
187
188
|
- lib/kitsune/blueprints/kit.env.template
|
188
189
|
- lib/kitsune/kit.rb
|
189
190
|
- lib/kitsune/kit/cli.rb
|
@@ -197,6 +198,7 @@ files:
|
|
197
198
|
- lib/kitsune/kit/commands/setup_docker_prereqs.rb
|
198
199
|
- lib/kitsune/kit/commands/setup_firewall.rb
|
199
200
|
- lib/kitsune/kit/commands/setup_postgres_docker.rb
|
201
|
+
- lib/kitsune/kit/commands/setup_redis_docker.rb
|
200
202
|
- lib/kitsune/kit/commands/setup_swap.rb
|
201
203
|
- lib/kitsune/kit/commands/setup_unattended.rb
|
202
204
|
- lib/kitsune/kit/commands/setup_user.rb
|