mimas 0.1.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +106 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +346 -0
  7. data/Rakefile +4 -0
  8. data/bin/mimas +5 -0
  9. data/lib/mimas/archiver.rb +68 -0
  10. data/lib/mimas/base_command.rb +22 -0
  11. data/lib/mimas/cli.rb +22 -0
  12. data/lib/mimas/commands/console.rb +21 -0
  13. data/lib/mimas/commands/init.rb +63 -0
  14. data/lib/mimas/commands/install.rb +21 -0
  15. data/lib/mimas/commands/provision.rb +50 -0
  16. data/lib/mimas/commands/push.rb +28 -0
  17. data/lib/mimas/commands/setup/caddy.rb +18 -0
  18. data/lib/mimas/commands/setup/deploy_user.rb +16 -0
  19. data/lib/mimas/commands/setup/ruby.rb +17 -0
  20. data/lib/mimas/commands/setup.rb +10 -0
  21. data/lib/mimas/config.rb +124 -0
  22. data/lib/mimas/deployment/caddy.rb +39 -0
  23. data/lib/mimas/deployment/files.rb +51 -0
  24. data/lib/mimas/deployment/paths.rb +54 -0
  25. data/lib/mimas/deployment/ruby_app.rb +126 -0
  26. data/lib/mimas/deployment/static_site.rb +28 -0
  27. data/lib/mimas/deployment.rb +27 -0
  28. data/lib/mimas/hooks.rb +25 -0
  29. data/lib/mimas/plugins.rb +19 -0
  30. data/lib/mimas/scripts/configure_ruby.sh +19 -0
  31. data/lib/mimas/scripts/create_deploy_user.sh +30 -0
  32. data/lib/mimas/scripts/harden.sh +125 -0
  33. data/lib/mimas/scripts/install_caddy.sh +51 -0
  34. data/lib/mimas/scripts/install_ruby_prerequisites.sh +26 -0
  35. data/lib/mimas/server/caddy.rb +17 -0
  36. data/lib/mimas/server/console.rb +34 -0
  37. data/lib/mimas/server/deploy_user.rb +11 -0
  38. data/lib/mimas/server/harden.rb +20 -0
  39. data/lib/mimas/server/prerequisites.rb +25 -0
  40. data/lib/mimas/server/ruby.rb +37 -0
  41. data/lib/mimas/server.rb +37 -0
  42. data/lib/mimas/site.rb +24 -0
  43. data/lib/mimas/ssh.rb +78 -0
  44. data/lib/mimas/template.rb +28 -0
  45. data/lib/mimas/templates/Caddyfile.ruby.erb +12 -0
  46. data/lib/mimas/templates/Caddyfile.static.erb +15 -0
  47. data/lib/mimas/templates/caddy.service.erb +19 -0
  48. data/lib/mimas/templates/config.rb.erb +51 -0
  49. data/lib/mimas/templates/falcon.rb.erb +12 -0
  50. data/lib/mimas/templates/mimas.env.erb +2 -0
  51. data/lib/mimas/templates/puma.rb +11 -0
  52. data/lib/mimas/templates/systemd.service.erb +20 -0
  53. data/lib/mimas/terminal/ansi.rb +71 -0
  54. data/lib/mimas/terminal/printer.rb +14 -0
  55. data/lib/mimas/version.rb +3 -0
  56. data/lib/mimas.rb +48 -0
  57. data/mimas.gemspec +29 -0
  58. data/scripts/release +8 -0
  59. data/scripts/test +7 -0
  60. data/tmp/.keep +0 -0
  61. metadata +181 -0
