mimas-postgresql 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '082013adafb7795ab1e364ae00e5c092f4b75c1485745fe1e2cd74e0c5ab2768'
4
- data.tar.gz: '0922ae80ccfb5863bf8bbfcf8f2f61a5b67ae46591490c9feb17d89299f1b7e2'
3
+ metadata.gz: bea84cbe83f0285815a8130ea675f80f09fe7583042b2004cff51af4828e7c1e
4
+ data.tar.gz: 29e4cc1be23d3c7c8134698ecd8a85671149123307316c83617eff019627ef7e
5
5
  SHA512:
6
- metadata.gz: 81f3a5e2ef7ae98132a7d2cb9c915d5b1de0ee59951bf8b07c0dba2f1516084b642d524fcacdd61e9b7be8f43a8a11dae00400950d6c9eee70d01a788d9d3a3e
7
- data.tar.gz: 7edc8d7066a4ac96ebe2b5dca9838aca15944b3e9d30c1a7941dcf0a60f6bc003277e16f9f1d369fd8b9dba12d98f3f7fcafb14b6874bffd1dc77783c00ccdde
6
+ metadata.gz: 8e9ed7a73b5ed61091c19e2cde5d3069afa5adcaf744f6d96791c669f5626c17ff3e3c775cbc4969c52e92738ac9d4d92e8ce6f6cf0aeee30d784340a816811a
7
+ data.tar.gz: b7712ba747f15a45a0ba30ba9e56062b343072a41d58e8b47ec01be6aa67c2412ac217a167118d38b93713c9f74a54a7d481895c523b742b37453008146d7b18
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026-present Ayush Newatia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -5,7 +5,7 @@ module Mimas
5
5
  class Configure < Mimas::CLI::Commands::BaseCommand
6
6
  desc "Install configuration files for PostgreSQL."
7
7
 
8
- argument :server_name, required: true, desc: "The name of the server to install PostgreSQL on"
8
+ argument :server_name, required: true, desc: "The name of the server to configure PostgreSQL on"
9
9
 
10
10
  option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
11
11
 
@@ -5,7 +5,7 @@ module Mimas
5
5
  class Console < Mimas::CLI::Commands::BaseCommand
6
6
  desc "Start the PostgreSQL console."
7
7
 
8
- argument :server_name, required: true, desc: "The name of the server to install PostgreSQL on"
8
+ argument :server_name, required: true, desc: "The name of the server"
9
9
 
10
10
  option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
11
11
 
@@ -6,7 +6,7 @@ module Mimas
6
6
  desc "Create a new database on the server."
7
7
 
8
8
  argument :db_name, required: true, desc: "The name of the database to create"
9
- argument :server_name, required: true, desc: "The name of the server to install PostgreSQL on"
9
+ argument :server_name, required: true, desc: "The name of the server"
10
10
 
11
11
  option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
12
12
  option :owner, aliases: ["-o"], desc: "The owner of the database. Omit to create a new role named after the database"
@@ -24,8 +24,9 @@ module Mimas
24
24
  say "Created a new role #{db_name.dup.bold.magenta} with password: #{password.bold.white}"
25
25
  say "Ensure you save this password as it cannot be displayed again."
26
26
  end
27
+ owner = options[:owner] || db_name
27
28
 
28
- session.run "sudo -u postgres psql -c \"CREATE DATABASE #{db_name} OWNER #{db_name};\"", capture: true
29
+ session.run "sudo -u postgres psql -c \"CREATE DATABASE #{db_name} OWNER #{owner};\"", capture: true
29
30
 
30
31
  say ""
31
32
  say "Created database named #{db_name.dup.bold.magenta}"
@@ -6,7 +6,7 @@ module Mimas
6
6
  desc "Create a new PostgreSQL role."
7
7
 
8
8
  argument :role_name, required: true, desc: "The name of the role to create"
9
- argument :server_name, required: true, desc: "The name of the server to install PostgreSQL on"
9
+ argument :server_name, required: true, desc: "The name of the server"
10
10
 
11
11
  option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
12
12
  option :password, aliases: ["-p"], desc: "The password for the role. Leave blank to autogenerate a secure password"
@@ -0,0 +1,25 @@
1
+ module Mimas
2
+ module Plugins
3
+ module PostgreSQL
4
+ module Commands
5
+ class PrepareBackups < Mimas::CLI::Commands::BaseCommand
6
+ desc "Install a backup script to trigger via cron"
7
+
8
+ argument :server_name, required: true, desc: "The name of the server to configure PostgreSQL on"
9
+
10
+ option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
11
+
12
+ def call(server_name:, **options)
13
+ server = Config.current.servers[server_name.to_sym]
14
+ sudo_user = options[:user]
15
+
16
+ server.install_backup_script(sudo_user: sudo_user)
17
+
18
+ say ""
19
+ say "PostgreSQL backups can now be scheduled via cron."
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -5,7 +5,7 @@ module Mimas
5
5
  class Setup < Mimas::CLI::Commands::BaseCommand
