Compare commits

...

2 commits

Author SHA1 Message Date
2840b6e221 Add option for archive and restore VMs 2025-08-13 10:21:46 +02:00
8bbf7d31a5 add ca service 2025-08-13 07:06:53 +02:00
13 changed files with 233 additions and 20 deletions

4
bin/admin/certbot-cert Normal file
View file

@ -0,0 +1,4 @@
#/usr/bin/env bash
certbot certonly --manual --preferred-challenges=dns -d "*.gurgul.org" -d "gurgul.org"

21
bin/admin/install-idf Normal file
View file

@ -0,0 +1,21 @@
if [ -z "$SUDO_USER" ]; then
echo "This script must be run within sudo."
exit 1
fi
# from says ~/esp
ESP=/pkg/esp
apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
sudo -u "$SUDO_USER" bash <<EOF
mkdir -p $ESP
cd $ESP
git clone -b v5.4.1 --recursive https://github.com/espressif/esp-idf.git
cd "$ESP/esp-idf"
export IDF_TOOLS_PATH="$ESP/esp-idf/.espressif"
./install.sh esp32,esp32c2,esp32c3,esp32c5,esp32c6,esp32c61,esp32h2,esp32p4,esp32s2,esp32s3
EOF

View file

@ -0,0 +1,2 @@
export IDF_TOOLS_PATH="/pkg/esp/esp-idf/.espressif"
. /pkg/esp/esp-idf/export.sh

6
bin/services/ca/Gemfile Normal file
View file

@ -0,0 +1,6 @@
source "https://rubygems.org"
ruby ">= 3.0"
gem "roda"
gem "puma"
gem "rackup"

View file

@ -0,0 +1,26 @@
GEM
remote: https://rubygems.org/
specs:
nio4r (2.7.4)
puma (6.6.1)
nio4r (~> 2.0)
rack (3.2.0)
rackup (2.2.1)
rack (>= 3)
roda (3.95.0)
rack
PLATFORMS
arm64-darwin-24
ruby
DEPENDENCIES
puma
rackup
roda
RUBY VERSION
ruby 3.4.5p51
BUNDLED WITH
2.6.9

12
bin/services/ca/app.rb Normal file
View file

@ -0,0 +1,12 @@
require "roda"
class App < Roda
# automatically sets application/json and encodes Ruby objects
plugin :json
route do |r|
r.get "hello" do
{ message: "world" }
end
end
end

View file

@ -0,0 +1,2 @@
require_relative "app"
run App.freeze.app

0
bin/services/ca/make Executable file
View file

View file

@ -0,0 +1,9 @@
bundle exec rackup -p 9292 -o 0.0.0.0
RACK_ENV=production bundle exec rackup -p 8080 -o 0.0.0.0
curl http://0.0.0.0:9292/hello --verbose

View file

@ -17,9 +17,11 @@ subcommand = ARGV.shift&.to_sym
arg1 = ARGV[0] && ARGV[0] !~ /^-/ ? ARGV.shift : nil
arg2 = ARGV[0] && ARGV[0] !~ /^-/ ? ARGV.shift : nil
$domains = ["mediacenter.lan"]
$ips = ["192.168.0.94"]
# $domains = ["mediacenter.lan"]
# $ips = ["192.168.0.94"]
$domains = ["testing.self"]
$ips = ["127.0.0.2"]
$ips = []
### Setting up for client
$cn = $domains.first

39
bin/vm
View file

@ -4,6 +4,10 @@ require 'optparse'
require 'ostruct'
require 'virtual-machine'
# Paramteters
# -env: DAT_VM_DATA=~/.cache/vm
# vm setup debian --arch "<host:arch64>" --name "<image_name: debian>"
options = OpenStruct.new
@ -18,6 +22,8 @@ OptionParser.new do |opt|
opt.on('--name NAME', 'Virtaul Machine name') do |name|
options.name = name
end
# --port (ssh port)
# --attached (do not leave the shell process)
# new from copy
# fetch from the server
end.parse!
@ -25,11 +31,40 @@ end.parse!
case subcommand
when :create
puts "Creating image...."
puts "vm create debian-copy --name debian"
puts "Creating image base on existing one...."
when :run
# same as setup but fetches image not
puts "Run the image or fetch and run...."
options[:distro] = parameter
VirtualMachine.run(options)
when :setup
options[:distro] = parameter
VirtualMachine.setup(options)
when :archive
# whole image or files that are not present in the archived
# --type files (zst all files by files)
# by default
#before start if should create index of files that are present on
# the vm, so later we can copy new files or changed
options[:distro] = parameter
VirtualMachine.archive(options)
when :appy
puts "appy chnages from VM to the host os"
when :restore
options[:distro] = parameter
VirtualMachine.restore(options)
#puts "download image from remote or if local copy exists then the local copy"
when :daemon
puts "setup a pprocess so i can attach to it"
# paramaters exatly as run/setup
when :status
puts "Print all images and status stopped/daemon(port)/running(port/)"
when :attach
puts "if not paramteres attaches to last used"
else
puts "Error not found #{options.type}"
end