@@ -0,0 +1,25 @@
1
+ module Mimas
2
+ class Hooks
3
+ POINTS = [ :before_push, :after_push ]
4
+
5
+ def initialize
6
+ @hooks = Hash[POINTS.zip([[], [], []])].freeze
7
+ end
8
+
9
+ def [](hook)
10
+ @hooks[hook]
11
+ end
12
+
13
+ def merge(with_hooks)
14
+ POINTS.each do |point|
15
+ @hooks[point].push(*with_hooks[point])
16
+ end
17
+ end
18
+
19
+ POINTS.each do |point|
20
+ define_method(point) do |&block|
21
+ @hooks[point] << block
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module Mimas
2
+ MUTEX = Mutex.new
3
+ private_constant :MUTEX
4
+
5
+ PLUGINS = Set.new([])
6
+ private_constant :PLUGINS
7
+
8
+ module Plugins
9
+ extend self
10
+
11
+ def fetch
12
+ MUTEX.synchronize { PLUGINS }
13
+ end
14
+
15
+ def register(plugin)
16
+ MUTEX.synchronize { PLUGINS << plugin }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ cat << STRING >> ~/.profile
6
+
7
+ # Use chruby to auto-switch Ruby versions
8
+ source /usr/local/share/chruby/chruby.sh
9
+ source /usr/local/share/chruby/auto.sh
10
+ STRING
11
+
12
+ source /usr/local/share/chruby/chruby.sh
13
+ source /usr/local/share/chruby/auto.sh
14
+
15
+ echo 'gem: --no-document' >> ~/.gemrc
16
+
17
+ gem update --system
18
+ gem install bundler
19
+ bundle config set --global without 'development test'
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ export DEBIAN_FRONTEND=noninteractive
5
+
6
+ DEPLOY_USER="${DEPLOY_USER:-deploy}"
7
+
8
+ if ! id $DEPLOY_USER >/dev/null 2>&1; then
9
+ printf "Creating the $DEPLOY_USER user\n\n"
10
+ useradd $DEPLOY_USER -s /bin/bash -m
11
+ printf "$DEPLOY_USER user created\n\n"
12
+ else
13
+ printf "$DEPLOY_USER user exists. Configuring the user..."
14
+ fi
15
+
16
+ sudo passwd -ld $DEPLOY_USER
17
+ sudo loginctl enable-linger $DEPLOY_USER
18
+ sudo rsync --archive --chown=$DEPLOY_USER:$DEPLOY_USER ~/.ssh /home/$DEPLOY_USER
19
+
20
+ sudo touch /etc/logrotate.d/$DEPLOY_USER
21
+ sudo cat << STRING > /etc/logrotate.d/$DEPLOY_USER
22
+ /home/$DEPLOY_USER/http/*/logs/*.log {
23
+ daily
24
+ rotate 30
25
+ compress
26
+ missingok
27
+ }
28
+ STRING
29
+
30
+ printf "$DEPLOY_USER user configured\n\n"
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ export DEBIAN_FRONTEND=noninteractive
5
+
6
+ printf "Upgrading APT\n\n"
7
+ apt-get update && apt-get -y upgrade
8
+
9
+ printf "Enabling UFW\n\n"
10
+ ufw default deny incoming
11
+ ufw default allow outgoing
12
+ ufw allow OpenSSH
13
+ ufw allow http
14
+ ufw allow https
15
+ ufw --force enable
16
+ printf "UFW enabled\n\n"
17
+
18
+ printf "Creating the admin user\n\n"
19
+
20
+ if ! id admin >/dev/null 2>&1; then
21
+ # Add a new user, set the default shell, and create a home directory
22
+ useradd admin -s /bin/bash -m
23
+ fi
24
+
25
+ # Disable password login
26
+ passwd -ld admin
27
+ # Sync the private keys to allow SSH access
28
+ rsync --archive --chown=admin:admin ~/.ssh /home/admin
29
+
30
+ # Allow passwordless sudo for `admin`
31
+ echo "%admin $(cat /etc/hostname)=(root) NOPASSWD:ALL" > /etc/sudoers.d/admin
32
+
33
+ # Validate the modified sudoers file
34
+ if ! visudo -c -f /etc/sudoers.d/admin; then
35
+ printf "Failed to configure passwordless sudo for the admin user.\n\n"
36
+ exit 1
37
+ fi
38
+
39
+ printf "Installing fail2ban\n\n"
40
+ # Install fail2ban to block abusive IPs
41
+ apt-get install fail2ban -y
42
+ touch /etc/fail2ban/jail.local
43
+ cat << STRING >> /etc/fail2ban/jail.local
44
+ [DEFAULT]
45
+ bantime = 1d
46
+ findtime = 10m
47
+ maxretry = 5
48
+
49
+ [sshd]
50
+ enabled = true
51
+ STRING
52
+ systemctl enable fail2ban
53
+ printf "fail2ban installed and enabled\n\n"
54
+
55
+ printf "Enhanching kernel and system security...\n\n"
56
+ cat << STRING > /etc/sysctl.d/mimas-security.conf
57
+ # Disable ICMP redirects.
58
+ net.ipv4.conf.all.send_redirects = 0
59
+ net.ipv4.conf.default.send_redirects = 0
60
+ net.ipv4.conf.all.accept_redirects = 0
61
+ net.ipv4.conf.default.accept_redirects = 0
62
+ net.ipv6.conf.all.accept_redirects = 0
63
+ net.ipv6.conf.default.accept_redirects = 0
64
+
65
+ # ICMP noise hygiene.
66
+ net.ipv4.icmp_echo_ignore_broadcasts = 1
67
+ net.ipv4.icmp_ignore_bogus_error_responses = 1
68
+
69
+ # Drop spoofed/martian packets at the door.
70
+ net.ipv4.conf.all.rp_filter = 1
71
+ net.ipv4.conf.default.rp_filter = 1
72
+ net.ipv4.conf.all.accept_source_route = 0
73
+ net.ipv4.conf.default.accept_source_route = 0
74
+ net.ipv6.conf.all.accept_source_route = 0
75
+ net.ipv6.conf.default.accept_source_route = 0
76
+
77
+ # SYN-flood resilience as the server handles
78
+ # port 80/443 traffic from the internet.
79
+ net.ipv4.tcp_syncookies = 1
80
+ net.ipv4.tcp_synack_retries = 2
81
+ net.ipv4.tcp_syn_retries = 5
82
+
83
+ # Hide kernel internals from unprivileged eyes (kernel pointer leaks, dmesg,
84
+ # perf side channels) and disable unprivileged eBPF.
85
+ kernel.kptr_restrict = 2
86
+ kernel.dmesg_restrict = 1
87
+ kernel.perf_event_paranoid = 3
88
+ kernel.unprivileged_bpf_disabled = 1
89
+ net.core.bpf_jit_harden = 2
90
+
91
+ # Only processes with CAP_SYS_PTRACE may ptrace.
92
+ kernel.yama.ptrace_scope = 2
93
+
94
+ # Block runtime kernel replacement via kexec (one-way until reboot).
95
+ # CAVEAT: if you ever set up kdump crash dumps, remove this line first.
96
+ kernel.kexec_load_disabled = 1
97
+
98
+ # Filesystem link/dump hardening.
99
+ fs.protected_hardlinks = 1
100
+ fs.protected_symlinks = 1
101
+ fs.suid_dumpable = 0
102
+
103
+ # Turn off Martian logging
104
+ net.ipv4.conf.all.log_martians = 0
105
+ net.ipv4.conf.default.log_martians = 0
106
+ STRING
107
+
108
+ sysctl --system >/dev/null
109
+
110
+ printf "System security settings applied.\n\n"
111
+
112
+ printf "Installing molly-guard\n\n"
113
+ apt-get install molly-guard
114
+ printf "molly-guard installed.\n\n"
115
+
116
+ # Disable root login and password authentication
117
+ touch /etc/ssh/sshd_config.d/mimas.conf
118
+ cat << STRING >> /etc/ssh/sshd_config.d/mimas.conf
119
+ PermitRootLogin no
120
+ PasswordAuthentication no
121
+ STRING
122
+ systemctl restart ssh
123
+ passwd -ld root
124
+
125
+ printf "Password auth and root login disabled\n\n"
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ export DEBIAN_FRONTEND=noninteractive
5
+
6
+ # Update the apt source for Caddy
7
+ sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https
8
+ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor --no-tty --batch --yes -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
9
+ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
10
+ sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
11
+ sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
12
+ sudo apt-get update
13
+
14
+ # Download and install the Caddy binary
15
+ mkdir ~/tmp
16
+ cd ~/tmp
17
+ apt-get download caddy
18
+ mkdir -p caddy-unpack
19
+ dpkg -x $(find caddy*.deb) ~/tmp/caddy-unpack
20
+ sudo mv ~/tmp/caddy-unpack/usr/bin/caddy /usr/local/bin/caddy
21
+ cd ~/
22
+ rm -rf ~/tmp
23
+
24
+ DEPLOY_USER="${DEPLOY_USER:-deploy}"
25
+
26
+ # Give the deploy user sudo access to control the Caddy service only
27
+ sudo touch /etc/sudoers.d/$DEPLOY_USER
28
+
29
+ cat << STRING >> /etc/sudoers.d/$DEPLOY_USER
30
+ deploy $(cat /etc/hostname)=(root) NOPASSWD: /bin/systemctl reload caddy
31
+ deploy $(cat /etc/hostname)=(root) NOPASSWD: /bin/systemctl status caddy
32
+ STRING
33
+
34
+ sudo mkdir -p /home/$DEPLOY_USER/http
35
+ sudo touch /home/$DEPLOY_USER/http/Caddyfile
36
+ sudo touch /home/$DEPLOY_USER/http/caddy.global
37
+
38
+ sudo cat <<STRING >> /home/$DEPLOY_USER/http/caddy.global
39
+ {
40
+ servers {
41
+ protocols h1 h2
42
+ }
43
+ }
44
+ STRING
45
+
46
+ sudo cat <<STRING >> /home/$DEPLOY_USER/http/Caddyfile
47
+ import caddy.global
48
+ import */Caddyfile
49
+ STRING
50
+
51
+ sudo chown $DEPLOY_USER:$DEPLOY_USER -R /home/$DEPLOY_USER
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ export DEBIAN_FRONTEND=noninteractive
5
+
6
+ # Install Ruby prerequisites
7
+ sudo apt-get install $PREREQUISITES -y
8
+
9
+ # Install Ruby Install
10
+ wget https://github.com/postmodern/ruby-install/releases/download/v0.10.2/ruby-install-0.10.2.tar.gz
11
+ tar -xzvf ruby-install-0.10.2.tar.gz
12
+ cd ruby-install-0.10.2/
13
+ sudo make install
14
+ cd ..
15
+ rm ruby-install-0.10.2.tar.gz
16
+ rm -rf ruby-install-0.10.2/
17
+
18
+ # Install chruby
19
+ wget https://github.com/postmodern/chruby/releases/download/v0.3.9/chruby-0.3.9.tar.gz
20
+ tar -xzvf chruby-0.3.9.tar.gz
21
+ cd chruby-0.3.9/
22
+ sudo make install
23
+ cd ..
24
+ rm chruby-0.3.9.tar.gz
25
+ rm -rf chruby-0.3.9/
26
+
@@ -0,0 +1,17 @@
1
+ module Mimas
2
+ class Server
3
+ module Caddy
4
+ def install_caddy(sudo_user:)
5
+ ssh(self, user: sudo_user) do |session|
6
+ session.script("install_caddy", sudo: true, vars: { DEPLOY_USER: self.user })
7
+
8
+ caddy_service = template("caddy.service", deploy_user: self.user)
9
+ session.upload StringIO.new(caddy_service), "/tmp/caddy.service"
10
+ session.run "sudo mv /tmp/caddy.service /etc/systemd/system/caddy.service"
11
+
12
+ session.run "sudo systemctl daemon-reload && sudo systemctl enable --now caddy"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ module Mimas
2
+ class Server
3
+ module Console
4
+ def start_console(site)
5
+ console_command = site.console
6
+
7
+ system('stty cbreak -echo')
8
+ Net::SSH.start(host, user) do |session|
9
+ session.open_channel do |channel|
10
+ channel.request_pty do
11
+ channel.exec("cd #{current_path(site)} && /bin/bash -lc #{console_command}") do
12
+ channel.on_data do |_, data|
13
+ $stdout.print(data) if data
14
+ end
15
+
16
+ channel.on_extended_data do |_, data|
17
+ $stdout.print(data) if data
18
+ end
19
+
20
+ session.listen_to($stdin) do |stdin|
21
+ input = stdin.readpartial(1024)
22
+ channel.send_data(input) unless input.empty?
23
+ end
24
+ end
25
+ end
26
+ end
27
+ session.loop
28
+ end
29
+ ensure
30
+ system('stty sane')
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ module Mimas
2
+ class Server
3
+ module DeployUser
4
+ def setup_deploy_user(sudo_user:)
5
+ ssh(self, user: sudo_user) do |session|
6
+ session.script("create_deploy_user", sudo: true, vars: { DEPLOY_USER: self.user })
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module Mimas
2
+ class Server
3
+ module Harden
4
+ def harden
5
+ ssh(self, user: "root") do |session|
6
+ session.script("harden", vars: { DEPLOY_USER: self.user })
7
+
8
+ say "Rebooting server...".bold.blue
9
+ session.run "reboot.no-molly-guard"
10
+ rescue SSH::Session::NonZeroExitCode => e
11
+ say "Sorry, an error occured while hardening the server".bold.red
12
+ say e.to_s.bold.red
13
+ raise e
14
+ rescue Errno::ECONNRESET
15
+ # Triggered by reboot
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module Mimas
2
+ class Server
3
+ module Prerequisites
4
+ extend self
5
+
6
+ def for_ruby
7
+ %w[
8
+ xz-utils
9
+ build-essential
10
+ zlib1g-dev
11
+ libyaml-dev
12
+ libssl-dev
13
+ libncurses-dev
14
+ libffi-dev
15
+ rustc
16
+ libjemalloc-dev
17
+ ]
18
+ end
19
+
20
+ def utilities
21
+ %w[curl jq]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ module Mimas
2
+ class Server
3
+ module Ruby
4
+ def install_ruby_prerequisites(sudo_user:)
5
+ ssh(self, user: sudo_user) do |session|
6
+ prerequisites = Prerequisites.for_ruby + Prerequisites.utilities
7
+ prerequisites = prerequisites.join(" ")
8
+
9
+ session.script("install_ruby_prerequisites",
10
+ sudo: true,
11
+ vars: { PREREQUISITES: "'#{prerequisites}'" }
12
+ )
13
+ end
14
+ end
15
+
16
+ def install_ruby(version: Config.current.ruby_version)
17
+ ssh(self) do |session|
18
+ current_ruby = session.run "/usr/bin/env bash -lc 'which ruby'", capture: true, silent: true
19
+
20
+ if current_ruby != ""
21
+ ruby_grep = session.run "/usr/bin/env bash -lc 'chruby' | grep #{version}", capture: true, silent: true
22
+ if ruby_grep.size > 0
23
+ return say "Ruby #{version} is already installed!"
24
+ end
25
+ end
26
+
27
+ session.run "ruby-install --no-install-deps --cleanup #{version} -- --enable-yjit --with-jemalloc --disable-install-rdoc"
28
+ session.run "echo '#{version}' > ~/.ruby-version"
29
+
30
+ if current_ruby == ""
31
+ session.script("configure_ruby")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module Mimas
2
+ class Server
3
+ include SSH, Template, Terminal::Printer
4
+
5
+ # Server setup helpers
6
+ include Harden, DeployUser, Ruby, Caddy
7
+
8
+ attr_reader :name, :host, :user, :ssh_options
9
+
10
+ def initialize(name, args)
11
+ @name = name
12
+ @host = args[:host]
13
+ @user = args[:user]
14
+ @ssh_options = args.except(:host, :user)
15
+ end
16
+
17
+ def user_home
18
+ @user_home ||= Pathname.new(File.join("/", "home", @user.to_s))
19
+ end
20
+
21
+ def http_root
22
+ @http_root ||= user_home.join("http")
23
+ end
24
+
25
+ def user_systemd_path
26
+ @user_systemd_path ||= user_home.join(".config", "systemd", "user")
27
+ end
28
+
29
+ def site_root(site)
30
+ http_root.join("#{site.domain}")
31
+ end
32
+
33
+ def current_path(site)
34
+ site_root(site).join("current")
35
+ end
36
+ end
37
+ end
data/lib/mimas/site.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Mimas
2
+ class Site
3
+ attr_reader :name
4
+ def initialize(name, args)
5
+ @name = name
6
+ args[:services] ||= []
7
+ args[:deploy] ||= "bundle install"
8
+ args[:env] ||= ""
9
+ args[:healthcheck_path] ||= "/"
10
+
11
+ args.each do |key, value|
12
+ define_singleton_method(key) { value }
13
+ end
14
+ end
15
+
16
+ def static?
17
+ !ruby_app?
18
+ end
19
+
20
+ def ruby_app?
21
+ services.any?
22
+ end
23
+ end
24
+ end
data/lib/mimas/ssh.rb ADDED
@@ -0,0 +1,78 @@
1
+ module Mimas
2
+ module SSH
3
+ def ssh(server, user: nil, &block)
4
+ Session.new(server, user: user).perform(&block)
5
+ end
6
+
7
+ class Session
8
+ class NonZeroExitCode < StandardError
9
+ attr_reader :exit_code, :output
10
+ def initialize(command:, exit_code:, output:)
11
+ @command = command
12
+ @exit_code = exit_code
13
+ @output = output
14
+ end
15
+
16
+ def to_s
17
+ "'#{@command}' exited with code: #{@exit_code}"
18
+ end
19
+ end
20
+
21
+ def initialize(server, user:)
22
+ @server = server
23
+ @user = user || server.user
24
+ end
25
+
26
+ def perform(&block)
27
+ @ssh = Net::SSH.start(@server.host, @user, timeout: 60, **@server.ssh_options)
28
+ @hostname = run("cat /etc/hostname", capture: true).chomp
29
+ yield(self)
30
+ ensure
31
+ @ssh&.close
32
+ end
33
+
34
+ def run(command, capture: false, silent: false)
35
+ status = {}
36
+ output = ""
37
+ @ssh.exec!(command, status: status) do |channel, stream, data|
38
+ if stream == :stdout && capture
39
+ output << data
40
+ elsif stream == :stderr
41
+ print "#{data}".bold.red unless capture
42
+ else
43
+ print "#{data}".white unless capture
44
+ end
45
+ end
46
+
47
+ if status[:exit_code] != 0 && !silent
48
+ raise NonZeroExitCode.new(command: command, exit_code: status[:exit_code], output: output)
49
+ end
50
+
51
+ return output if capture
52
+ end
53
+
54
+ def upload(source_file, destination_file)
55
+ @ssh.scp.upload! source_file, destination_file
56
+ end
57
+
58
+ def script(name, sudo: false, vars: {})
59
+ filename = "#{name}.sh"
60
+ remote_location = "/tmp/#{filename}"
61
+
62
+ source_path = File.expand_path("./scripts/#{filename}", __dir__)
63
+ upload source_path, remote_location
64
+ run "chmod +x #{remote_location}"
65
+
66
+ vars = vars.to_a.map { it.join("=") }.join(" ")
67
+
68
+ exec_command = remote_location
69
+ exec_command = "#{vars} #{exec_command}".strip
70
+ exec_command = "sudo #{exec_command}" if sudo
71
+
72
+ run exec_command
73
+
74
+ run "rm #{remote_location}"
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ require "fileutils"
2
+
3
+ module Mimas
4
+ module Template
5
+ BASE_DIRECTORY = File.join(__dir__, "templates")
6
+
7
+ def template(file_name, dir: BASE_DIRECTORY, **vars)
8
+ template = read_template(file_name, dir: dir)
9
+ template.result_with_hash(vars)
10
+ end
11
+
12
+ def read_file(file_name, dir: BASE_DIRECTORY)
13
+ File.read(File.join(dir, file_name))
14
+ end
15
+
16
+ def copy_file(destination, source_file_name, rename: nil)
17
+ source = File.join(BASE_DIRECTORY, source_file_name)
18
+ FileUtils.copy(source, File.join(destination, rename || source_file_name))
19
+ end
20
+
21
+ private
22
+
23
+ def read_template(file_name, dir:)
24
+ file = File.read(File.join(dir, "#{file_name}.erb"))
25
+ ERB.new(file, trim_mode: "-")
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ <%= domain %> {
2
+ reverse_proxy {
3
+ to unix/<%= unix_socket %>
4
+
5
+ lb_try_duration 5s
6
+ }
7
+
8
+ log {
9
+ format console
10
+ output file <%= site_root %>/logs/caddy.log
11
+ }
12
+ }
@@ -0,0 +1,15 @@
1
+ <%= domain %> {
2
+ root <%= site_root %>/current/root
3
+ encode
4
+ file_server
5
+
6
+ handle_errors {
7
+ rewrite /404.html
8
+ file_server
9
+ }
10
+
11
+ log {
12
+ format console
13
+ output file <%= site_root %>/logs/caddy.log
14
+ }
15
+ }
@@ -0,0 +1,19 @@
1
+ [Unit]
2
+ Description=Caddy
3
+ Documentation=https://caddyserver.com/docs/
4
+ After=network.target network-online.target
5
+ Requires=network-online.target
6
+
7
+ [Service]
8
+ Type=notify
9
+ User=<%= deploy_user %>
10
+ ExecStart=/usr/local/bin/caddy run --environ --config /home/<%= deploy_user %>/http/Caddyfile
11
+ ExecReload=/usr/local/bin/caddy reload --config /home/<%= deploy_user %>/http/Caddyfile --force
12
+ TimeoutStopSec=5s
13
+ LimitNOFILE=1048576
14
+ PrivateTmp=true
15
+ ProtectSystem=full
16
+ AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
17
+
18
+ [Install]
19
+ WantedBy=multi-user.target