6
6
  desc "Install and configure PostgreSQL on the server."
7
7
 
8
- argument :server_name, required: true, desc: "The name of the server to install PostgreSQL on"
8
+ argument :server_name, required: true, desc: "The name of the server to setup PostgreSQL on"
9
9
 
10
10
  option :user, default: "admin", aliases: ["-u"], desc: "A user with sudo access"
11
11
 
@@ -15,6 +15,7 @@ module Mimas
15
15
 
16
16
  server.install_postgresql(sudo_user: sudo_user)
17
17
  server.configure_postgresql(sudo_user: sudo_user)
18
+ server.install_backup_script(sudo_user: sudo_user)
18
19
 
19
20
  say ""
20
21
  say "PostgreSQL has been installed and configured! 🎉"
@@ -1,7 +1,7 @@
1
1
  module Mimas
2
2
  module Plugins
3
3
  module PostgreSQL
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
6
6
  end
7
7
  end
@@ -5,12 +5,13 @@ module Mimas
5
5
 
6
6
  def register_commands(cli)
7
7
  cli.register "postgresql" do |pg|
8
- pg.register "install", Commands::Install
9
- pg.register "console", Commands::Console
10
- pg.register "configure", Commands::Configure
11
- pg.register "setup", Commands::Setup
12
- pg.register "create_db", Commands::CreateDB
13
- pg.register "create_role", Commands::CreateRole
8
+ pg.register "install", Commands::Install
9
+ pg.register "console", Commands::Console
10
+ pg.register "configure", Commands::Configure
11
+ pg.register "setup", Commands::Setup
12
+ pg.register "create_db", Commands::CreateDB
13
+ pg.register "create_role", Commands::CreateRole
14
+ pg.register "prepare_backups", Commands::PrepareBackups
14
15
  end
15
16
  end
16
17
 
@@ -32,6 +32,33 @@ module Mimas
32
32
  session.run "sudo systemctl restart postgresql"
33
33
  end
34
34
  end
35
+
36
+ def install_backup_script(sudo_user:)
37
+ ssh(self, user: sudo_user) do |session|
38
+ pg_home = Pathname.new("/").join("var", "lib", "postgresql")
39
+ private_key_file_name = "pg_dump_private_key.pem"
40
+
41
+ # Create certificate and private key for backups
42
+ session.run "sudo -u postgres bash -c \"cd ~; openssl req -x509 -newkey rsa:4096 -keyout #{private_key_file_name} -out pg_dump_certificate.pem -days 36500 -nodes -subj '/CN=PostgreSQL Backup Certificate'\""
43
+ session.run "sudo mv #{pg_home.join(private_key_file_name)} /tmp/"
44
+ session.run "sudo chmod 666 #{Pathname.new("/tmp").join(private_key_file_name)}"
45
+
46
+ session.download Pathname.new("/tmp").join(private_key_file_name).to_s, Pathname.new(".").join("tmp", private_key_file_name).to_s
47
+
48
+ session.run "sudo rm #{Pathname.new("/tmp").join(private_key_file_name)}"
49
+ session.run "sudo -u postgres bash -c 'mkdir -p #{pg_home.join("bin")}'"
50
+
51
+ backup_script = find_files("mimas_pg_backup.sh").first
52
+ session.upload backup_script, Pathname.new("/tmp").join("mimas_pg_backup").to_s
53
+
54
+ session.run "sudo mv #{Pathname.new("/tmp").join("mimas_pg_backup")} #{pg_home.join("bin/")}"
55
+ session.run "sudo chown postgres:postgres #{pg_home.join("bin", "mimas_pg_backup")}"
56
+ session.run "sudo chmod 700 #{pg_home.join("bin", "mimas_pg_backup")}"
57
+
58
+ say "The private key to decrypt backups has been downloaded to your project's `tmp/` folder. Please store this safely, ideally in a password manager!".bold
59
+ say "To schedule backups, run `/var/lib/postgresql/bin mimas_pg_backup -d DB_NAME -o OUTPUT_DIR"
60
+ end
61
+ end
35
62
  end
36
63
  end