View file

@ -2,13 +2,46 @@ require 'downloader'
require 'system'
require_relative 'data/resources/iso-images'
require 'vm/qemu'
require 'vm/archive'
module VirtualMachine
def self.distro(name, arch, type = :install)
ISO_URLS[:debian][:arm64][:install]
ISO_URLS[name][arch][type]
end
def self.setup(options)
def self.vm_root_path
ENV["DAT_VM_DATA"] || File.join(User.cache_path, "vm")
end
def self.vm_dir(options)
File.join(vm_root_path, "image", "#{options[:distro].to_s}-#{options[:arch].to_s}", options[:name])
end
def self.archive_dir(options)
File.join(vm_root_path, "archive", "#{options[:distro].to_s}-#{options[:arch].to_s}", options[:name])
end
def self.create_archive_path(options)
File.join(archive_dir(options), "archive.tar.zst")
end
def self.get_recent_archive_path(options)
File.join(archive_dir(options), "archive.tar.zst")
end
# https://artur.gurgul.pro/vm/
# https://artur.gurgul.pro/vm/debian-arm64/debian/archive.tar.zst
def self.vm_archive_url(options)
return nil unless ENV["DAT_VM_REPO_URL"]
end
def self.root_img_path(options)
File.join(vm_dir(options), "root.img")
end
def self.fill_defaults(options)
if options[:name] == nil
options[:name] = options[:distro]
end
@ -18,27 +51,51 @@ module VirtualMachine
else
options[:arch] = System.arch_to_symbol(options[:arch])
end
end
puts options
def self.archive(options)
fill_defaults(options)
Archive.create(vm_dir(options), out: create_archive_path(options))
end
distro = options[:distro]
type = :install
arch = options[:arch]
url = distro(name, arch, type)
def self.restore(options)
fill_defaults(options)
Archive.restore(get_recent_archive_path(options), vm_dir(options))
end
def self.run(options)
fill_defaults(options)
disk_img_path = root_img_path(options)
# TODO:
# - if image path not exists, check the cache
# - if cache do not exists try to download
puts "Starting image: #{disk_img_path}"
Qemu.launch(
options[:arch],
disk_img_path,
cpus: [1, System.cpus - 2].max,
detach: true
)
end
def self.setup(options)
fill_defaults(options)
Downloader.get(url) do |path|
disk_img_path = File.join(User.cache_path, "vm", distro.to_s, arch.to_s, options[:name], "root.img")
create_disk_image(disk_img_path, 15000)
puts path
puts disk_img_path
url = distro(options[:name], options[:arch], :install)
disk_img_path = root_img_path(options)
Downloader.get(url) do |path|
create_disk_image(disk_img_path, 64000)
Qemu.launch(
arch,
options[:arch],
disk_img_path,
cpus: [1, System.cpus - 2].max,
cdrom: path,
detach: false
detach: true
)
end
end

37
lib/vm/archive.rb Normal file
View file

@ -0,0 +1,37 @@
require "fileutils"
module Archive
def self.cmd(*cmd)
puts "cmd: #{cmd.join(" ")}"
# return
stdout, stderr, status = Open3.capture3(*cmd)
unless status.success?
warn "Command failed: #{cmd.join(' ')}"
warn stderr
exit status.exitstatus || 1
end
stdout
end
# it preserved sparsiveness
# gtar -S --sparse-version=2 -I 'zstd -T0 -19' -cpf test.tar.zst /Volumes/Projs/VM/VM-data/image/debian-arm64/debian/
# tar --zstd -xpf test.tar.zst -C ./r
def self.create(path, **options)
out = options[:out] || File.join(Dir.pwd, "archive.tar.zst")
FileUtils.mkdir_p(File.dirname(out))
cmd "gtar", "-S", "--sparse-version=2", "-I",
"zstd -T0 -19", "-cpf", out, "-C" , path, "."
end
def self.restore(file, path, **options)
puts file
puts path
puts options
FileUtils.mkdir_p(path)
cmd "gtar", "-S", "--sparse-version=2", "-I", "zstd", "-xpf",
file, "-C", path
end
end