kitsune-kit 0.1.0 → 0.2.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 +1 -1
- data/bin/kit +0 -1
- data/lib/kitsune/blueprints/.env.template +8 -3
- data/lib/kitsune/blueprints/docker/postgres.yml +7 -0
- data/lib/kitsune/kit/cli.rb +9 -0
- data/lib/kitsune/kit/commands/bootstrap.rb +16 -8
- data/lib/kitsune/kit/commands/bootstrap_docker.rb +1 -1
- data/lib/kitsune/kit/commands/setup_do_metrics.rb +123 -0
- data/lib/kitsune/kit/commands/setup_docker_prereqs.rb +1 -0
- data/lib/kitsune/kit/commands/setup_postgres_docker.rb +8 -6
- data/lib/kitsune/kit/commands/setup_swap.rb +151 -0
- data/lib/kitsune/kit/defaults.rb +24 -0
- data/lib/kitsune/kit/env_loader.rb +2 -2
- data/lib/kitsune/kit/version.rb +1 -1
- metadata +88 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56c28afb6d454bee7e7751b75bfa3c131183fed868f158a324de8d804e54dab3
|
4
|
+
data.tar.gz: 2ca2b272f8bcfc12a92736aba334f4d70139cf0f5e3988a65c419ff52c644e6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f90bb7fec9592df584b627f0dc7a66df6da61ce70b4c2cdf4028990db77c53a6f5e965b456d1edb031551ca9f9510302261c24579e88a5b231b27e934de024f1
|
7
|
+
data.tar.gz: d423fab92de78e0c2468bbf2d33eac4d1ea9115253f41dbf6e5f56a39e9dded302b66672753e9b02d130cf91a8acc0f203fd393dcdfd4e006798b361d94a6f4f
|
data/README.md
CHANGED
data/bin/kit
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# DigitalOcean Droplet
|
1
|
+
# DigitalOcean Droplet
|
2
2
|
DO_API_TOKEN=
|
3
3
|
DROPLET_NAME=
|
4
4
|
REGION=
|
@@ -6,12 +6,17 @@ SIZE=
|
|
6
6
|
IMAGE=
|
7
7
|
SSH_KEY_ID=
|
8
8
|
TAG_NAME=
|
9
|
+
ENABLE_DO_METRICS=true
|
9
10
|
|
10
|
-
# SSH
|
11
|
+
# SSH
|
11
12
|
SSH_KEY_PATH=
|
12
13
|
# SSH_PORT=22 (optional)
|
13
14
|
|
14
|
-
#
|
15
|
+
# System
|
16
|
+
SWAP_SIZE_GB=2
|
17
|
+
DISABLE_SWAP=false
|
18
|
+
|
19
|
+
# PostgreSQL Docker
|
15
20
|
POSTGRES_DB=
|
16
21
|
POSTGRES_USER=
|
17
22
|
POSTGRES_PASSWORD=
|
@@ -8,6 +8,9 @@ services:
|
|
8
8
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
9
9
|
ports:
|
10
10
|
- "${POSTGRES_PORT:-5432}:5432"
|
11
|
+
command: postgres -c listen_addresses='*'
|
12
|
+
networks:
|
13
|
+
- private
|
11
14
|
volumes:
|
12
15
|
- pgdata:/var/lib/postgresql/data
|
13
16
|
healthcheck:
|
@@ -18,3 +21,7 @@ services:
|
|
18
21
|
|
19
22
|
volumes:
|
20
23
|
pgdata:
|
24
|
+
|
25
|
+
networks:
|
26
|
+
private:
|
27
|
+
driver: bridge
|
data/lib/kitsune/kit/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "thor"
|
2
|
+
require "colorize"
|
2
3
|
require_relative "env_loader"
|
3
4
|
require_relative "commands/init"
|
4
5
|
require_relative "commands/switch_env"
|
@@ -6,6 +7,8 @@ require_relative "commands/provision"
|
|
6
7
|
require_relative "commands/setup_user"
|
7
8
|
require_relative "commands/setup_firewall"
|
8
9
|
require_relative "commands/setup_unattended"
|
10
|
+
require_relative "commands/setup_swap"
|
11
|
+
require_relative "commands/setup_do_metrics"
|
9
12
|
require_relative "commands/bootstrap"
|
10
13
|
require_relative "commands/setup_docker_prereqs"
|
11
14
|
require_relative "commands/install_docker_engine"
|
@@ -42,6 +45,12 @@ module Kitsune
|
|
42
45
|
desc "setup_unattended SUBCOMMAND", "Configure or rollback unattended-upgrades"
|
43
46
|
subcommand "setup_unattended", Kitsune::Kit::Commands::SetupUnattended
|
44
47
|
|
48
|
+
desc "setup_swap SUBCOMMAND", "Configure or rollback swap memory"
|
49
|
+
subcommand "setup_swap", Kitsune::Kit::Commands::SetupSwap
|
50
|
+
|
51
|
+
desc "setup_do_metrics SUBCOMMAND", "Install or rollback DigitalOcean Metrics Agent"
|
52
|
+
subcommand "setup_do_metrics", Kitsune::Kit::Commands::SetupDoMetrics
|
53
|
+
|
45
54
|
desc "bootstrap SUBCOMMAND", "Run full server setup or rollback"
|
46
55
|
subcommand "bootstrap", Kitsune::Kit::Commands::Bootstrap
|
47
56
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "thor"
|
2
|
-
require "
|
2
|
+
require "stringio"
|
3
3
|
require_relative "../defaults"
|
4
4
|
require_relative "../options_builder"
|
5
5
|
require_relative "../provisioner"
|
@@ -42,6 +42,8 @@ module Kitsune
|
|
42
42
|
run_cli("setup_user create", droplet_ip, filled_options)
|
43
43
|
run_cli("setup_firewall create", droplet_ip, filled_options)
|
44
44
|
run_cli("setup_unattended create", droplet_ip, filled_options)
|
45
|
+
run_cli("setup_swap create", droplet_ip, filled_options)
|
46
|
+
run_cli("setup_do_metrics create", droplet_ip, filled_options)
|
45
47
|
end
|
46
48
|
|
47
49
|
def rollback_sequence(filled_options)
|
@@ -60,6 +62,8 @@ module Kitsune
|
|
60
62
|
droplet_ip = provisioner.send(:public_ip, droplet)
|
61
63
|
say "→ Using Droplet IP: #{droplet_ip}", :cyan
|
62
64
|
|
65
|
+
run_cli("setup_do_metrics rollback", droplet_ip, filled_options)
|
66
|
+
|
63
67
|
if ssh_accessible?(droplet_ip, filled_options)
|
64
68
|
run_cli("setup_unattended rollback", droplet_ip, filled_options)
|
65
69
|
run_cli("setup_firewall rollback", droplet_ip, filled_options)
|
@@ -67,6 +71,7 @@ module Kitsune
|
|
67
71
|
say "⏭️ Skipping unattended-upgrades and firewall rollback (no deploy user)", :yellow
|
68
72
|
end
|
69
73
|
|
74
|
+
run_cli("setup_swap rollback", droplet_ip, filled_options)
|
70
75
|
run_cli("setup_user rollback", droplet_ip, filled_options)
|
71
76
|
|
72
77
|
unless filled_options[:keep_server]
|
@@ -78,18 +83,21 @@ module Kitsune
|
|
78
83
|
end
|
79
84
|
|
80
85
|
def fetch_droplet_ip
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
out = StringIO.new
|
87
|
+
$stdout = out
|
88
|
+
begin
|
89
|
+
Kitsune::Kit::CLI.start(["provision", "create"])
|
90
|
+
ensure
|
91
|
+
$stdout = STDOUT
|
84
92
|
end
|
85
|
-
|
86
|
-
ip =
|
87
|
-
abort "❌ Could not detect droplet IP!" if ip.empty?
|
93
|
+
|
94
|
+
ip = out.string[/(\d{1,3}\.){3}\d{1,3}/]
|
95
|
+
abort "❌ Could not detect droplet IP!" if ip.nil? || ip.empty?
|
88
96
|
ip
|
89
97
|
end
|
90
98
|
|
91
99
|
def run_cli(command, droplet_ip, filled_options)
|
92
|
-
say "▶️ Running: kitsune kit #{command} --server-ip #{droplet_ip}", :blue
|
100
|
+
say "\n▶️ Running: kitsune kit #{command} --server-ip #{droplet_ip}", :blue
|
93
101
|
subcommand, action = command.split(" ", 2)
|
94
102
|
Kitsune::Kit::CLI.start([
|
95
103
|
subcommand, action,
|
@@ -47,7 +47,7 @@ module Kitsune
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def run_cli(command, filled_options)
|
50
|
-
say "▶️ Running: kitsune kit #{command} --server-ip #{filled_options[:server_ip]}", :blue
|
50
|
+
say "\n▶️ Running: kitsune kit #{command} --server-ip #{filled_options[:server_ip]}", :blue
|
51
51
|
|
52
52
|
subcommand, action = command.split(" ", 2)
|
53
53
|
Kitsune::Kit::CLI.start([
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "net/ssh"
|
3
|
+
require_relative "../defaults"
|
4
|
+
require_relative "../options_builder"
|
5
|
+
|
6
|
+
module Kitsune
|
7
|
+
module Kit
|
8
|
+
module Commands
|
9
|
+
class SetupDoMetrics < Thor
|
10
|
+
namespace "setup_do_metrics"
|
11
|
+
|
12
|
+
class_option :server_ip, aliases: "-s", required: true, desc: "Server IP address"
|
13
|
+
class_option :ssh_port, aliases: "-p", desc: "SSH port"
|
14
|
+
class_option :ssh_key_path, aliases: "-k", desc: "SSH private key path"
|
15
|
+
|
16
|
+
desc "create", "Install and enable the DigitalOcean Metrics Agent"
|
17
|
+
def create
|
18
|
+
unless Kitsune::Kit::Defaults.metrics[:enable_do_metrics]
|
19
|
+
say "⚠️ DigitalOcean Metrics Agent setup is disabled via ENABLE_DO_METRICS=false", :yellow
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
24
|
+
options,
|
25
|
+
required: [:server_ip],
|
26
|
+
defaults: Kitsune::Kit::Defaults.ssh
|
27
|
+
)
|
28
|
+
|
29
|
+
with_ssh(filled_options) do |ssh|
|
30
|
+
install_agent(ssh)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "rollback", "Uninstall the DigitalOcean Metrics Agent"
|
35
|
+
def rollback
|
36
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
37
|
+
options,
|
38
|
+
required: [:server_ip],
|
39
|
+
defaults: Kitsune::Kit::Defaults.ssh
|
40
|
+
)
|
41
|
+
|
42
|
+
with_ssh(filled_options) do |ssh|
|
43
|
+
uninstall_agent(ssh)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
no_commands do
|
48
|
+
def with_ssh(filled_options)
|
49
|
+
Net::SSH.start(
|
50
|
+
filled_options[:server_ip],
|
51
|
+
"deploy",
|
52
|
+
port: filled_options[:ssh_port],
|
53
|
+
keys: [File.expand_path(filled_options[:ssh_key_path])],
|
54
|
+
non_interactive: true,
|
55
|
+
timeout: 5
|
56
|
+
) do |ssh|
|
57
|
+
yield ssh
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def install_agent(ssh)
|
62
|
+
marker = "/usr/local/backups/setup_do_metrics.after"
|
63
|
+
|
64
|
+
script = <<~BASH
|
65
|
+
set -e
|
66
|
+
sudo mkdir -p /usr/local/backups
|
67
|
+
|
68
|
+
if [ -f "#{marker}" ]; then
|
69
|
+
echo "🔁 Metrics Agent already installed, skipping."
|
70
|
+
exit 0
|
71
|
+
fi
|
72
|
+
|
73
|
+
echo "✍🏻 Installing DigitalOcean Metrics Agent..."
|
74
|
+
curl -sSL https://repos.insights.digitalocean.com/install.sh | sudo bash
|
75
|
+
|
76
|
+
sudo touch "#{marker}"
|
77
|
+
echo "✅ Metrics Agent installed"
|
78
|
+
|
79
|
+
ps aux | grep do-agent | grep -v grep || echo "⚠️ do-agent process not found"
|
80
|
+
BASH
|
81
|
+
|
82
|
+
say ssh.exec!(script)
|
83
|
+
end
|
84
|
+
|
85
|
+
def uninstall_agent(ssh)
|
86
|
+
marker = "/usr/local/backups/setup_do_metrics.after"
|
87
|
+
|
88
|
+
script = <<~BASH
|
89
|
+
set -e
|
90
|
+
|
91
|
+
if [ ! -f "#{marker}" ]; then
|
92
|
+
echo "💡 No marker for metrics agent found. Skipping rollback."
|
93
|
+
exit 0
|
94
|
+
fi
|
95
|
+
|
96
|
+
echo "🧹 Uninstalling DigitalOcean Metrics Agent..."
|
97
|
+
|
98
|
+
if dpkg -l | grep -q do-agent; then
|
99
|
+
echo "📦 Removing do-agent package..."
|
100
|
+
sudo apt-get remove --purge -y do-agent
|
101
|
+
else
|
102
|
+
echo "💡 do-agent is not installed, skipping package removal."
|
103
|
+
fi
|
104
|
+
|
105
|
+
if systemctl list-unit-files | grep -q do-agent.service; then
|
106
|
+
echo "✍🏻 Stopping do-agent service..."
|
107
|
+
sudo systemctl stop do-agent || true
|
108
|
+
sudo systemctl disable do-agent || true
|
109
|
+
else
|
110
|
+
echo "💡 do-agent.service not found in systemd, skipping stop/disable"
|
111
|
+
fi
|
112
|
+
|
113
|
+
sudo rm -f "#{marker}"
|
114
|
+
echo "✅ Metrics Agent removed"
|
115
|
+
BASH
|
116
|
+
|
117
|
+
say ssh.exec!(script)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -86,6 +86,7 @@ module Kitsune
|
|
86
86
|
sudo apt-get install -y "\${TARGET_PKGS[@]}"
|
87
87
|
sudo touch "$AFTER_FILE" && echo " - marker created at $AFTER_FILE"
|
88
88
|
else
|
89
|
+
echo "🔁 Already set up, ensuring latest"
|
89
90
|
sudo apt-get update -y
|
90
91
|
sudo apt-get install -y "\${TARGET_PKGS[@]}"
|
91
92
|
echo "✅ Prerequisites are current"
|
@@ -46,6 +46,8 @@ module Kitsune
|
|
46
46
|
|
47
47
|
desc "rollback", "Remove PostgreSQL Docker setup from remote server"
|
48
48
|
def rollback
|
49
|
+
postgres_defaults = Kitsune::Kit::Defaults.postgres
|
50
|
+
|
49
51
|
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
50
52
|
options,
|
51
53
|
required: [:server_ip],
|
@@ -53,7 +55,7 @@ module Kitsune
|
|
53
55
|
)
|
54
56
|
|
55
57
|
with_ssh_connection(filled_options) do |ssh|
|
56
|
-
perform_rollback(ssh)
|
58
|
+
perform_rollback(ssh, postgres_defaults)
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
@@ -168,7 +170,7 @@ module Kitsune
|
|
168
170
|
success = true
|
169
171
|
break
|
170
172
|
else
|
171
|
-
say "⏳
|
173
|
+
say "⏳ PostgreSQL not ready yet, retrying in 5 seconds... (#{attempt + 1}/#{max_attempts})", :yellow
|
172
174
|
sleep 5
|
173
175
|
end
|
174
176
|
end
|
@@ -184,7 +186,7 @@ module Kitsune
|
|
184
186
|
if ! sudo ufw status | grep -q "#{postgres_defaults[:postgres_port]}"; then
|
185
187
|
sudo ufw allow #{postgres_defaults[:postgres_port]}
|
186
188
|
else
|
187
|
-
echo "
|
189
|
+
echo "💡 Port #{postgres_defaults[:postgres_port]} is already allowed in ufw."
|
188
190
|
fi
|
189
191
|
else
|
190
192
|
echo "⚠️ ufw not found. Skipping firewall configuration."
|
@@ -193,7 +195,7 @@ module Kitsune
|
|
193
195
|
ssh.exec!(firewall)
|
194
196
|
end
|
195
197
|
|
196
|
-
def perform_rollback(ssh)
|
198
|
+
def perform_rollback(ssh, postgres_defaults)
|
197
199
|
output = ssh.exec! <<~EOH
|
198
200
|
set -e
|
199
201
|
|
@@ -213,10 +215,10 @@ module Kitsune
|
|
213
215
|
|
214
216
|
if command -v ufw >/dev/null; then
|
215
217
|
echo "🛡️ Removing PostgreSQL port from firewall..."
|
216
|
-
sudo ufw delete allow
|
218
|
+
sudo ufw delete allow #{postgres_defaults[:postgres_port]} || true
|
217
219
|
fi
|
218
220
|
else
|
219
|
-
echo "
|
221
|
+
echo "💡 Nothing to rollback"
|
220
222
|
fi
|
221
223
|
|
222
224
|
echo "✅ Rollback completed"
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "net/ssh"
|
3
|
+
require_relative "../defaults"
|
4
|
+
require_relative "../options_builder"
|
5
|
+
|
6
|
+
module Kitsune
|
7
|
+
module Kit
|
8
|
+
module Commands
|
9
|
+
class SetupSwap < Thor
|
10
|
+
namespace "setup_swap"
|
11
|
+
|
12
|
+
class_option :server_ip, aliases: "-s", required: true, desc: "Server IP address"
|
13
|
+
class_option :ssh_port, aliases: "-p", desc: "SSH port"
|
14
|
+
class_option :ssh_key_path, aliases: "-k", desc: "SSH private key path"
|
15
|
+
class_option :size_gb, type: :numeric, desc: "Swap size in GB"
|
16
|
+
class_option :swappiness, type: :numeric, desc: "vm.swappiness value (0-100)"
|
17
|
+
|
18
|
+
desc "create", "Create and activate a swap file on the remote server"
|
19
|
+
def create
|
20
|
+
if Kitsune::Kit::Defaults.system[:disable_swap]
|
21
|
+
say "⚠️ Swap setup is disabled via DISABLE_SWAP=true", :yellow
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
26
|
+
options,
|
27
|
+
required: [:server_ip],
|
28
|
+
defaults: Kitsune::Kit::Defaults.system.merge(Kitsune::Kit::Defaults.ssh)
|
29
|
+
)
|
30
|
+
|
31
|
+
with_ssh_connection(filled_options) do |ssh|
|
32
|
+
perform_setup(ssh, filled_options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "rollback", "Disable and remove swap file from remote server"
|
37
|
+
def rollback
|
38
|
+
filled_options = Kitsune::Kit::OptionsBuilder.build(
|
39
|
+
options,
|
40
|
+
required: [:server_ip],
|
41
|
+
defaults: Kitsune::Kit::Defaults.system.merge(Kitsune::Kit::Defaults.ssh)
|
42
|
+
)
|
43
|
+
|
44
|
+
with_ssh_connection(filled_options) do |ssh|
|
45
|
+
perform_rollback(ssh)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
no_commands do
|
50
|
+
def with_ssh_connection(filled)
|
51
|
+
server = filled[:server_ip]
|
52
|
+
port = filled[:ssh_port]
|
53
|
+
key = File.expand_path(filled[:ssh_key_path])
|
54
|
+
|
55
|
+
say "🔑 Connecting as deploy@#{server}:#{port}", :green
|
56
|
+
Net::SSH.start(server, "deploy", port: port, keys: [key], non_interactive: true, timeout: 5) do |ssh|
|
57
|
+
yield ssh
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def perform_setup(ssh, filled_options)
|
62
|
+
size_gb = filled_options[:swap_size_gb].to_i
|
63
|
+
swappiness = filled_options[:swap_swappiness].to_i
|
64
|
+
|
65
|
+
abort "❌ Invalid swap size" if size_gb <= 0
|
66
|
+
|
67
|
+
script = <<~EOH
|
68
|
+
set -e
|
69
|
+
|
70
|
+
BACKUP_DIR="/usr/local/backups"
|
71
|
+
MARKER_FILE="${BACKUP_DIR}/setup_swap.after"
|
72
|
+
SWAPPINESS_BEFORE_FILE="${BACKUP_DIR}/setup_swap.swappiness.before"
|
73
|
+
|
74
|
+
if [ -f "$MARKER_FILE" ]; then
|
75
|
+
echo "🔁 Swap already set up, skipping."
|
76
|
+
exit 0
|
77
|
+
fi
|
78
|
+
|
79
|
+
SWAPFILE="/swapfile"
|
80
|
+
SIZE_GB=#{size_gb}
|
81
|
+
SIZE_BYTES=$((SIZE_GB * 1024 * 1024 * 1024))
|
82
|
+
|
83
|
+
echo "📝 Creating ${SIZE_GB}GB swap file..."
|
84
|
+
sudo fallocate -l ${SIZE_BYTES} ${SWAPFILE}
|
85
|
+
sudo chmod 600 ${SWAPFILE}
|
86
|
+
sudo mkswap ${SWAPFILE}
|
87
|
+
sudo swapon ${SWAPFILE}
|
88
|
+
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
89
|
+
|
90
|
+
# Backup swappiness if not already backed up
|
91
|
+
if [ ! -f "$SWAPPINESS_BEFORE_FILE" ]; then
|
92
|
+
CURRENT=$(cat /proc/sys/vm/swappiness)
|
93
|
+
echo "$CURRENT" | sudo tee "$SWAPPINESS_BEFORE_FILE"
|
94
|
+
echo "✍🏻 Backed up vm.swappiness: $CURRENT"
|
95
|
+
fi
|
96
|
+
|
97
|
+
echo "🛠️ Setting vm.swappiness=#{swappiness}"
|
98
|
+
sudo sysctl vm.swappiness=#{swappiness}
|
99
|
+
echo "vm.swappiness=#{swappiness}" | sudo tee -a /etc/sysctl.conf
|
100
|
+
|
101
|
+
sudo mkdir -p "$BACKUP_DIR"
|
102
|
+
sudo touch "$MARKER_FILE"
|
103
|
+
|
104
|
+
echo "✅ Swap file created and swappiness set"
|
105
|
+
free -h
|
106
|
+
EOH
|
107
|
+
|
108
|
+
say ssh.exec!(script)
|
109
|
+
end
|
110
|
+
|
111
|
+
def perform_rollback(ssh)
|
112
|
+
script = <<~EOH
|
113
|
+
set -e
|
114
|
+
|
115
|
+
BACKUP_DIR="/usr/local/backups"
|
116
|
+
MARKER_FILE="${BACKUP_DIR}/setup_swap.after"
|
117
|
+
SWAPPINESS_BEFORE_FILE="${BACKUP_DIR}/setup_swap.swappiness.before"
|
118
|
+
|
119
|
+
if [ ! -f "$MARKER_FILE" ]; then
|
120
|
+
echo "💡 No swap marker found, skipping rollback."
|
121
|
+
exit 0
|
122
|
+
fi
|
123
|
+
|
124
|
+
echo "🧹 Removing swap..."
|
125
|
+
sudo swapoff /swapfile || true
|
126
|
+
sudo rm -f /swapfile
|
127
|
+
sudo sed -i '/\\/swapfile none swap sw 0 0/d' /etc/fstab
|
128
|
+
sudo rm -f "$MARKER_FILE"
|
129
|
+
|
130
|
+
if [ -f "$SWAPPINESS_BEFORE_FILE" ]; then
|
131
|
+
ORIGINAL=$(cat "$SWAPPINESS_BEFORE_FILE")
|
132
|
+
echo "🔁 Restoring vm.swappiness: $ORIGINAL"
|
133
|
+
sudo sysctl vm.swappiness=$ORIGINAL
|
134
|
+
sudo sed -i '/vm.swappiness=/d' /etc/sysctl.conf
|
135
|
+
echo "vm.swappiness=$ORIGINAL" | sudo tee -a /etc/sysctl.conf
|
136
|
+
sudo rm -f "$SWAPPINESS_BEFORE_FILE"
|
137
|
+
else
|
138
|
+
echo "💡 No swappiness backup found, skipping restore."
|
139
|
+
fi
|
140
|
+
|
141
|
+
echo "✅ Swap rollback completed"
|
142
|
+
free -h
|
143
|
+
EOH
|
144
|
+
|
145
|
+
say ssh.exec!(script)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/lib/kitsune/kit/defaults.rb
CHANGED
@@ -22,6 +22,16 @@ module Kitsune
|
|
22
22
|
image: "postgres:15"
|
23
23
|
}.freeze
|
24
24
|
|
25
|
+
SYSTEM = {
|
26
|
+
swap_size_gb: 2,
|
27
|
+
swap_swappiness: 10,
|
28
|
+
disable_swap: false
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
METRICS = {
|
32
|
+
enable_do_metrics: true
|
33
|
+
}.freeze
|
34
|
+
|
25
35
|
def self.infra
|
26
36
|
{
|
27
37
|
droplet_name: ENV.fetch('DROPLET_NAME', DROPLET[:droplet_name]),
|
@@ -51,6 +61,20 @@ module Kitsune
|
|
51
61
|
postgres_image: ENV.fetch('POSTGRES_IMAGE', POSTGRES[:image])
|
52
62
|
}
|
53
63
|
end
|
64
|
+
|
65
|
+
def self.system
|
66
|
+
{
|
67
|
+
swap_size_gb: ENV.fetch("SWAP_SIZE_GB", SYSTEM[:swap_size_gb]).to_i,
|
68
|
+
swap_swappiness: ENV.fetch("SWAP_SWAPPINESS", SYSTEM[:swap_swappiness]).to_i,
|
69
|
+
disable_swap: ENV.fetch("DISABLE_SWAP", SYSTEM[:disable_swap].to_s) == "true"
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.metrics
|
74
|
+
{
|
75
|
+
enable_do_metrics: ENV.fetch("ENABLE_DO_METRICS", METRICS[:enable_do_metrics].to_s) == "true"
|
76
|
+
}
|
77
|
+
end
|
54
78
|
end
|
55
79
|
end
|
56
80
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "dotenv"
|
2
|
-
|
3
2
|
module Kitsune
|
4
3
|
module Kit
|
5
4
|
class EnvLoader
|
@@ -19,7 +18,8 @@ module Kitsune
|
|
19
18
|
|
20
19
|
if found
|
21
20
|
Dotenv.load(found)
|
22
|
-
puts "🧪 Loaded Kitsune environment from #{found}"
|
21
|
+
puts "🧪 Loaded Kitsune environment from #{found.light_cyan}"
|
22
|
+
puts "=======================================================================\n".light_cyan
|
23
23
|
else
|
24
24
|
puts "⚠️ No Kitsune infra config found for environment '#{env}' (looked for infra.#{env}.env and infra.env)"
|
25
25
|
end
|
data/lib/kitsune/kit/version.rb
CHANGED
metadata
CHANGED
@@ -1,113 +1,169 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitsune-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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-
|
11
|
+
date: 2025-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: net-ssh
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '7.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '7.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: ed25519
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bcrypt_pbkdf
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '1.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: dotenv
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '3.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '3.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: droplet_kit
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.17'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.17'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: thor
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '1.3'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: colorize
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.0.4
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.0.4
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: pry
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.14'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.14'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-stack_explorer
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.6.0
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.6.0
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '3.12'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '3.12'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: aruba
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
102
158
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
159
|
+
version: '2.2'
|
104
160
|
type: :development
|
105
161
|
prerelease: false
|
106
162
|
version_requirements: !ruby/object:Gem::Requirement
|
107
163
|
requirements:
|
108
|
-
- - "
|
164
|
+
- - "~>"
|
109
165
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
166
|
+
version: '2.2'
|
111
167
|
description: Kitsune Kit is a CLI toolkit that automates the provisioning, configuration,
|
112
168
|
and Docker setup of remote servers, especially tailored for Ruby developers using
|
113
169
|
Kamal. Includes rollback features and multi-environment support.
|
@@ -137,9 +193,11 @@ files:
|
|
137
193
|
- lib/kitsune/kit/commands/install_docker_engine.rb
|
138
194
|
- lib/kitsune/kit/commands/postinstall_docker.rb
|
139
195
|
- lib/kitsune/kit/commands/provision.rb
|
196
|
+
- lib/kitsune/kit/commands/setup_do_metrics.rb
|
140
197
|
- lib/kitsune/kit/commands/setup_docker_prereqs.rb
|
141
198
|
- lib/kitsune/kit/commands/setup_firewall.rb
|
142
199
|
- lib/kitsune/kit/commands/setup_postgres_docker.rb
|
200
|
+
- lib/kitsune/kit/commands/setup_swap.rb
|
143
201
|
- lib/kitsune/kit/commands/setup_unattended.rb
|
144
202
|
- lib/kitsune/kit/commands/setup_user.rb
|
145
203
|
- lib/kitsune/kit/commands/switch_env.rb
|