37
64
  end
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ usage() {
6
+ cat << EOF
7
+ Usage: mimas_pg_backup -d DB_NAME -o OUTPUT_DIR
8
+
9
+ Options:
10
+ -d, --db-name DB_NAME The name of the database to backup
11
+ -o, --output DIR The output directory
12
+ -h, --help Print this help
13
+ EOF
14
+ }
15
+
16
+ db_name=""
17
+ output_dir=""
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ -d|--db-name)
22
+ [[ $# -ge 2 ]] || { echo "Error: --db-name requires an argument" >&2; exit 1; }
23
+ db_name="$2"
24
+ shift 2
25
+ ;;
26
+ -o|--output)
27
+ [[ $# -ge 2 ]] || { echo "Error: --output requires an argument" >&2; exit 1; }
28
+ output_dir="${2/%}"
29
+ shift 2
30
+ ;;
31
+ -h|--help)
32
+ usage
33
+ exit 0
34
+ ;;
35
+ *)
36
+ echo "Error: unknown option: $1" >&2
37
+ usage >&2
38
+ exit 1
39
+ ;;
40
+ esac
41
+ done
42
+
43
+ if [[ -z "$db_name" || -z "$output_dir" ]]; then
44
+ echo "Error: --db-name and --output are required" >&2
45
+ usage >&2
46
+ exit 1
47
+ fi
48
+
49
+ # Mimas will only retain the last 5 backups.
50
+ delete_expired_backups() {
51
+ local -a backups
52
+ local -a expired_backups
53
+
54
+ mapfile -t backups < <(
55
+ find $output_dir/*_backup_*.dump.enc -maxdepth 1 -type f -printf '%f\n' |
56
+ sort -r
57
+ )
58
+
59
+ if (( ${#backups[@]} > 5 )); then
60
+ expired_backups=("${backups[@]:5}")
61
+
62
+ for backup in "${expired_backups[@]}"; do
63
+ rm -- "$output_dir/$backup"
64
+ done
65
+ fi
66
+ }
67
+
68
+ delete_expired_backups
69
+
70
+ backup_name="${db_name}_backup_$(date -u '+%Y%m%d%H%M%S')"
71
+ certificate_path="/var/lib/postgresql/pg_dump_certificate.pem"
72
+ output_file="$output_dir/${backup_name}.dump.enc"
73
+
74
+ pg_dump \
75
+ --format=custom \
76
+ --username=postgres \
77
+ --dbname="$db_name" |
78
+ openssl smime \
79
+ -encrypt \
80
+ -aes256 \
81
+ -binary \
82
+ -outform DER \
83
+ -out "$output_file" \
84
+ "$certificate_path"
@@ -11,5 +11,6 @@ require_relative "mimas/plugins/postgresql/commands/configure"
11
11
  require_relative "mimas/plugins/postgresql/commands/setup"
12
12
  require_relative "mimas/plugins/postgresql/commands/create_db"
13
13
  require_relative "mimas/plugins/postgresql/commands/create_role"
14
+ require_relative "mimas/plugins/postgresql/commands/prepare_backups"
14
15
 
15
16
  Mimas::Plugins.register(Mimas::Plugins::PostgreSQL)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimas-postgresql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ayush Newatia
@@ -15,19 +15,20 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0.5'
18
+ version: '0.8'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0.5'
25
+ version: '0.8'
26
26
  email: ayush@hey.com
27
27
  executables: []
28
28
  extensions: []
29
29
  extra_rdoc_files: []
30
30
  files:
31
+ - LICENSE.txt
31
32
  - lib/mimas-postgresql.rb
32
33
  - lib/mimas/plugins/postgresql.rb
33
34
  - lib/mimas/plugins/postgresql/commands/configure.rb
@@ -35,10 +36,12 @@ files:
35
36
  - lib/mimas/plugins/postgresql/commands/create_db.rb
36
37
  - lib/mimas/plugins/postgresql/commands/create_role.rb
37
38
  - lib/mimas/plugins/postgresql/commands/install.rb
39
+ - lib/mimas/plugins/postgresql/commands/prepare_backups.rb
38
40
  - lib/mimas/plugins/postgresql/commands/setup.rb
39
41
  - lib/mimas/plugins/postgresql/version.rb
40
42
  - lib/mimas/plugins/server/console.rb
41
43
  - lib/mimas/plugins/server/postgresql.rb
44
+ - lib/mimas/plugins/templates/mimas_pg_backup.sh
42
45
  - lib/mimas/plugins/templates/postgresql/conf.d/01-mimas.conf
43
46
  - lib/mimas/plugins/templates/postgresql/pg_hba.conf
44
47
  - lib/mimas/plugins/templates/postgresql/pg_hba.d/99-mimas.conf
@@ -61,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
64
  - !ruby/object:Gem::Version
62
65
  version: '0'
63
66
  requirements: []
64
- rubygems_version: 4.0.18
67
+ rubygems_version: 4.0.16
65
68
  specification_version: 4
66
69
  summary: Install and manage PostgreSQL using Mimas
67
70
  test_files: []