Merge branch 'main' of ssh://gurgul.pro/artur/environment
This commit is contained in:
commit
297d02ad00
81 changed files with 3110 additions and 54 deletions
4
bin/admin/certbot-cert
Normal file
4
bin/admin/certbot-cert
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#/usr/bin/env bash
|
||||||
|
|
||||||
|
certbot certonly --manual --preferred-challenges=dns -d "*.gurgul.org" -d "gurgul.org"
|
||||||
|
|
||||||
7
bin/admin/install-gui
Executable file
7
bin/admin/install-gui
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
## missing in the install script
|
||||||
|
apt install zsh curl
|
||||||
|
|
||||||
|
apt install sway libgtk-3-0 libasound2
|
||||||
|
|
||||||
|
wget https://github.com/zen-browser/desktop/releases/download/1.14.11b/zen.linux-x86_64.tar.xz
|
||||||
21
bin/admin/install-idf
Normal file
21
bin/admin/install-idf
Normal 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
|
||||||
|
|
||||||
2
bin/admin/install-idf-enable
Normal file
2
bin/admin/install-idf-enable
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export IDF_TOOLS_PATH="/pkg/esp/esp-idf/.espressif"
|
||||||
|
. /pkg/esp/esp-idf/export.sh
|
||||||
80
bin/admin/single-user
Executable file
80
bin/admin/single-user
Executable file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#!/bin/bash
|
||||||
|
## This script make autologin. If user has phisical access
|
||||||
|
## to the device we can trust him, otherwiese we require password
|
||||||
|
## for remote access
|
||||||
|
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Settings
|
||||||
|
USERNAME="user"
|
||||||
|
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "Please run this script as root." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
id "$USERNAME" &>/dev/null || { echo "User '$USERNAME' does not exist." >&2; exit 1; }
|
||||||
|
|
||||||
|
echo "Configuring passwordless sudo ONLY on local TTYs for $USERNAME"
|
||||||
|
echo
|
||||||
|
|
||||||
|
SUDOERS_FILE="/etc/sudoers.d/90-$USERNAME-sudo"
|
||||||
|
if [ ! -f "$SUDOERS_FILE" ]; then
|
||||||
|
echo "$USERNAME ALL=(ALL:ALL) ALL" > "$SUDOERS_FILE"
|
||||||
|
chmod 0440 "$SUDOERS_FILE"
|
||||||
|
visudo -cf "$SUDOERS_FILE" >/dev/null || { echo "sudoers validation failed"; exit 1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PAM: allow passwordless sudo on physical ttys, require password otherwise.
|
||||||
|
PAM_FILE="/etc/pam.d/sudo"
|
||||||
|
BACKUP_FILE="/etc/pam.d/sudo.bak"
|
||||||
|
|
||||||
|
if ! grep -q "BEGIN local TTY passwordless" "$PAM_FILE"; then
|
||||||
|
echo "Backing up $PAM_FILE to $BACKUP_FILE"
|
||||||
|
cp "$PAM_FILE" "$BACKUP_FILE"
|
||||||
|
|
||||||
|
# Insert at the top of the file:
|
||||||
|
# - If TTY matches /dev/ttyN (real VT), immediately permit auth (no password).
|
||||||
|
# - Otherwise fall through to the normal rules (which will ask for a password).
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# - pam_succeed_if.so is in the libpam-modules package on Debian/Ubuntu (ensure installed).
|
||||||
|
# - The 'success=done' short-circuits the auth stack on real TTYs.
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
cat > "$tmp" <<'PAMHEAD'
|
||||||
|
# --- BEGIN local TTY passwordless ---
|
||||||
|
# Passwordless sudo on real virtual consoles only:
|
||||||
|
# /dev/tty1, /dev/tty2, ... (NOT /dev/pts/* used by SSH)
|
||||||
|
auth [success=done default=ignore] pam_succeed_if.so tty =~ ^/dev/tty[0-9]+$
|
||||||
|
# --- END local TTY passwordless ---
|
||||||
|
PAMHEAD
|
||||||
|
cat "$PAM_FILE" >> "$tmp"
|
||||||
|
mv "$tmp" "$PAM_FILE"
|
||||||
|
echo "PAM updated. On SSH (/dev/pts/*) a password will be required."
|
||||||
|
else
|
||||||
|
echo "PAM sudo already has local TTY rule."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3) Autologin on tty1 (physical console)
|
||||||
|
echo "Configuring systemd autologin on tty1 for $USERNAME..."
|
||||||
|
mkdir -p /etc/systemd/system/getty@tty1.service.d
|
||||||
|
AUTOLOGIN_CONF="/etc/systemd/system/getty@tty1.service.d/override.conf"
|
||||||
|
AGETTY_BIN="$(command -v agetty || true)"
|
||||||
|
: "${AGETTY_BIN:=/sbin/agetty}"
|
||||||
|
|
||||||
|
cat > "$AUTOLOGIN_CONF" <<EOF
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=-$AGETTY_BIN --autologin $USERNAME --noclear %I \$TERM
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart getty@tty1
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "• $USERNAME will auto-login on tty1."
|
||||||
|
echo "• On real TTYs (/dev/ttyN), sudo won't prompt for a password."
|
||||||
|
echo "• Over SSH (/dev/pts/*), sudo will require the user's password."
|
||||||
28
bin/apas
Executable file
28
bin/apas
Executable file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
function lhash {
|
||||||
|
echo -n "${1}" | openssl dgst -sha512 | cut -d' ' -f2 | openssl dgst -md5 | cut -d' ' -f2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prompt user for input
|
||||||
|
read -p "Website: " url
|
||||||
|
read -p "Login: " login
|
||||||
|
read -s -p "Password: " password
|
||||||
|
echo
|
||||||
|
|
||||||
|
domain=$(echo "$url" | sed -E 's~https?://([^/]+).*~\1~')
|
||||||
|
hash=$(lhash "$login")
|
||||||
|
pass_path="web/${domain}/${hash}"
|
||||||
|
|
||||||
|
# Entry content
|
||||||
|
entry="${password}
|
||||||
|
url: ${url}
|
||||||
|
login: ${login}
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "$entry" | pass insert -m "$pass_path"
|
||||||
|
|
||||||
|
# url
|
||||||
|
# login
|
||||||
|
# tags
|
||||||
|
# note
|
||||||
7
bin/certbot
Executable file
7
bin/certbot
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
export PYTHONPATH="/pkg/certbot/4.2.0/local/lib/python3.11/dist-packages"
|
||||||
|
export PATH="/pkg/certbot/4.2.0/local/bin:$PATH"
|
||||||
|
|
||||||
|
/pkg/certbot/4.2.0/local/bin/certbot
|
||||||
|
|
||||||
98
bin/cht
Executable file
98
bin/cht
Executable file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import path from "path"
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
|
// DAT_ROOT should exists in ~/.zshrc-local
|
||||||
|
const indexPath = path.join(process.env["NOTES_DIR"], "")
|
||||||
|
const processFile = path.join(process.cwd(), process.argv[2])
|
||||||
|
|
||||||
|
|
||||||
|
const data = fs.readFileSync(processFile, 'utf8')
|
||||||
|
const jsonData = JSON.parse(data)
|
||||||
|
|
||||||
|
function wantSave(str) {
|
||||||
|
return typeof str == "string" && str.split("\n").length > 10
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveToFileSync(content, file) {
|
||||||
|
const dir = path.dirname(file);
|
||||||
|
try {
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(file, content, 'utf8')
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error saving file:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const toSave = jsonData.flatMap(o => {
|
||||||
|
const date = new Date(o.create_time * 1000)
|
||||||
|
|
||||||
|
// const formattedDate = date.toLocaleDateString('en-GB', {
|
||||||
|
// day: '2-digit',
|
||||||
|
// month: '2-digit',
|
||||||
|
// year: '2-digit',
|
||||||
|
// })
|
||||||
|
// return formattedDate
|
||||||
|
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const year = String(date.getFullYear()).slice(-2)
|
||||||
|
|
||||||
|
let baseNotePath = path.join(indexPath, "gpt", `${day}-${month}-${year}`, `${o.title}`)
|
||||||
|
|
||||||
|
let conversations = []
|
||||||
|
for (const [key, value] of Object.entries(o.mapping)) {
|
||||||
|
//console.log(key, value)
|
||||||
|
|
||||||
|
conversations.push({
|
||||||
|
path: path.join(baseNotePath, `${key}.json`),
|
||||||
|
content: JSON.stringify(value, null, 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
let parts = value?.message?.content.parts
|
||||||
|
if (Array.isArray(parts)) {
|
||||||
|
|
||||||
|
if (parts.length == 0) {
|
||||||
|
// skip
|
||||||
|
} else if (parts.length == 1) {
|
||||||
|
let fileName = path.join(baseNotePath, `${key}.md`)
|
||||||
|
let md = parts[0]
|
||||||
|
|
||||||
|
if (wantSave(md)) {
|
||||||
|
conversations.push({
|
||||||
|
path: fileName,
|
||||||
|
content: md
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (const [key, value] of parts.entries()) {
|
||||||
|
let fileName = path.join(baseNotePath, `${key}-${key+1}.md`)
|
||||||
|
let md = parts[key]
|
||||||
|
|
||||||
|
if (wantSave(md)) {
|
||||||
|
conversations.push({
|
||||||
|
path: fileName,
|
||||||
|
content: md
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//process.exit(-1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return conversations
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
for(const f of toSave) {
|
||||||
|
//for(const f of toSave.slice(0,5)) {
|
||||||
|
saveToFileSync(f.content,f.path)
|
||||||
|
}
|
||||||
17
bin/dat
17
bin/dat
|
|
@ -12,6 +12,7 @@ options = OpenStruct.new
|
||||||
|
|
||||||
# take the first so OptionParser will not see it
|
# take the first so OptionParser will not see it
|
||||||
subcommand = ARGV.shift&.to_sym
|
subcommand = ARGV.shift&.to_sym
|
||||||
|
options.name = ARGV[0] && ARGV[0] !~ /^-/ ? ARGV.shift : nil
|
||||||
|
|
||||||
OptionParser.new do |opt|
|
OptionParser.new do |opt|
|
||||||
opt.on('-i', '--install', 'Install dat for the user') { |o| options.type = :install }
|
opt.on('-i', '--install', 'Install dat for the user') { |o| options.type = :install }
|
||||||
|
|
@ -26,6 +27,9 @@ OptionParser.new do |opt|
|
||||||
opt.on('--cache', 'Use cache') do |o|
|
opt.on('--cache', 'Use cache') do |o|
|
||||||
options.use_cache = true
|
options.use_cache = true
|
||||||
end
|
end
|
||||||
|
opt.on('--forced', "if case of existing data, delete and recreate") do |o|
|
||||||
|
options.forced = true
|
||||||
|
end
|
||||||
|
|
||||||
opt.on('-t', '--target TARGET', ['user', 'usr', 'package', 'pkg', 'system', 'sys'], 'Target type (user, package, system)') do |target|
|
opt.on('-t', '--target TARGET', ['user', 'usr', 'package', 'pkg', 'system', 'sys'], 'Target type (user, package, system)') do |target|
|
||||||
|
|
||||||
|
|
@ -55,6 +59,19 @@ when :make
|
||||||
puts "making..."
|
puts "making..."
|
||||||
require 'make'
|
require 'make'
|
||||||
Make.command(options)
|
Make.command(options)
|
||||||
|
when :pkgmake
|
||||||
|
puts "Making package #{options.name}"
|
||||||
|
require 'make'
|
||||||
|
Make.create_package(options)
|
||||||
|
when :pkginstall
|
||||||
|
require 'make'
|
||||||
|
# TODO: wrong naming it is not name, but path
|
||||||
|
Make.install_package(options.name)
|
||||||
|
when :execute
|
||||||
|
puts "Ececuting: #{options.name}"
|
||||||
|
require 'execute'
|
||||||
|
puts "Arguments: #{options}"
|
||||||
|
Execute.file(options)
|
||||||
when :goto
|
when :goto
|
||||||
Dir.chdir(ENV["DAT_ROOT"])
|
Dir.chdir(ENV["DAT_ROOT"])
|
||||||
when :vm
|
when :vm
|
||||||
|
|
|
||||||
57
bin/get
Executable file
57
bin/get
Executable file
|
|
@ -0,0 +1,57 @@
|
||||||
|
ARCHIVE=false
|
||||||
|
DESTINATION_LOCAL_DIR="./"
|
||||||
|
|
||||||
|
if [[ "$1" == "--archive" ]]; then
|
||||||
|
ARCHIVE=true
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
echo "Usage: $0 [--archive] user@host remote_source_dir [local_destination_dir]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
USER_HOST="$1"
|
||||||
|
REMOTE_USER="${USER_HOST%@*}"
|
||||||
|
HOST="${USER_HOST#*@}"
|
||||||
|
|
||||||
|
REMOTE_SOURCE_DIR="$2"
|
||||||
|
if [[ -n "$3" ]]; then
|
||||||
|
DESTINATION_LOCAL_DIR="$3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$REMOTE_SOURCE_DIR" = /* ]]; then
|
||||||
|
IS_ABSOLUTE=true
|
||||||
|
else
|
||||||
|
IS_ABSOLUTE=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo "ARCHIVE=$ARCHIVE"
|
||||||
|
echo "REMOTE_USER=$REMOTE_USER"
|
||||||
|
echo "HOST=$HOST"
|
||||||
|
echo "REMOTE_SOURCE_DIR=$REMOTE_SOURCE_DIR"
|
||||||
|
echo "DESTINATION_LOCAL_DIR=$DESTINATION_LOCAL_DIR"
|
||||||
|
|
||||||
|
REMOTE_BASE_DIR=""
|
||||||
|
|
||||||
|
if $IS_ABSOLUTE; then
|
||||||
|
REMOTE_BASE_DIR="/"
|
||||||
|
else
|
||||||
|
REMOTE_BASE_DIR=/home/$REMOTE_USER
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Example that works
|
||||||
|
# ssh debian@gurgul.org "tar --zstd -cf - -C /home/debian .dat" | tar --zstd -xf - -C .
|
||||||
|
# get debian@gurgul.org .dat
|
||||||
|
|
||||||
|
# get --archive debian@gurgul.org /etc
|
||||||
|
|
||||||
|
TAR_COMMAND="tar --zstd -cf - -C $REMOTE_BASE_DIR $REMOTE_SOURCE_DIR"
|
||||||
|
|
||||||
|
if $ARCHIVE; then
|
||||||
|
ssh $REMOTE_USER@$HOST $TAR_COMMAND > "$DESTINATION_LOCAL_DIR/$(basename "$REMOTE_SOURCE_DIR")-$(date +"%d-%m-%Y").tar.zst"
|
||||||
|
else
|
||||||
|
ssh $REMOTE_USER@$HOST $TAR_COMMAND | tar --zstd -xf - -C $DESTINATION_LOCAL_DIR
|
||||||
|
fi
|
||||||
16
bin/index
Executable file
16
bin/index
Executable file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# find $NOTES_DIR/gpt -type d -path "$NOTES_DIR/gpt/[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*" | while read -r path; do
|
||||||
|
# echo $(basename "$path")
|
||||||
|
# done | sort -u | fzf
|
||||||
|
|
||||||
|
SEARCH_DIR="$NOTES_DIR/gpt"
|
||||||
|
DELIMITER="|"
|
||||||
|
|
||||||
|
selected=$(find "$SEARCH_DIR" -type d -path "$SEARCH_DIR/[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*" | while read -r path; do
|
||||||
|
topic=$(basename "$path")
|
||||||
|
echo -e "$topic\t$path"
|
||||||
|
done | fzf --delimiter='\t' --with-nth=1)
|
||||||
|
|
||||||
|
selected_path=$(echo "$selected" | cut -f2)
|
||||||
|
echo "Path: $selected_path"
|
||||||
152
bin/make-winux
Executable file
152
bin/make-winux
Executable file
|
|
@ -0,0 +1,152 @@
|
||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
#export LINUX_DISK_IMG=/home/artur/winux/VM/linux/linux.img
|
||||||
|
export LINUX_DISK_IMG=/home/artur/winux/VM/deb-orig/debian.img
|
||||||
|
|
||||||
|
export WINUX_DISK_IMG=./winux.img
|
||||||
|
|
||||||
|
# Mount the image of oryginal
|
||||||
|
#
|
||||||
|
|
||||||
|
# Mounting the image
|
||||||
|
function wxumount {
|
||||||
|
echo "unmounting :$1"
|
||||||
|
while lsof +D $1 >/dev/null 2>&1 || fuser $1 >/dev/null 2>&1
|
||||||
|
do
|
||||||
|
fuser -a $1
|
||||||
|
echo "Waiting for $1 to be free..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p $1
|
||||||
|
if mountpoint -q $1; then
|
||||||
|
echo "Unmounting $1..."
|
||||||
|
umount $1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Successfully unmounted $1."
|
||||||
|
else
|
||||||
|
echo "Failed to unmount $1."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$1 is not mounted."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
wxumount /mnt/winux
|
||||||
|
wxumount /mnt/linux
|
||||||
|
|
||||||
|
# (re)create an empty sparsed file
|
||||||
|
rm -rf $WINUX_DISK_IMG
|
||||||
|
dd if=/dev/zero of=$WINUX_DISK_IMG bs=1 count=0 seek=20G
|
||||||
|
|
||||||
|
# Check size
|
||||||
|
# real size: du -h winux.img
|
||||||
|
# appeared as: ls -lh winux.img
|
||||||
|
|
||||||
|
|
||||||
|
# Copy boot
|
||||||
|
|
||||||
|
IMG="/home/artur/winux/VM/linux/linux.img"
|
||||||
|
|
||||||
|
SECTOR_SIZE=$(LC_ALL=C sfdisk -d "$LINUX_DISK_IMG" | awk 'match($0,/sector-size:\s*([0-9]+)/,m){print m[1]; exit}')
|
||||||
|
START=$(LC_ALL=C sfdisk -d "$LINUX_DISK_IMG" | awk 'match($0,/start=\s*([0-9]+)/,m){print m[1]; exit}')
|
||||||
|
|
||||||
|
echo "Sector size: $SECTOR_SIZE"
|
||||||
|
echo "Start sector: $START"
|
||||||
|
|
||||||
|
|
||||||
|
dd if="$LINUX_DISK_IMG" of="$WINUX_DISK_IMG" bs="$SECTOR_SIZE" count="$START" conv=notrunc
|
||||||
|
|
||||||
|
# Formatting the disk
|
||||||
|
# No altering the first 1MB
|
||||||
|
echo '2048,,83,*' | sudo sfdisk --no-reread $WINUX_DISK_IMG
|
||||||
|
|
||||||
|
# List all loops: sudo losetup -a
|
||||||
|
WINUX_LOOP_DEV=$(sudo losetup --find --show $WINUX_DISK_IMG)
|
||||||
|
# Scan also for partitions: sudo losetup --find --show --partscan winux.img
|
||||||
|
|
||||||
|
echo "Loop device: $WINUX_LOOP_DEV"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export WINUX_LOOP_DEV="$(losetup --find --show -P $WINUX_LOOP_DEV)"
|
||||||
|
|
||||||
|
mkfs.ext2 ${WINUX_LOOP_DEV}p1
|
||||||
|
|
||||||
|
tune2fs ${WINUX_LOOP_DEV}p1 -U 1be261e2-a12d-4468-aa45-cbd7e68636eb
|
||||||
|
|
||||||
|
mount ${WINUX_LOOP_DEV}p1 /mnt/winux
|
||||||
|
|
||||||
|
## The image is formatted and ready to copy files over
|
||||||
|
|
||||||
|
export LINUX_LOOP_DEV="$(losetup --find --show --partscan $LINUX_DISK_IMG)"
|
||||||
|
mount ${LINUX_LOOP_DEV}p1 /mnt/linux
|
||||||
|
|
||||||
|
# copying files
|
||||||
|
SAVED_PWD=`pwd`
|
||||||
|
cd /mnt/linux
|
||||||
|
tar --numeric-owner --xattrs --acls -cpf - \
|
||||||
|
--exclude='lost+found' \
|
||||||
|
--exclude='var/log/*' \
|
||||||
|
--exclude='var/tmp/*' \
|
||||||
|
--exclude='tmp/*' \
|
||||||
|
--exclude='var/cache/*' \
|
||||||
|
--exclude='swapfile' \
|
||||||
|
--exclude='dev/*' \
|
||||||
|
--exclude='proc/*' \
|
||||||
|
--exclude='sys/*' \
|
||||||
|
--exclude='run/*' \
|
||||||
|
. | tar --numeric-owner --xattrs --acls -xpf - -C /mnt/winux
|
||||||
|
|
||||||
|
cd "$SAVED_PWD"
|
||||||
|
|
||||||
|
#### TESTTING CODE
|
||||||
|
# losetup -j $WINUX_DISK_IMG
|
||||||
|
|
||||||
|
# Clean up after building
|
||||||
|
|
||||||
|
sync
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
wxumount /mnt/winux
|
||||||
|
wxumount /mnt/linux
|
||||||
|
|
||||||
|
for dev in $(losetup -j $WINUX_DISK_IMG | cut -d: -f1); do
|
||||||
|
losetup -d "$dev"
|
||||||
|
done
|
||||||
|
|
||||||
|
for dev in $(losetup -j $LINUX_DISK_IMG | cut -d: -f1); do
|
||||||
|
losetup -d "$dev"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "making the archive"
|
||||||
|
|
||||||
|
# Best compressing rato, but slow and memory hungry (I LIKE IT)
|
||||||
|
#tar --sparse -I 'zstd -T0 --ultra -22 --long=31' \
|
||||||
|
# -cvf winux.img.tar.zst winux.img
|
||||||
|
## SO I PICKED NOW FOR SPEED
|
||||||
|
tar --sparse -I 'zstd -T0 -9' -cvf winux.img.tar.zst winux.img
|
||||||
|
|
||||||
|
|
||||||
|
# extract
|
||||||
|
# brew install gnu-tar
|
||||||
|
# tar -I zstd -xvf winux.img.tar.zst
|
||||||
|
# on macOS gtar or /opt/homebrew/opt/gnu-tar/libexec/gnubin/tar -I 'zstd --long=31' -xvf winux.img.tar.zst winux.img
|
||||||
|
|
||||||
|
|
||||||
|
# FINISHED
|
||||||
|
#=======================================================
|
||||||
|
|
||||||
|
# compressing with XZ. Supprisely it seems to have worst compresion rate than zstd
|
||||||
|
|
||||||
|
# tar --sparse -I 'xz -T0 -9e' -cvf winux.img.tar.xz winux.img
|
||||||
|
## Extracting
|
||||||
|
# tar -I xz -xvf winux.img.tar.xz
|
||||||
|
#
|
||||||
|
# zstd -T0 --ultra -22 winux.img -o winux.img.zst
|
||||||
|
|
||||||
|
# # decompression with
|
||||||
|
# # unzstd --sparse winux.img.zst
|
||||||
|
# # or
|
||||||
|
# # zstd -d --sparse winux.img.zst -o winux.img
|
||||||
20
bin/password
Executable file
20
bin/password
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# password for account, must be one or the default
|
||||||
|
# password amazon
|
||||||
|
# copy login
|
||||||
|
# password amazon -l
|
||||||
|
|
||||||
|
# search for password for given account
|
||||||
|
# password -l artur@gurgul.org
|
||||||
|
|
||||||
|
# http://example.com/login
|
||||||
|
# password example -l artur@gurgul.org
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# set -euo pipefail
|
||||||
|
# login="${DEFAULT_INTERNET_LOGIN:-${1-}}"
|
||||||
|
# file="$(find web -type f -path "web/*/$DEFAULT_INTERNET_LOGIN.gpg" -print | fzf --delimiter='/' --with-nth=2)"
|
||||||
|
# password_entry="${file%.gpg}"
|
||||||
|
# pass -c "$password_entry"
|
||||||
108
bin/recipes/edk2/make
Executable file
108
bin/recipes/edk2/make
Executable file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
rm -rf edk2
|
||||||
|
rm -rf output
|
||||||
|
|
||||||
|
git clone https://github.com/tianocore/edk2.git
|
||||||
|
cd edk2
|
||||||
|
git checkout fc0fffa7e9089e7b79b9ae7babb950f1f153e0ae
|
||||||
|
|
||||||
|
|
||||||
|
# 0) Make sure LLVM is installed
|
||||||
|
brew install llvm acpica nasm
|
||||||
|
brew install lld
|
||||||
|
|
||||||
|
# 1) Point PATH and tool vars to Homebrew’s LLVM (Apple Silicon path shown)
|
||||||
|
export LLVM_PREFIX="/opt/homebrew/opt/llvm" # Intel Macs: /usr/local/opt/llvm
|
||||||
|
export LLD_PREFIX="/opt/homebrew/opt/lld"
|
||||||
|
export PATH="$LLVM_PREFIX/bin:$LLD_PREFIX/bin:$PATH"
|
||||||
|
|
||||||
|
hash -r
|
||||||
|
|
||||||
|
# 2) Explicitly select LLVM tools so EDK2 doesn’t fall back to Apple’s
|
||||||
|
export CC="$LLVM_PREFIX/bin/clang"
|
||||||
|
export CXX="$LLVM_PREFIX/bin/clang++"
|
||||||
|
export LD="$LLD_PREFIX/bin/ld.lld"
|
||||||
|
export AR="$LLVM_PREFIX/bin/llvm-ar"
|
||||||
|
export RANLIB="$LLVM_PREFIX/bin/llvm-ranlib"
|
||||||
|
export NM="$LLVM_PREFIX/bin/llvm-nm"
|
||||||
|
export STRIP="$LLVM_PREFIX/bin/llvm-strip"
|
||||||
|
export OBJCOPY="$LLVM_PREFIX/bin/llvm-objcopy"
|
||||||
|
export OBJDUMP="$LLVM_PREFIX/bin/llvm-objdump"
|
||||||
|
|
||||||
|
# 3) Sanity check — these MUST point into .../opt/llvm/bin
|
||||||
|
which clang; clang --version
|
||||||
|
which ld.lld
|
||||||
|
which llvm-ar
|
||||||
|
|
||||||
|
# 4) Rebuild tools & firmware
|
||||||
|
make -C BaseTools -j
|
||||||
|
source ./edksetup.sh
|
||||||
|
|
||||||
|
build -a AARCH64 -t CLANGDWARF \
|
||||||
|
-p ShellPkg/ShellPkg.dsc \
|
||||||
|
-m ShellPkg/Application/KeyTools/KeyTool/KeyTool.inf \
|
||||||
|
-b RELEASE
|
||||||
|
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
mkdir -p output/keys/EFI/Boot
|
||||||
|
openssl x509 -in "microsoft corporation kek 2k ca 2023.crt" -outform DER -out output/keys/kek2023.cer
|
||||||
|
openssl x509 -in "windows uefi ca 2023.crt" -outform DER -out output/keys/db2023.cer
|
||||||
|
|
||||||
|
open /Users/artur/projs/edk2
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
|
# (Optional) clean the previous failed build to avoid stale flags/objects
|
||||||
|
rm -rf Build/ArmVirtQemu-AARCH64
|
||||||
|
|
||||||
|
build -a AARCH64 \
|
||||||
|
-t CLANGDWARF \
|
||||||
|
-p ArmVirtPkg/ArmVirtQemu.dsc \
|
||||||
|
-D SECURE_BOOT_ENABLE=TRUE \
|
||||||
|
-b DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# CODE="/Volumes/Cache/vms/image/win11-arm64/win11/QEMU_EFI.fd"
|
||||||
|
# VARS="/Volumes/Cache/vms/image/win11-arm64/win11/QEMU_VARS.fd"
|
||||||
|
|
||||||
|
|
||||||
|
# # Make blank 64 MiB raws
|
||||||
|
# qemu-img create -f raw QEMU_EFI-pflash.raw 64M
|
||||||
|
# qemu-img create -f raw QEMU_VARS-pflash.raw 64M
|
||||||
|
|
||||||
|
# # Copy firmware into the front of each file without truncating the 64 MiB size
|
||||||
|
# dd if="$CODE" of=QEMU_EFI-pflash.raw conv=notrunc
|
||||||
|
# dd if="$VARS" of=QEMU_VARS-pflash.raw conv=notrunc
|
||||||
|
|
||||||
|
# # Confirm size is exactly 67108864 bytes
|
||||||
|
# stat -f "%z %N" QEMU_EFI-pflash.raw QEMU_VARS-pflash.raw
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-secure-boot-key-creation-and-management-guidance?view=windows-11
|
||||||
|
# https://go.microsoft.com/fwlink/?linkid=2239775
|
||||||
|
# https://go.microsoft.com/fwlink/?linkid=2239776
|
||||||
|
|
||||||
|
|
||||||
|
# -drive if=none,id=mskeys,format=raw,file=fat:rw:keys
|
||||||
|
# -device usb-storage,drive=mskeys
|
||||||
|
|
||||||
|
|
||||||
|
# 5. Enroll the certs in firmware
|
||||||
|
# Boot into UEFI shell, run FS0:\EFI\Boot\KeyTool.efi.
|
||||||
|
|
||||||
|
# In KeyTool:
|
||||||
|
# Go to Edit Keys → KEK → Add New Key, pick kek2023.cer.
|
||||||
|
# Go to Edit Keys → db → Add New Key, pick db2023.cer.
|
||||||
|
# If no PK is present yet, you must enroll a Platform Key (PK) first (can be self-signed with OpenSSL; KeyTool can also generate). Without a PK, Secure Boot remains “greyed out.”
|
||||||
|
|
||||||
|
# ✅ After PK + KEK + DB are enrolled, reboot → go into firmware setup → Secure Boot option will be toggleable → set it to Enabled.
|
||||||
|
# Now Windows 11 installer/bootloader should run under Secure Boot.
|
||||||
|
# Ref: 68adf715-f29c-832e-89d7-a37025f63cf3
|
||||||
|
|
||||||
|
|
||||||
BIN
bin/recipes/edk2/microsoft corporation kek 2k ca 2023.crt
Normal file
BIN
bin/recipes/edk2/microsoft corporation kek 2k ca 2023.crt
Normal file
Binary file not shown.
61
bin/recipes/edk2/notes.md
Normal file
61
bin/recipes/edk2/notes.md
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
That error means your **WORKSPACE** points to a *different* edk2 tree:
|
||||||
|
|
||||||
|
```
|
||||||
|
/Users/artur/.dat/bin/recipes/edk2/edk2
|
||||||
|
```
|
||||||
|
|
||||||
|
so `build` is looking for `ShellPkg/.../KeyTool.inf` **there**, not in `~/projs/edk2`.
|
||||||
|
|
||||||
|
Fix by resetting your env and sourcing `edksetup.sh` from the repo you actually want to build.
|
||||||
|
|
||||||
|
## Do this exactly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 0) Go to the edk2 you want to use
|
||||||
|
cd ~/projs/edk2
|
||||||
|
git rev-parse --show-toplevel # should print /Users/artur/projs/edk2
|
||||||
|
|
||||||
|
# 1) Clear any stale EDK2 env from previous shells
|
||||||
|
unset WORKSPACE EDK_TOOLS_PATH PACKAGES_PATH
|
||||||
|
|
||||||
|
# 2) Rebuild BaseTools (with your LLVM/lld PATH still set like earlier)
|
||||||
|
make -C BaseTools -j
|
||||||
|
|
||||||
|
# 3) Reset Conf inside THIS tree and re-source
|
||||||
|
rm -f Conf/target.txt Conf/tools_def.txt
|
||||||
|
source ./edksetup.sh
|
||||||
|
|
||||||
|
# Sanity checks — these must point into ~/projs/edk2
|
||||||
|
echo "WORKSPACE=$WORKSPACE"
|
||||||
|
echo "EDK_TOOLS_PATH=$EDK_TOOLS_PATH"
|
||||||
|
test -f "$WORKSPACE/ShellPkg/Application/KeyTools/KeyTool/KeyTool.inf" && echo "KeyTool found"
|
||||||
|
|
||||||
|
# 4) Build KeyTool for AArch64 with clang/lld
|
||||||
|
build -a AARCH64 -t CLANGDWARF \
|
||||||
|
-p ShellPkg/ShellPkg.dsc \
|
||||||
|
-m ShellPkg/Application/KeyTools/KeyTool/KeyTool.inf \
|
||||||
|
-b RELEASE
|
||||||
|
```
|
||||||
|
|
||||||
|
### If you still see it picking the wrong path
|
||||||
|
|
||||||
|
You probably have these variables exported in your shell config. Force them for this shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export WORKSPACE="$PWD"
|
||||||
|
export EDK_TOOLS_PATH="$WORKSPACE/BaseTools"
|
||||||
|
export PACKAGES_PATH="$WORKSPACE"
|
||||||
|
source ./edksetup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Then re-run the `build` command above.
|
||||||
|
|
||||||
|
### Where the binary will land
|
||||||
|
|
||||||
|
Typical output path (adjust for your build target):
|
||||||
|
|
||||||
|
```
|
||||||
|
Build/Shell/RELEASE_CLANGDWARF/AARCH64/ShellPkg/Application/KeyTools/KeyTool/KeyTool/OUTPUT/KeyTool.efi
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you’ve got `KeyTool.efi`, mount it along with your `kek2023.cer` and `db2023.cer`, enroll **PK → KEK → db**, reboot into the firmware UI, and enable **Secure Boot**.
|
||||||
BIN
bin/recipes/edk2/windows uefi ca 2023.crt
Normal file
BIN
bin/recipes/edk2/windows uefi ca 2023.crt
Normal file
Binary file not shown.
1
bin/recipes/gnome/notes.md
Normal file
1
bin/recipes/gnome/notes.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
sudo apt-get install task-gnome-desktop
|
||||||
20
bin/recipes/net/net-up
Executable file
20
bin/recipes/net/net-up
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
sudo mkdir -p /etc/systemd/network
|
||||||
|
cat <<'EOF' | sudo tee /etc/systemd/network/20-enp0s1.network
|
||||||
|
[Match]
|
||||||
|
Name=enp0s1
|
||||||
|
|
||||||
|
[Network]
|
||||||
|
DHCP=yes
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl enable --now systemd-networkd
|
||||||
|
sudo systemctl enable --now systemd-resolved
|
||||||
|
|
||||||
|
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
|
||||||
|
|
||||||
|
sudo ip link set enp0s1 up
|
||||||
|
sudo networkctl reload
|
||||||
|
sudo networkctl reconfigure enp0s1
|
||||||
|
|
||||||
16
bin/recipes/net/notes.md
Normal file
16
bin/recipes/net/notes.md
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# bring the link up
|
||||||
|
sudo ip link set enp0s1 up
|
||||||
|
|
||||||
|
# give yourself an address in QEMU's usernet
|
||||||
|
sudo ip addr add 10.0.2.15/24 dev enp0s1
|
||||||
|
|
||||||
|
# default gateway for slirp
|
||||||
|
sudo ip route add default via 10.0.2.2
|
||||||
|
|
||||||
|
# DNS via slirp (or use 1.1.1.1 if you prefer)
|
||||||
|
echo "nameserver 10.0.2.3" | sudo tee /etc/resolv.conf > /dev/null
|
||||||
|
|
||||||
|
# sanity checks
|
||||||
|
ip -4 a show enp0s1
|
||||||
|
ping -c2 10.0.2.2
|
||||||
|
ping -c2 deb.debian.org
|
||||||
93
bin/recipes/vnc/notes.md
Normal file
93
bin/recipes/vnc/notes.md
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
Here’s what those two pieces typically look like in a QEMU VNC + TLS + SASL setup.
|
||||||
|
|
||||||
|
# `/etc/pki/qemu` (TLS x509 creds)
|
||||||
|
|
||||||
|
QEMU’s `-object tls-creds-x509,...,dir=/etc/pki/qemu,endpoint=server` expects this directory to hold the server’s cert/key and the CA it should trust for client certs.
|
||||||
|
|
||||||
|
Example layout:
|
||||||
|
|
||||||
|
```
|
||||||
|
/etc/pki/qemu/
|
||||||
|
├── ca-cert.pem # CA cert used to verify client certificates (if verify-peer=yes)
|
||||||
|
├── server-cert.pem # Server certificate (CN should match the host, or use subjectAltName)
|
||||||
|
├── server-key.pem # Private key for server-cert.pem (chmod 600, root-only)
|
||||||
|
└── crl.pem # (optional) Certificate Revocation List
|
||||||
|
```
|
||||||
|
|
||||||
|
Typical QEMU arg:
|
||||||
|
|
||||||
|
```
|
||||||
|
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=yes
|
||||||
|
-vnc :0,tls-creds=tls0,sasl
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
* `verify-peer=yes` means the VNC client must present a client certificate signed by `ca-cert.pem`. Omit or set `no` if you only want encryption without client certs (and rely on SASL for auth).
|
||||||
|
* File names above are the conventional ones QEMU looks for in that dir in server mode.
|
||||||
|
* Permissions matter: keep `server-key.pem` readable only by the QEMU user (e.g., `chmod 600`).
|
||||||
|
|
||||||
|
(If you wanted the client side for certificate auth, you’d create a *client* bundle with `client-cert.pem` / `client-key.pem` and give the server’s CA to the client.)
|
||||||
|
|
||||||
|
# `/etc/sasl2/qemu.conf` (SASL settings)
|
||||||
|
|
||||||
|
This file tells Cyrus SASL how to authenticate for the “qemu” service. A simple, local-password (sasldb) setup might be:
|
||||||
|
|
||||||
|
```
|
||||||
|
# /etc/sasl2/qemu.conf
|
||||||
|
mech_list: scram-sha-256 digest-md5
|
||||||
|
pwcheck_method: auxprop
|
||||||
|
auxprop_plugin: sasldb
|
||||||
|
sasldb_path: /etc/sasldb2
|
||||||
|
```
|
||||||
|
|
||||||
|
What each line does:
|
||||||
|
|
||||||
|
* `mech_list`: Which SASL mechanisms to allow. (If your build doesn’t have SCRAM, use `digest-md5` and/or `plain`/`login` — but prefer SCRAM or DIGEST over PLAIN.)
|
||||||
|
* `pwcheck_method: auxprop` + `auxprop_plugin: sasldb`: use the local SASL database.
|
||||||
|
* `sasldb_path`: where the password DB lives (default is `/etc/sasldb2` on many distros).
|
||||||
|
|
||||||
|
Create users in the sasldb:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo saslpasswd2 -a qemu -c alice
|
||||||
|
# (it will prompt for a password)
|
||||||
|
sudo sasldblistusers2 -f /etc/sasldb2 # verify entry exists
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run QEMU with both TLS and SASL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server,verify-peer=no \
|
||||||
|
-vnc :0,tls-creds=tls0,sasl
|
||||||
|
```
|
||||||
|
|
||||||
|
* Client connects over **TLS** (encrypted), then is prompted for **SASL username/password** (“alice” and the password you set).
|
||||||
|
* If you set `verify-peer=yes`, the client must also present a valid client cert signed by your CA.
|
||||||
|
|
||||||
|
## Quick OpenSSL one-liners (for testing)
|
||||||
|
|
||||||
|
> For production, use a proper CA workflow and strong key handling.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# CA
|
||||||
|
openssl genrsa -out ca.key 4096
|
||||||
|
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca-cert.pem -subj "/CN=QEMU Test CA"
|
||||||
|
|
||||||
|
# Server cert
|
||||||
|
openssl genrsa -out server-key.pem 2048
|
||||||
|
openssl req -new -key server-key.pem -out server.csr -subj "/CN=your.host.name"
|
||||||
|
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca.key -CAcreateserial -out server-cert.pem -days 825 -sha256
|
||||||
|
install -m 600 server-key.pem /etc/pki/qemu/
|
||||||
|
install -m 644 server-cert.pem ca-cert.pem /etc/pki/qemu/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common pitfalls
|
||||||
|
|
||||||
|
* **Wrong filenames/paths** in `/etc/pki/qemu` → QEMU won’t find the certs.
|
||||||
|
* **Permissions too open** on `server-key.pem` → QEMU may refuse or it’s a security risk.
|
||||||
|
* **SASL mechanism mismatch** → ensure your client supports one from `mech_list`.
|
||||||
|
* **No TLS but SASL with PLAIN/LOGIN** → credentials go over the wire unencrypted; always pair PLAIN/LOGIN with TLS.
|
||||||
|
|
||||||
|
If you tell me your distro, I can tailor the exact package names (Cyrus SASL modules) and service paths.
|
||||||
6
bin/services/ca/Gemfile
Normal file
6
bin/services/ca/Gemfile
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
ruby ">= 3.0"
|
||||||
|
gem "roda"
|
||||||
|
gem "puma"
|
||||||
|
gem "rackup"
|
||||||
26
bin/services/ca/Gemfile.lock
Normal file
26
bin/services/ca/Gemfile.lock
Normal 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
12
bin/services/ca/app.rb
Normal 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
|
||||||
2
bin/services/ca/config.ru
Normal file
2
bin/services/ca/config.ru
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
require_relative "app"
|
||||||
|
run App.freeze.app
|
||||||
0
bin/services/ca/make
Executable file
0
bin/services/ca/make
Executable file
9
bin/services/ca/readme.md
Normal file
9
bin/services/ca/readme.md
Normal 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
|
||||||
1
bin/set-zsh
Normal file
1
bin/set-zsh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
chsh -s $(which zsh)
|
||||||
100
bin/sq
Executable file
100
bin/sq
Executable file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
# Path to QEMU monitor socket
|
||||||
|
sock_path = "/tmp/qemu-monitor.sock"
|
||||||
|
|
||||||
|
# Connect to UNIX socket
|
||||||
|
sock = UNIXSocket.new(sock_path)
|
||||||
|
|
||||||
|
# Read greeting from QEMU (optional)
|
||||||
|
puts sock.readline rescue nil
|
||||||
|
|
||||||
|
# Function to send a single keystroke
|
||||||
|
def send_key(sock, key)
|
||||||
|
cmd = "sendkey #{key}\n"
|
||||||
|
puts ">>> #{cmd.strip}"
|
||||||
|
sock.write(cmd)
|
||||||
|
end
|
||||||
|
|
||||||
|
def char_to_key(ch)
|
||||||
|
case ch
|
||||||
|
# Control characters
|
||||||
|
when "\n" then "ret"
|
||||||
|
when "\t" then "tab"
|
||||||
|
when " " then "spc"
|
||||||
|
when "\e" then "esc"
|
||||||
|
when "\b" then "backspace"
|
||||||
|
|
||||||
|
# Lowercase letters
|
||||||
|
when "a".."z" then ch
|
||||||
|
|
||||||
|
# Uppercase letters (shift + letter)
|
||||||
|
when "A".."Z" then "shift-#{ch.downcase}"
|
||||||
|
|
||||||
|
# Digits
|
||||||
|
when "0".."9" then ch
|
||||||
|
|
||||||
|
# Shifted number row
|
||||||
|
when "!" then "shift-1"
|
||||||
|
when "@" then "shift-2"
|
||||||
|
when "#" then "shift-3"
|
||||||
|
when "$" then "shift-4"
|
||||||
|
when "%" then "shift-5"
|
||||||
|
when "^" then "shift-6"
|
||||||
|
when "&" then "shift-7"
|
||||||
|
when "*" then "shift-8"
|
||||||
|
when "(" then "shift-9"
|
||||||
|
when ")" then "shift-0"
|
||||||
|
|
||||||
|
when "-" then "minus"
|
||||||
|
when "_" then "shift-minus"
|
||||||
|
when "=" then "equal"
|
||||||
|
when "+" then "shift-equal"
|
||||||
|
when "[" then "bracket_left"
|
||||||
|
when "{" then "shift-bracket_left"
|
||||||
|
when "]" then "bracket_right"
|
||||||
|
when "}" then "shift-bracket_right"
|
||||||
|
when "\\" then "backslash"
|
||||||
|
when "|" then "shift-backslash"
|
||||||
|
when ";" then "semicolon"
|
||||||
|
when ":" then "shift-semicolon"
|
||||||
|
when "'" then "apostrophe"
|
||||||
|
when "\"" then "shift-apostrophe"
|
||||||
|
when "," then "comma"
|
||||||
|
when "<" then "shift-comma"
|
||||||
|
when "." then "dot"
|
||||||
|
when ">" then "shift-dot"
|
||||||
|
when "/" then "slash"
|
||||||
|
when "?" then "shift-slash"
|
||||||
|
when "`" then "grave_accent"
|
||||||
|
when "~" then "shift-grave_accent"
|
||||||
|
|
||||||
|
else
|
||||||
|
raise "Unsupported character: #{ch.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ARGV[0]
|
||||||
|
puts ARGV[0]
|
||||||
|
input = ARGV[0]
|
||||||
|
puts "Typing: #{input.inspect}"
|
||||||
|
|
||||||
|
input.chars.each do |ch|
|
||||||
|
send_key(sock, char_to_key(ch))
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
# Example: type "hello<Enter>"
|
||||||
|
%w[p a s s ret].each do |k|
|
||||||
|
send_key(sock, k)
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sock.close
|
||||||
|
|
||||||
|
|
||||||
|
# (qemu) screendump /Volumes/Cache/homes/debian/guaset.ppm
|
||||||
|
# ffmpeg -y -i guaset.ppm guest.png
|
||||||
95
bin/ssl
Executable file
95
bin/ssl
Executable file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require "fileutils"
|
||||||
|
require "open3"
|
||||||
|
|
||||||
|
def cmd(*cmd)
|
||||||
|
stdout, stderr, status = Open3.capture3(*cmd)
|
||||||
|
unless status.success?
|
||||||
|
warn "Command failed: #{cmd.join(' ')}"
|
||||||
|
warn stderr
|
||||||
|
exit status.exitstatus || 1
|
||||||
|
end
|
||||||
|
stdout
|
||||||
|
end
|
||||||
|
|
||||||
|
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 = ["testing.self"]
|
||||||
|
$ips = ["127.0.0.2"]
|
||||||
|
$ips = []
|
||||||
|
|
||||||
|
### Setting up for client
|
||||||
|
$cn = $domains.first
|
||||||
|
name = $cn.gsub("*", "wildcard")
|
||||||
|
|
||||||
|
dir = "certs"
|
||||||
|
FileUtils.mkdir_p(dir)
|
||||||
|
$key = File.join(dir, "#{name}.key.pem")
|
||||||
|
$csr = File.join(dir, "#{name}.csr.pem")
|
||||||
|
$crt = File.join(dir, "#{name}.crt.pem")
|
||||||
|
$ext = File.join(dir, "#{name}.ext")
|
||||||
|
############################
|
||||||
|
|
||||||
|
### Setting up for CA
|
||||||
|
|
||||||
|
$ca_name = "My Lab"
|
||||||
|
|
||||||
|
#############################
|
||||||
|
|
||||||
|
def create_CA
|
||||||
|
cmd "openssl", "genrsa", "-out", "rootCA.key.pem", "4096"
|
||||||
|
cmd "chmod", "600", "rootCA.key.pem"
|
||||||
|
cmd "openssl", "req", "-x509", "-new", "-nodes", "-key",
|
||||||
|
"rootCA.key.pem", "-sha256", "-days", "3650",
|
||||||
|
"-out", "rootCA.crt.pem",
|
||||||
|
"-subj", "/C=XX/ST=Lab/L=Local/O=#{$ca_name}/CN=#{$ca_name} Root CA"
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_CSR
|
||||||
|
cmd "openssl", "genrsa", "-out", $key, "2048"
|
||||||
|
cmd "openssl", "req", "-new", "-key", $key, "-out", $csr, "-subj", "/CN=#{$cn}/O=#{$ca_name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_extfile
|
||||||
|
ext_lines = []
|
||||||
|
ext_lines << "basicConstraints=CA:FALSE"
|
||||||
|
ext_lines << "keyUsage=digitalSignature,keyEncipherment"
|
||||||
|
ext_lines << "extendedKeyUsage=serverAuth"
|
||||||
|
ext_lines << "subjectAltName=@alt_names"
|
||||||
|
ext_lines << "[alt_names]"
|
||||||
|
|
||||||
|
$domains.each_with_index do |d, i|
|
||||||
|
ext_lines << "DNS.#{i + 1}=#{d}"
|
||||||
|
end
|
||||||
|
|
||||||
|
$ips.each_with_index do |ip, j|
|
||||||
|
ext_lines << "IP.#{j + 1}=#{ip}"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.write($ext, ext_lines.join("\n") + "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def sign_with_CA
|
||||||
|
cmd "openssl", "x509", "-req", "-in", $csr,
|
||||||
|
"-CA", "rootCA.crt.pem", "-CAkey", "rootCA.key.pem",
|
||||||
|
"-CAcreateserial", "-out", $crt, "-days", "397", "-sha256",
|
||||||
|
"-extfile", $ext
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
case subcommand
|
||||||
|
when :ca
|
||||||
|
create_CA
|
||||||
|
when :csr
|
||||||
|
create_CSR
|
||||||
|
when :casign
|
||||||
|
create_extfile
|
||||||
|
sign_with_CA
|
||||||
|
else
|
||||||
|
puts "no command handler"
|
||||||
|
end
|
||||||
4
bin/use
Normal file
4
bin/use
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
use python 3.11
|
||||||
|
|
||||||
|
|
||||||
|
.zshrc-using < setting the environment for the user/serice
|
||||||
107
bin/vm
107
bin/vm
|
|
@ -1,27 +1,90 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
# mount -t 9p -o trans=virtio,version=9p2000.L share /home/user
|
require 'optparse'
|
||||||
|
require 'ostruct'
|
||||||
|
require 'virtual-machine'
|
||||||
|
|
||||||
# this add to brake and inspect /dev if /dev/sda1 not found
|
# Paramteters
|
||||||
# -append "root=/dev/sda1 console=ttyS0 rd.break"
|
# -env: DAT_VM_DATA=~/.cache/vm
|
||||||
|
|
||||||
function run {
|
|
||||||
qemu-system-x86_64 -append "root=/dev/sda1 console=ttyS0 rd.break" \
|
|
||||||
-kernel "vmlinuz-linux" \
|
|
||||||
-initrd "initramfs-linux.img" \
|
|
||||||
-m 2048 \
|
|
||||||
-smp $(sysctl -n hw.logicalcpu) \
|
|
||||||
-cpu qemu64 \
|
|
||||||
-virtfs local,path=.,security_model=none,mount_tag=share \
|
|
||||||
-drive id=root-disk,if=none,format=raw,file=linux.img \
|
|
||||||
-device ide-hd,bus=ide.0,drive=root-disk \
|
|
||||||
-drive id=data-disk,if=none,format=qcow2,file=dat.qcow2 \
|
|
||||||
-device ide-hd,bus=ide.1,drive=data-disk \
|
|
||||||
-nographic
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function reset {
|
# vm setup debian --arch "<host:arch64>" --name "<image_name: debian>"
|
||||||
qemu-img create -f qcow2 dat.qcow2 32G
|
|
||||||
}
|
|
||||||
|
|
||||||
$1
|
options = OpenStruct.new
|
||||||
|
subcommand = ARGV.shift&.to_sym
|
||||||
|
parameter = ARGV[0] && ARGV[0] !~ /^-/ ? ARGV.shift : nil
|
||||||
|
|
||||||
|
OptionParser.new do |opt|
|
||||||
|
opt.on('--arch ARCH', 'Architecture arm64 or x86_64') do |arch|
|
||||||
|
options.arch = arch
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('--name NAME', 'Virtaul Machine name') do |name|
|
||||||
|
options.name = name
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('--cdrom CDROM', 'Use local cdrom image') do |cdrom|
|
||||||
|
options.cdrom = cdrom
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('--tpm', 'Use tpm') do
|
||||||
|
options.tpm = true
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('--shell', 'QEMU process must be detached to exec ssh') do
|
||||||
|
options.shell = true
|
||||||
|
options.detached = true
|
||||||
|
end
|
||||||
|
|
||||||
|
opt.on('--detached') do
|
||||||
|
options.detached = true
|
||||||
|
end
|
||||||
|
# --port (ssh port)
|
||||||
|
# --attached (do not leave the shell process)
|
||||||
|
# new from copy
|
||||||
|
# fetch from the server
|
||||||
|
end.parse!
|
||||||
|
|
||||||
|
|
||||||
|
case subcommand
|
||||||
|
when :create
|
||||||
|
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 :apply
|
||||||
|
puts "apply 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 :execute
|
||||||
|
puts "vm execute debian --file example.sh --attach (block terminal till done otherwiese notifi when done)"
|
||||||
|
puts "if name not provided then use the last accessed"
|
||||||
|
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
|
||||||
|
|
|
||||||
222
bin/vm-cmd
Executable file
222
bin/vm-cmd
Executable file
|
|
@ -0,0 +1,222 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
rm -rf /Volumes/Cache/vms/image/win11-arm64/win11/code.fd
|
||||||
|
rm -rf /Volumes/Cache/vms/image/win11-arm64/win11/vars.fd
|
||||||
|
cp /opt/homebrew/share/qemu/edk2-aarch64-code.fd /Volumes/Cache/vms/image/win11-arm64/win11/code.fd
|
||||||
|
cp /opt/homebrew/share/qemu/edk2-arm-vars.fd /Volumes/Cache/vms/image/win11-arm64/win11/vars.fd
|
||||||
|
|
||||||
|
|
||||||
|
# brew install qemu swtpm
|
||||||
|
|
||||||
|
# qemu-system-aarch64 -drive if=pflash,format=raw,unit=0,readonly=on,file=/Volumes/Cache/vms/image/win11-arm64/win11/code.fd -drive if=pflash,format=raw,unit=1,file=/Volumes/Cache/vms/image/win11-arm64/win11/vars.fd -display cocoa -device qemu-xhci,id=xhci -device usb-kbd -device usb-tablet -device virtio-keyboard-device -device virtio-mouse-device -device virtio-gpu -device virtio-net,netdev=n0 -netdev user,id=n0 -accel hvf -machine virt -cpu max -m 16384 -smp 6 -name FirstVM -boot order=d -drive file=/Volumes/Cache/vms/image/win11-arm64/win11/root.img,if=virtio,cache=writeback,format=raw,id=nvme0 -drive id=cd,format=raw,file=/Volumes/Cache/downloads/win11arm64.iso,media=cdrom -device usb-storage,drive=cd,bootindex=1 -device ramfb -chardev socket,id=chrtpm,path=/Users/agurgul/Downloads/tpm/tpm.sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis-device,tpmdev=tpm0
|
||||||
|
# vm setup win11 --tpm --cdrom /Volumes/Cache/downloads/win11arm64.iso
|
||||||
|
|
||||||
|
|
||||||
|
# qemu-system-aarch64 -drive if=pflash,format=raw,unit=0,readonly=on,file=/Volumes/Cache/vms/image/win11-arm64/win11/code.fd -drive if=pflash,format=raw,unit=1,file=/Volumes/Cache/vms/image/win11-arm64/win11/vars.fd -display cocoa -device qemu-xhci,id=xhci -device usb-kbd -device usb-tablet -device virtio-keyboard-device -device virtio-mouse-device -device virtio-gpu -device virtio-net,netdev=n0 -netdev user,id=n0 -accel hvf -machine virt -cpu max -m 16384 -smp 6 -name FirstVM -boot order=d -drive file=/Volumes/Cache/vms/image/win11-arm64/win11/root.img,if=virtio,cache=writeback,format=raw,id=nvme0 -drive id=cd,format=raw,file=/Volumes/Cache/downloads/win11arm64.iso,media=cdrom -device usb-storage,drive=cd,bootindex=1 -device ramfb -chardev socket,id=chrtpm,path=/Users/agurgul/Downloads/tpm/tpm.sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis-device,tpmdev=tpm0
|
||||||
|
|
||||||
|
# -netdev user,id=net0,hostfwd=tcp::33890-:3389,hostfwd=tcp::59850-:5985 \
|
||||||
|
# -machine virt,accel=hvf,highmem=off \
|
||||||
|
|
||||||
|
|
||||||
|
# -device virtio-keyboard-pci \
|
||||||
|
# -device virtio-tablet-pci \
|
||||||
|
|
||||||
|
# -device ich9-ahci,id=ahci0 \
|
||||||
|
# -device ide-hd,drive=drv0,bus=ahci0.0 \
|
||||||
|
|
||||||
|
# -device nvme,drive=drv0,serial=nvme0
|
||||||
|
|
||||||
|
# -boot order=d \
|
||||||
|
# -device usb-storage,drive=udisk,port=3\
|
||||||
|
|
||||||
|
# wget http://http.us.debian.org/debian/pool/main/e/edk2/qemu-efi-aarch64_2025.02-8_all.deb
|
||||||
|
# qemu-system-aarch64 \
|
||||||
|
# -machine virt,accel=hvf \
|
||||||
|
# -cpu host -smp 6 -m 8G \
|
||||||
|
# --boot order=d,menu=on \
|
||||||
|
# -bios /Users/artur/Downloads/tpm/QEMU_EFI.fd \
|
||||||
|
# -device qemu-xhci,id=xhci \
|
||||||
|
# \
|
||||||
|
# -drive file=/Volumes/Cache/vms/image/win11-arm64/win11/root.img,format=raw \
|
||||||
|
# \
|
||||||
|
# -device virtio-scsi-pci,id=scsi0 \
|
||||||
|
# -drive file=/Volumes/Cache/downloads/win11arm64.iso,if=none,media=cdrom,id=cd0 \
|
||||||
|
# -device scsi-cd,drive=cd0,bus=scsi0.0,bootindex=1 \
|
||||||
|
# -device ramfb \
|
||||||
|
# -device usb-kbd,bus=xhci.0,port=1 \
|
||||||
|
# -device usb-tablet,bus=xhci.0,port=2 \
|
||||||
|
# -netdev user,id=net0,hostfwd=tcp::35890-:3589 \
|
||||||
|
# -device virtio-net-pci,netdev=net0 \
|
||||||
|
# -chardev socket,id=chrtpm,path=/Users/artur/Downloads/tpm/tpm.sock \
|
||||||
|
# -tpmdev emulator,id=tpm0,chardev=chrtpm \
|
||||||
|
# -device tpm-tis-device,tpmdev=tpm0 \
|
||||||
|
# -monitor stdio
|
||||||
|
|
||||||
|
|
||||||
|
# in Shell
|
||||||
|
# FS0:
|
||||||
|
# cd EFI\BOOT
|
||||||
|
# BOOTAA64.EFI
|
||||||
|
|
||||||
|
|
||||||
|
# Disk driver: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/
|
||||||
|
# Used: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.271-1/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Attempt 1
|
||||||
|
# qemu-system-aarch64 \
|
||||||
|
# -machine virt,accel=hvf \
|
||||||
|
# -cpu host -smp 6 -m 8G \
|
||||||
|
# --boot order=d,menu=on \
|
||||||
|
# -drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/code.fd,readonly=on \
|
||||||
|
# -drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/vars.fd \
|
||||||
|
# -drive file=/Volumes/Cache/vms/image/win11-arm64/win11/root.img,if=none,format=raw,id=drv0 \
|
||||||
|
# -device nvme,drive=drv0,serial=nvme0 \
|
||||||
|
# -device virtio-scsi-pci,id=scsi0 \
|
||||||
|
# -drive file=/Volumes/Cache/downloads/win11arm64.iso,if=none,media=cdrom,id=cd0 \
|
||||||
|
# -device scsi-cd,drive=cd0,bus=scsi0.0,bootindex=1 \
|
||||||
|
# -device ramfb \
|
||||||
|
# -device qemu-xhci,id=xhci \
|
||||||
|
# -device usb-kbd,bus=xhci.0,port=1 \
|
||||||
|
# -device usb-tablet,bus=xhci.0,port=2 \
|
||||||
|
# -netdev user,id=net0,hostfwd=tcp::33890-:3389 \
|
||||||
|
# -device virtio-net-pci,netdev=net0 \
|
||||||
|
# -chardev socket,id=chrtpm,path=/Users/artur/Downloads/tpm/tpm.sock \
|
||||||
|
# -tpmdev emulator,id=tpm0,chardev=chrtpm \
|
||||||
|
# -device tpm-tis-device,tpmdev=tpm0 \
|
||||||
|
# -monitor stdio
|
||||||
|
|
||||||
|
|
||||||
|
# Attempt 2
|
||||||
|
# qemu-system-aarch64 \
|
||||||
|
# -machine virt,accel=hvf \
|
||||||
|
# -cpu host -smp 6 -m 8G \
|
||||||
|
# --boot order=d,menu=on \
|
||||||
|
# -drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/code.fd,readonly=on \
|
||||||
|
# -drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/vars.fd \
|
||||||
|
# -drive file=/Volumes/Cache/vms/image/win11-arm64/win11/root.img,if=none,format=raw,id=drv0 \
|
||||||
|
# -device ich9-ahci,id=ahci0 \
|
||||||
|
# -device ide-hd,drive=drv0,bus=ahci0.0 \
|
||||||
|
# -device virtio-scsi-pci,id=scsi0 \
|
||||||
|
# -drive file=/Volumes/Cache/downloads/win11arm64.iso,if=none,media=cdrom,id=cd0 \
|
||||||
|
# -device scsi-cd,drive=cd0,bus=scsi0.0,bootindex=1 \
|
||||||
|
# -device ramfb \
|
||||||
|
# -device qemu-xhci,id=xhci \
|
||||||
|
# -device usb-kbd,bus=xhci.0,port=1 \
|
||||||
|
# -device usb-tablet,bus=xhci.0,port=2 \
|
||||||
|
# -netdev user,id=net0,hostfwd=tcp::33890-:3389 \
|
||||||
|
# -device virtio-net-pci,netdev=net0 \
|
||||||
|
# -chardev socket,id=chrtpm,path=/Users/artur/Downloads/tpm/tpm.sock \
|
||||||
|
# -tpmdev emulator,id=tpm0,chardev=chrtpm \
|
||||||
|
# -device tpm-tis-device,tpmdev=tpm0 \
|
||||||
|
# -monitor stdio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Attempt 3
|
||||||
|
# qemu-system-aarch64 \
|
||||||
|
# -machine virt,accel=hvf \
|
||||||
|
# -cpu host -smp 6 -m 8G \
|
||||||
|
# --boot menu=on \
|
||||||
|
# \
|
||||||
|
# -drive if=pflash,format=raw,readonly=on,file=/Volumes/Cache/vms/image/win11-arm64/win11/code.fd \
|
||||||
|
# -drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/vars.fd \
|
||||||
|
# \
|
||||||
|
# -drive if=none,file=/Volumes/Cache/vms/image/win11-arm64/win11/root.qcow2,format=qcow2,id=drv0 \
|
||||||
|
# -device nvme,drive=drv0,serial=nvme-1 \
|
||||||
|
# \
|
||||||
|
# -device qemu-xhci,id=xhci \
|
||||||
|
# -drive if=none,id=winiso,media=cdrom,readonly=on,file=/Volumes/Cache/downloads/win11arm64.iso \
|
||||||
|
# -device usb-storage,drive=winiso,bootindex=1 \
|
||||||
|
# \
|
||||||
|
# -device ramfb \
|
||||||
|
# -device usb-kbd \
|
||||||
|
# -device usb-tablet \
|
||||||
|
# -netdev user,id=net0,hostfwd=tcp::33890-:3389 \
|
||||||
|
# -device virtio-net-pci,netdev=net0 \
|
||||||
|
# \
|
||||||
|
# -chardev socket,id=chrtpm,path=/Users/artur/Downloads/tpm/tpm.sock \
|
||||||
|
# -tpmdev emulator,id=tpm0,chardev=chrtpm \
|
||||||
|
# -device tpm-tis-device,tpmdev=tpm0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -serial mon:stdio
|
||||||
|
|
||||||
|
# File: bypass.reg
|
||||||
|
# Windows Registry Editor Version 5.00
|
||||||
|
|
||||||
|
# [HKEY_LOCAL_MACHINE\SYSTEM\Setup\LabConfig]
|
||||||
|
# "BypassTPMCheck"=dword:00000001
|
||||||
|
# "BypassSecureBootCheck"=dword:00000001
|
||||||
|
# "BypassCPUCheck"=dword:00000001
|
||||||
|
# "BypassRAMCheck"=dword:00000001
|
||||||
|
|
||||||
|
# hdiutil makehybrid -iso -joliet -o bypass.iso bypass.reg
|
||||||
|
|
||||||
|
# Shift+F10
|
||||||
|
# reg import D:\bypass.reg
|
||||||
|
|
||||||
|
|
||||||
|
## Build EDK2
|
||||||
|
# brew install nasm iasl python@3 openssl pkg-config
|
||||||
|
# brew install llvm acpica nasm
|
||||||
|
# git clone https://github.com/tianocore/edk2.git
|
||||||
|
# cd edk2
|
||||||
|
# git submodule update --init
|
||||||
|
# make -C BaseTools
|
||||||
|
# source ./edksetup.sh
|
||||||
|
# export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||||
|
# build -a X64 \
|
||||||
|
# -t XCODE5 \
|
||||||
|
# -p OvmfPkg/OvmfPkgX64.dsc \
|
||||||
|
# -D SECURE_BOOT_ENABLE=TRUE
|
||||||
|
# build -a AARCH64 \
|
||||||
|
# -t XCODE5 \
|
||||||
|
# -p ArmVirtPkg/ArmVirtQemu.dsc \
|
||||||
|
# -D SECURE_BOOT_ENABLE=TRUE
|
||||||
|
|
||||||
|
# build -a AARCH64 \
|
||||||
|
# -t CLANGDWARF \
|
||||||
|
# -p ArmVirtPkg/ArmVirtQemu.dsc \
|
||||||
|
# -D SECURE_BOOT_ENABLE=TRUE \
|
||||||
|
# -b DEBUG
|
||||||
|
# Steps moved to /bin/recipes/make-edk2
|
||||||
|
|
||||||
|
# Attempt 4
|
||||||
|
qemu-system-aarch64 \
|
||||||
|
-machine virt,accel=hvf \
|
||||||
|
-cpu host -smp 6 -m 8G \
|
||||||
|
--boot menu=on \
|
||||||
|
\
|
||||||
|
-drive if=pflash,format=raw,readonly=on,file=/Volumes/Cache/vms/image/win11-arm64/win11/QEMU_EFI-pflash.raw \
|
||||||
|
-drive if=pflash,format=raw,file=/Volumes/Cache/vms/image/win11-arm64/win11/QEMU_VARS-pflash.raw \
|
||||||
|
\
|
||||||
|
-drive if=none,file=/Volumes/Cache/vms/image/win11-arm64/win11/root.qcow2,format=qcow2,id=drv0 \
|
||||||
|
-device nvme,drive=drv0,serial=nvme-1 \
|
||||||
|
\
|
||||||
|
-device qemu-xhci,id=xhci \
|
||||||
|
-drive if=none,id=winiso,media=cdrom,readonly=on,file=/Volumes/Cache/downloads/win11arm64.iso \
|
||||||
|
-device usb-storage,drive=winiso,bootindex=1 \
|
||||||
|
\
|
||||||
|
-device ramfb \
|
||||||
|
-device usb-kbd \
|
||||||
|
-device usb-tablet \
|
||||||
|
-netdev user,id=net0,hostfwd=tcp::33890-:3389 \
|
||||||
|
-device virtio-net-pci,netdev=net0 \
|
||||||
|
\
|
||||||
|
-chardev socket,id=chrtpm,path=/Users/artur/Downloads/tpm/tpm.sock \
|
||||||
|
-tpmdev emulator,id=tpm0,chardev=chrtpm \
|
||||||
|
-device tpm-tis-device,tpmdev=tpm0
|
||||||
1
bin/vm-runner
Executable file
1
bin/vm-runner
Executable file
|
|
@ -0,0 +1 @@
|
||||||
|
[Install Zen on Linux | Flathub](https://flathub.org/apps/app.zen_browser.zen)
|
||||||
|
|
@ -6,4 +6,6 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
elif [[ "$ARCH" == "x86_64" ]]; then
|
elif [[ "$ARCH" == "x86_64" ]]; then
|
||||||
eval "$(/usr/local/bin/brew shellenv)"
|
eval "$(/usr/local/bin/brew shellenv)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export PATH="$(brew --prefix ruby)/bin:$PATH"
|
||||||
fi
|
fi
|
||||||
|
|
@ -3,12 +3,15 @@
|
||||||
|
|
||||||
export PATH="$DAT_ROOT/bin:$HOME/.local/bin:$PATH"
|
export PATH="$DAT_ROOT/bin:$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
export GEM_HOME="$HOME/.gems"
|
||||||
|
export GEM_PATH=$HOME/.gems
|
||||||
|
|
||||||
export RUBYLIB="$DAT_ROOT/lib"
|
export RUBYLIB="$DAT_ROOT/lib"
|
||||||
|
|
||||||
export PASSWORD_STORE_DIR=$HOME/.local/lib/secure-vault/passwords
|
export PASSWORD_STORE_DIR=$HOME/.local/lib/secure-vault/passwords
|
||||||
export NOTES_DIR=$HOME/.local/lib/notes
|
export NOTES_DIR=$HOME/.local/lib/notes
|
||||||
|
|
||||||
path=("$GEM_HOME/bin" $path)
|
path=("$GEM_HOME/bin" "$HOME/.cargo/bin" $path)
|
||||||
|
|
||||||
alias gf='git log --all --oneline | fzf'
|
alias gf='git log --all --oneline | fzf'
|
||||||
|
|
||||||
|
|
@ -16,6 +19,10 @@ function cdd {
|
||||||
cd $DAT_ROOT
|
cd $DAT_ROOT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cdp {
|
||||||
|
cd $PASSWORD_STORE_DIR
|
||||||
|
}
|
||||||
|
|
||||||
. $DAT_ROOT/bin/zshrc/prompt
|
. $DAT_ROOT/bin/zshrc/prompt
|
||||||
. $DAT_ROOT/bin/zshrc/utils
|
. $DAT_ROOT/bin/zshrc/utils
|
||||||
|
|
||||||
|
|
|
||||||
37
doc/execute.md
Normal file
37
doc/execute.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
|
||||||
|
It is how you can describe config of your server
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
user :artur
|
||||||
|
user :lucyna
|
||||||
|
|
||||||
|
service :forgejo do |context|
|
||||||
|
context.home_page = true
|
||||||
|
# per default all users are allowed
|
||||||
|
context.users = [:artur]
|
||||||
|
end
|
||||||
|
|
||||||
|
service :zulip
|
||||||
|
|
||||||
|
# this should be already installed, becouse it is required by others
|
||||||
|
service :postgresql
|
||||||
|
|
||||||
|
install :nvim, :python
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
And then save it as `Configfile` as default or with specyfic name
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# if default file name
|
||||||
|
dat execute
|
||||||
|
|
||||||
|
# if non standard file
|
||||||
|
dat execute file-name
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
require("command_runner")
|
||||||
require("plugins")
|
require("plugins")
|
||||||
require("options")
|
require("options")
|
||||||
require("keymaps")
|
require("keymaps")
|
||||||
|
|
|
||||||
36
home/.config/nvim/lua/command_runner.lua
Normal file
36
home/.config/nvim/lua/command_runner.lua
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
function M.run_shell_command_under_cursor()
|
||||||
|
local cmd = vim.api.nvim_get_current_line()
|
||||||
|
|
||||||
|
if cmd == "" then
|
||||||
|
print("No command on this line.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run command and capture output
|
||||||
|
local output = vim.fn.systemlist(cmd)
|
||||||
|
|
||||||
|
-- Save current window to return later
|
||||||
|
local current_win = vim.api.nvim_get_current_win()
|
||||||
|
|
||||||
|
-- Move to the right window (assumes it's already split)
|
||||||
|
vim.cmd("wincmd l")
|
||||||
|
|
||||||
|
-- Optional: clear buffer before writing
|
||||||
|
vim.api.nvim_buf_set_lines(0, 0, -1, false, {})
|
||||||
|
|
||||||
|
-- Set output in current buffer (right side)
|
||||||
|
vim.api.nvim_buf_set_lines(0, 0, -1, false, output)
|
||||||
|
|
||||||
|
-- Optional: make it editable plain text
|
||||||
|
vim.bo.filetype = "text"
|
||||||
|
vim.bo.modifiable = true
|
||||||
|
vim.bo.readonly = false
|
||||||
|
|
||||||
|
-- Return to the left window
|
||||||
|
vim.api.nvim_set_current_win(current_win)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
|
|
||||||
|
|
@ -5,6 +5,11 @@ map('n', '<leader>fg', require('telescope.builtin').live_grep, { desc = "Live gr
|
||||||
map('n', '<leader>fb', require('telescope.builtin').buffers, { desc = "Buffers" })
|
map('n', '<leader>fb', require('telescope.builtin').buffers, { desc = "Buffers" })
|
||||||
map('n', '<leader>fh', require('telescope.builtin').help_tags, { desc = "Help tags" })
|
map('n', '<leader>fh', require('telescope.builtin').help_tags, { desc = "Help tags" })
|
||||||
|
|
||||||
|
vim.keymap.set("n", "zr", function()
|
||||||
|
require("command_runner").run_shell_command_under_cursor()
|
||||||
|
end, { desc = "Run shell command under cursor and show output in right split" })
|
||||||
|
|
||||||
|
|
||||||
-- Project-specific ignored dirs for Telescope
|
-- Project-specific ignored dirs for Telescope
|
||||||
local function load_local_ignore()
|
local function load_local_ignore()
|
||||||
local cwd = vim.fn.getcwd()
|
local cwd = vim.fn.getcwd()
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@ lspconfig.gopls.setup {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- ruby LSP
|
||||||
|
lspconfig.ruby_lsp.setup({
|
||||||
|
cmd = { "ruby-lsp" }, -- or provide full path if needed
|
||||||
|
filetypes = { "ruby" },
|
||||||
|
root_dir = lspconfig.util.root_pattern("Gemfile", ".git"),
|
||||||
|
})
|
||||||
|
|
||||||
-- Completion
|
-- Completion
|
||||||
local cmp = require("cmp")
|
local cmp = require("cmp")
|
||||||
cmp.setup({
|
cmp.setup({
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,20 @@ require("lazy").setup({
|
||||||
{ "hrsh7th/vim-vsnip" },
|
{ "hrsh7th/vim-vsnip" },
|
||||||
|
|
||||||
-- Treesitter
|
-- Treesitter
|
||||||
{ "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" },
|
{
|
||||||
|
"nvim-treesitter/nvim-treesitter",
|
||||||
|
build = ":TSUpdate",
|
||||||
|
config = function()
|
||||||
|
require("nvim-treesitter.configs").setup({
|
||||||
|
ensure_installed = { "ruby", "lua", "vim", "bash", "json" }, -- include ruby
|
||||||
|
highlight = {
|
||||||
|
enable = true,
|
||||||
|
additional_vim_regex_highlighting = false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
-- Appearance
|
-- Appearance
|
||||||
{ "tomasiser/vim-code-dark" },
|
{ "tomasiser/vim-code-dark" },
|
||||||
|
|
|
||||||
15
install
15
install
|
|
@ -1,5 +1,12 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
## Software for bootstraping
|
||||||
|
# curl, gcc
|
||||||
|
|
||||||
|
# TODO: Packages that need to be added
|
||||||
|
# gem install ruby-lsp
|
||||||
|
|
||||||
|
#
|
||||||
# ./install --system --forced
|
# ./install --system --forced
|
||||||
# --forced (not forced, does not delete old version, just ends in failure)
|
# --forced (not forced, does not delete old version, just ends in failure)
|
||||||
# --system (refault user)
|
# --system (refault user)
|
||||||
|
|
@ -28,7 +35,7 @@ if [ "$system" = true ] && [ "$EUID" -ne 0 ]; then
|
||||||
exec sudo INSTALL_HOME="$INSTALL_HOME" "$0" "$@"
|
exec sudo INSTALL_HOME="$INSTALL_HOME" "$0" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
REPO_URL="https://gitlab.com/artur.gurgul/home.git"
|
REPO_URL="https://gurgul.pro/artur/environment.git"
|
||||||
|
|
||||||
is_debian_like() {
|
is_debian_like() {
|
||||||
if [ -r /etc/os-release ]; then
|
if [ -r /etc/os-release ]; then
|
||||||
|
|
@ -75,7 +82,7 @@ export DAT_ROOT=$(echo "$DAT_ROOT" | envsubst)
|
||||||
|
|
||||||
debian_install_packages() {
|
debian_install_packages() {
|
||||||
# List of required packages
|
# List of required packages
|
||||||
local packages=("git" "ruby")
|
local packages=("git" "ruby" "zsh")
|
||||||
local to_install=()
|
local to_install=()
|
||||||
|
|
||||||
# Determine if we need to use sudo
|
# Determine if we need to use sudo
|
||||||
|
|
@ -101,11 +108,13 @@ debian_install_packages() {
|
||||||
else
|
else
|
||||||
echo "All required packages are already installed."
|
echo "All required packages are already installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
chsh -s $(which zsh)
|
||||||
}
|
}
|
||||||
|
|
||||||
macos_install_packages() {
|
macos_install_packages() {
|
||||||
# List of required packages
|
# List of required packages
|
||||||
local packages=("git" "ruby")
|
local packages=("git" "ruby" "zsh")
|
||||||
local to_install=()
|
local to_install=()
|
||||||
|
|
||||||
# Check for Homebrew
|
# Check for Homebrew
|
||||||
|
|
|
||||||
155
lib/archive.rb
Normal file
155
lib/archive.rb
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
require 'net/http'
|
||||||
|
require 'uri'
|
||||||
|
require 'open3'
|
||||||
|
require 'fileutils'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'shellwords'
|
||||||
|
|
||||||
|
module Archive
|
||||||
|
MAGIC_NUMBERS = {
|
||||||
|
"\x1F\x8B" => 'gzip',
|
||||||
|
"\x50\x4B\x03\x04" => 'zip',
|
||||||
|
"\x28\xB5\x2F\xFD" => 'zstd',
|
||||||
|
"\xFD\x37\x7A\x58" => 'xz'
|
||||||
|
}
|
||||||
|
|
||||||
|
def self.extract(archive_path, destination_dir)
|
||||||
|
format = detect_format_from_url(archive_path)
|
||||||
|
|
||||||
|
unless format
|
||||||
|
format = detect_format_from_magic(archive_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
extract_archive(archive_path, destination_dir, format)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.fetch_and_extract(url, cache_path, destination_dir)
|
||||||
|
uri = URI.parse(url)
|
||||||
|
file_name = File.basename(uri.path)
|
||||||
|
archive_path = File.join(destination_dir, file_name)
|
||||||
|
|
||||||
|
format = detect_format_from_url(url)
|
||||||
|
puts "format #{format}"
|
||||||
|
download_file(uri, archive_path)
|
||||||
|
|
||||||
|
# Probably do not work
|
||||||
|
unless format
|
||||||
|
puts "case 1"
|
||||||
|
format = detect_format_from_headers(uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless format
|
||||||
|
puts "case 2"
|
||||||
|
format = detect_format_from_magic(archive_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
raise "Could not determine archive format" unless format
|
||||||
|
|
||||||
|
extract_archive(archive_path, format)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.download_file(uri, output_path, forced=false)
|
||||||
|
return if File.exist?(output_path) && !forced
|
||||||
|
|
||||||
|
# Ensure the directory exists
|
||||||
|
dir = File.dirname(output_path)
|
||||||
|
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
||||||
|
|
||||||
|
URI.open(uri) do |input|
|
||||||
|
File.open(output_path, 'wb') do |output|
|
||||||
|
IO.copy_stream(input, output)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def self.detect_format_from_url(url)
|
||||||
|
case File.extname(url)
|
||||||
|
when '.gz', '.tgz' then 'gzip'
|
||||||
|
when '.zip' then 'zip'
|
||||||
|
when '.zst' then 'zstd'
|
||||||
|
when '.xz' then 'xz'
|
||||||
|
else nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.detect_format_from_headers(uri)
|
||||||
|
response = Net::HTTP.get_response(uri)
|
||||||
|
content_type = response['content-type']
|
||||||
|
case content_type
|
||||||
|
when /gzip/ then 'gzip'
|
||||||
|
when /zip/ then 'zip'
|
||||||
|
when /zstd/ then 'zstd'
|
||||||
|
when /xz/ then 'xz'
|
||||||
|
else nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.detect_format_from_magic(file_path)
|
||||||
|
File.open(file_path, 'rb') do |f|
|
||||||
|
bytes = f.read(4)
|
||||||
|
MAGIC_NUMBERS.each do |magic, format|
|
||||||
|
return format if bytes.start_with?(magic)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
require 'shellwords'
|
||||||
|
|
||||||
|
def self.extract_archive(file_path, destination_dir, format)
|
||||||
|
# TODO: need to be checked
|
||||||
|
escaped_file = Shellwords.escape(file_path)
|
||||||
|
escaped_dir = Shellwords.escape(destination_dir)
|
||||||
|
|
||||||
|
system("mkdir -p #{escaped_dir}")
|
||||||
|
|
||||||
|
case format
|
||||||
|
when 'gzip'
|
||||||
|
system("tar -xzf #{escaped_file} -C #{escaped_dir}")
|
||||||
|
when 'zip'
|
||||||
|
system("unzip -d #{escaped_dir} #{escaped_file}")
|
||||||
|
when 'zstd'
|
||||||
|
if `file #{escaped_file}`.include?('tar archive')
|
||||||
|
system("unzstd -c #{escaped_file} | tar -xf - -C #{escaped_dir}")
|
||||||
|
else
|
||||||
|
system("unzstd -o \"#{escaped_dir}\" #{escaped_file}")
|
||||||
|
end
|
||||||
|
when 'xz'
|
||||||
|
if `file #{escaped_file}`.include?('tar archive')
|
||||||
|
system("tar -xJf #{escaped_file} -C #{escaped_dir}")
|
||||||
|
else
|
||||||
|
system("xz -dk #{escaped_file}")
|
||||||
|
decompressed = file_path.sub(/\.xz$/, '')
|
||||||
|
system("mv #{Shellwords.escape(decompressed)} #{escaped_dir}/")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise "Unsupported archive format: #{format}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# def self.extract_archive(file_path, destination_dir, format)
|
||||||
|
# case format
|
||||||
|
# when 'gzip'
|
||||||
|
# system("tar -xzf #{Shellwords.escape(file_path)}")
|
||||||
|
# when 'zip'
|
||||||
|
# system("unzip #{Shellwords.escape(file_path)}")
|
||||||
|
# when 'zstd'
|
||||||
|
# system("unzstd #{Shellwords.escape(file_path)}")
|
||||||
|
# when 'xz'
|
||||||
|
# # if file_path.end_with?('.tar.xz')
|
||||||
|
# if `file #{Shellwords.escape(file_path)}`.include?('tar archive')
|
||||||
|
# system("tar -xJf #{Shellwords.escape(file_path)}")
|
||||||
|
# else
|
||||||
|
# system("xz -dk #{Shellwords.escape(file_path)}")
|
||||||
|
# end
|
||||||
|
# else
|
||||||
|
# raise "Unsupported archive format: #{format}"
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
# Example usage:
|
||||||
|
# fetch_and_extract("https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz")
|
||||||
11
lib/certbot.rb
Normal file
11
lib/certbot.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
module Certbot
|
||||||
|
def self.create_certificate(domain, wildcard = false)
|
||||||
|
command = "/home/artur/.dat/bin/certbot"
|
||||||
|
if wildcard
|
||||||
|
system "sudo #{command} certonly --manual --preferred-challenges=dns -d \"*.#{domain}\" -d \"#{domain}\""
|
||||||
|
else
|
||||||
|
system "sudo #{command} --nginx -d #{domain}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
21
lib/data/resources/iso-images.rb
Normal file
21
lib/data/resources/iso-images.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
|
||||||
|
module VirtualMachine
|
||||||
|
ISO_URLS = {
|
||||||
|
debian: {
|
||||||
|
arm64: {
|
||||||
|
install: "https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso"
|
||||||
|
},
|
||||||
|
x86_64: {
|
||||||
|
install: "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.0.0-amd64-netinst.iso",
|
||||||
|
live: "https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-13.0.0-amd64-standard.iso"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
archlinux: {
|
||||||
|
x86_64: {
|
||||||
|
live: "https://geo.mirror.pkgbuild.com/iso/2025.08.01/archlinux-x86_64.iso"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
3
lib/data/templates/postgres/pg_hba.conf.erb
Normal file
3
lib/data/templates/postgres/pg_hba.conf.erb
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
local all all peer
|
||||||
|
#hostssl all all 0.0.0.0/0 scram-sha-256
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
36
lib/data/templates/postgres/postgres.service.erb
Normal file
36
lib/data/templates/postgres/postgres.service.erb
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
[Unit]
|
||||||
|
Description=PostgreSQL <%= version %>
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
#Type=simple
|
||||||
|
|
||||||
|
User=postgres
|
||||||
|
Group=services
|
||||||
|
|
||||||
|
ExecStart=<%= postgres_bin %> -D <%= database_dir %>
|
||||||
|
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
KillMode=mixed
|
||||||
|
TimeoutSec=300
|
||||||
|
Restart=on-failure
|
||||||
|
NotifyAccess=all
|
||||||
|
|
||||||
|
# Security
|
||||||
|
#ProtectSystem=full
|
||||||
|
#ProtectHome=true
|
||||||
|
ReadWritePaths=<%= database_dir %>
|
||||||
|
|
||||||
|
# PrivateTmp=true
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
# Resource Limits
|
||||||
|
LimitNOFILE=65536
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
57
lib/data/templates/postgres/postgresql.conf.erb
Normal file
57
lib/data/templates/postgres/postgresql.conf.erb
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
#data_directory = '/var/lib/postgresql/15/main'
|
||||||
|
#hba_file = '/etc/postgresql/15/main/pg_hba.conf'
|
||||||
|
#ident_file = '/etc/postgresql/15/main/pg_ident.conf'
|
||||||
|
|
||||||
|
|
||||||
|
#listen_addresses = 'localhost'
|
||||||
|
listen_addresses = '*'
|
||||||
|
port = 5432
|
||||||
|
max_connections = 100
|
||||||
|
unix_socket_directories = '/tmp, <%= unix_socket %>'
|
||||||
|
# unix_socket_directories = '/tmp'
|
||||||
|
password_encryption = scram-sha-256
|
||||||
|
|
||||||
|
### TODO Add support for ssl
|
||||||
|
#ssl = on
|
||||||
|
#
|
||||||
|
##ssl_ca_file = ''
|
||||||
|
#ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
|
||||||
|
##ssl_crl_file = ''
|
||||||
|
##ssl_crl_dir = ''
|
||||||
|
#ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
|
||||||
|
|
||||||
|
|
||||||
|
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers
|
||||||
|
#ssl_prefer_server_ciphers = on
|
||||||
|
#ssl_ecdh_curve = 'prime256v1'
|
||||||
|
#ssl_min_protocol_version = 'TLSv1.2'
|
||||||
|
#ssl_max_protocol_version = ''
|
||||||
|
#ssl_dh_params_file = ''
|
||||||
|
#ssl_passphrase_command = ''
|
||||||
|
#ssl_passphrase_command_supports_reload = off
|
||||||
|
|
||||||
|
shared_buffers = 128MB
|
||||||
|
dynamic_shared_memory_type = posix # the default is usually the first option
|
||||||
|
|
||||||
|
max_wal_size = 1GB
|
||||||
|
min_wal_size = 80MB
|
||||||
|
|
||||||
|
log_line_prefix = '%m [%p] %q%u@%d '
|
||||||
|
log_timezone = 'Etc/UTC'
|
||||||
|
|
||||||
|
|
||||||
|
#cluster_name = '15/main'
|
||||||
|
|
||||||
|
datestyle = 'iso, mdy'
|
||||||
|
timezone = 'Etc/UTC'
|
||||||
|
lc_messages = 'C.UTF-8'
|
||||||
|
lc_monetary = 'C.UTF-8'
|
||||||
|
lc_numeric = 'C.UTF-8'
|
||||||
|
lc_time = 'C.UTF-8'
|
||||||
|
|
||||||
|
default_text_search_config = 'pg_catalog.english'
|
||||||
|
|
||||||
|
# include files ending in '.conf' from
|
||||||
|
# include_dir = 'conf.d'
|
||||||
|
|
||||||
34
lib/downloader.rb
Normal file
34
lib/downloader.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
require 'uri'
|
||||||
|
require 'addressable/uri'
|
||||||
|
require 'user'
|
||||||
|
require 'fileutils'
|
||||||
|
require 'open-uri'
|
||||||
|
|
||||||
|
module Downloader
|
||||||
|
# brew install gnu-tar
|
||||||
|
# use_cache => save in the home and return path to it
|
||||||
|
# forced => download even if the file exists in the cache, saves to chace if use_cache == true
|
||||||
|
def self.get(url, use_cache = true, forced = false)
|
||||||
|
uri = Addressable::URI.parse(url)
|
||||||
|
path = File.join(User.cache_path, "downloads", uri.domain, uri.path)
|
||||||
|
|
||||||
|
#uri = URI.parse(url)
|
||||||
|
#file_name = File.basename(uri.path)
|
||||||
|
|
||||||
|
|
||||||
|
# Ensure the directory exists
|
||||||
|
dir = File.dirname(path)
|
||||||
|
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
||||||
|
|
||||||
|
unless File.exist?(path)
|
||||||
|
puts "File does not exist, downloading..."
|
||||||
|
URI.open(uri) do |input|
|
||||||
|
File.open(path, 'wb') do |output|
|
||||||
|
IO.copy_stream(input, output)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
yield path
|
||||||
|
end
|
||||||
|
end
|
||||||
153
lib/execute.rb
Normal file
153
lib/execute.rb
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
|
||||||
|
module Execute
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
require 'rubygems'
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
# dat execute progress
|
||||||
|
# dat execute < default Configfile
|
||||||
|
# dat execute --dry-run
|
||||||
|
# Execute single command
|
||||||
|
# dat command service zulip
|
||||||
|
|
||||||
|
module Execute
|
||||||
|
attr_accessor :options
|
||||||
|
|
||||||
|
def context(new_value = nil)
|
||||||
|
@options = new_value
|
||||||
|
end
|
||||||
|
|
||||||
|
class ServiceInstallContext
|
||||||
|
attr_accessor :bin_dir, :data_dir, :version, :user_name, :forced
|
||||||
|
|
||||||
|
def initialize(bin_dir, data_dir, user_name, version, forced = false)
|
||||||
|
@bin_dir = bin_dir
|
||||||
|
@data_dir = data_dir
|
||||||
|
@user_name = user_name
|
||||||
|
@version = version
|
||||||
|
@forced = forced
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class UserInstallContext
|
||||||
|
attr_accessor :user_name, :type, :can_login
|
||||||
|
|
||||||
|
def initialize(user_name, type = :user, can_login = nil)
|
||||||
|
@user_name = user_name
|
||||||
|
@type = type
|
||||||
|
|
||||||
|
if can_login == nil
|
||||||
|
case type
|
||||||
|
when :service
|
||||||
|
@can_login = false
|
||||||
|
when :user
|
||||||
|
@can_login = true
|
||||||
|
else
|
||||||
|
raise "Can not create user for type: #{type}"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@can_login = can_login
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def dependency(name)
|
||||||
|
puts "Checking for #{name}..."
|
||||||
|
|
||||||
|
unless gem_installed?(name)
|
||||||
|
puts "Installing #{name}..."
|
||||||
|
system("gem install #{name}")
|
||||||
|
else
|
||||||
|
puts "#{name} is already installed."
|
||||||
|
end
|
||||||
|
|
||||||
|
require name
|
||||||
|
rescue LoadError => e
|
||||||
|
puts "Failed to load #{name}: #{e.message}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def gem_installed?(name)
|
||||||
|
Gem::Specification::find_all_by_name(name).any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_install_executor(name)
|
||||||
|
require 'make'
|
||||||
|
pdata = Make.context(name)
|
||||||
|
bin_dir = pdata.get_prefix
|
||||||
|
data_dir = "/data/#{pdata.name}/#{pdata.version.split(".").first}"
|
||||||
|
service_install_context = ServiceInstallContext.new(
|
||||||
|
bin_dir, data_dir, name, pdata.version, @options.forced
|
||||||
|
)
|
||||||
|
|
||||||
|
case name
|
||||||
|
when :postgres
|
||||||
|
require 'setup/postgres'
|
||||||
|
-> { Setup::PostgreSQL.install(service_install_context) }
|
||||||
|
# ->(context) {
|
||||||
|
# Setup::PostgreSQL.install(context)
|
||||||
|
# }
|
||||||
|
else
|
||||||
|
raise "Can't find the executor"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_with_context(context)
|
||||||
|
|
||||||
|
end
|
||||||
|
# def postgres
|
||||||
|
# require 'setup/postgresql'
|
||||||
|
# Setup::PostgreSQL.install
|
||||||
|
# end
|
||||||
|
|
||||||
|
def service(name)
|
||||||
|
executor = get_install_executor(name)
|
||||||
|
#executor.call(service_install_context)
|
||||||
|
executor.call
|
||||||
|
|
||||||
|
if block_given?
|
||||||
|
context = OpenStruct.new
|
||||||
|
# service context
|
||||||
|
output = yield context
|
||||||
|
puts output
|
||||||
|
puts "context: #{context}"
|
||||||
|
else
|
||||||
|
puts "No block provided"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def domain(name)
|
||||||
|
require 'certbot'
|
||||||
|
wildcard = name.strip.start_with?("*.")
|
||||||
|
domain = name.strip.delete_prefix("*.")
|
||||||
|
Certbot.create_certificate(domain, wildcard)
|
||||||
|
end
|
||||||
|
|
||||||
|
def user(*users)
|
||||||
|
require 'user'
|
||||||
|
users.each do |name|
|
||||||
|
context = UserInstallContext.new(name, :user)
|
||||||
|
User.install(context)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def install(*packages)
|
||||||
|
packages.each do |pkg|
|
||||||
|
puts "Installing #{pkg}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.file(options)
|
||||||
|
dsl = Object.new
|
||||||
|
dsl.extend(Execute)
|
||||||
|
dsl.options = options
|
||||||
|
|
||||||
|
# Configfile
|
||||||
|
path = File.join(Dir.pwd, options.name || "./Configfile")
|
||||||
|
dsl.instance_eval(File.read(path), path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
10
lib/local-user/single-user.rb
Normal file
10
lib/local-user/single-user.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
module User
|
||||||
|
|
||||||
|
# Make user to be trusted when he use
|
||||||
|
# the computer locally
|
||||||
|
def make_local_trusted(user)
|
||||||
|
File.mkdir_p("/etc/systemd/system/getty@tty1.service.d")
|
||||||
|
end
|
||||||
|
end
|
||||||
70
lib/make.rb
70
lib/make.rb
|
|
@ -7,6 +7,7 @@ require 'fileutils'
|
||||||
require 'open3'
|
require 'open3'
|
||||||
|
|
||||||
# make for: the user, system, package
|
# make for: the user, system, package
|
||||||
|
# user/usr, system/sys, package/pkg
|
||||||
|
|
||||||
# as regular user, if dependencies provided
|
# as regular user, if dependencies provided
|
||||||
# user: $HOME/.local
|
# user: $HOME/.local
|
||||||
|
|
@ -28,13 +29,14 @@ module Make
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
attr_accessor :name, :use_cache, :environment, :steps, :packages, :repository
|
attr_accessor :name, :use_cache, :environment, :steps, :packages, :repository
|
||||||
attr_accessor :target, :archive, :source_type
|
attr_accessor :target, :archive, :source_type, :version, :forced
|
||||||
|
|
||||||
def initialize(options: OpenStruct.new)
|
def initialize(options: OpenStruct.new)
|
||||||
@target = options.target || :user
|
@target = options.target || :user
|
||||||
|
|
||||||
@name = options.name
|
@name = options.name
|
||||||
@use_cache = options.use_cache || false
|
@use_cache = options.use_cache || false
|
||||||
|
@forced = options.forced || false
|
||||||
|
|
||||||
#System.detect_os
|
#System.detect_os
|
||||||
# rbenv: brew install rbenv && rbenv install 3.0.0
|
# rbenv: brew install rbenv && rbenv install 3.0.0
|
||||||
|
|
@ -54,15 +56,21 @@ module Make
|
||||||
@packages = makefile["packages"] || []
|
@packages = makefile["packages"] || []
|
||||||
|
|
||||||
project_sources = {
|
project_sources = {
|
||||||
repository: makefile["repository"] != nil,
|
repository: makefile["repository"],
|
||||||
archive: makefile["archive"] != nil
|
archive: makefile["archive"]
|
||||||
}.select { |_, v| v }
|
}.select { |_, v| v }
|
||||||
|
|
||||||
if project_sources.size == 1
|
if project_sources.size == 1
|
||||||
|
source_data = project_sources.values.first
|
||||||
@source_type = project_sources.keys.first
|
@source_type = project_sources.keys.first
|
||||||
|
@version = source_data["version"] || source_data["branch"]
|
||||||
|
|
||||||
|
raise "No version provided" if @version == nil
|
||||||
|
@version = @version.to_s
|
||||||
else
|
else
|
||||||
raise "Exactly one type of source: 'repository' or 'archive'"
|
raise "Exactly one type of source: 'repository' or 'archive'"
|
||||||
end
|
end
|
||||||
|
|
||||||
puts @source_type
|
puts @source_type
|
||||||
|
|
||||||
@repository = Make.rostruct(makefile["repository"] || OpenStruct.new)
|
@repository = Make.rostruct(makefile["repository"] || OpenStruct.new)
|
||||||
|
|
@ -96,7 +104,7 @@ module Make
|
||||||
when :user
|
when :user
|
||||||
"#{ENV["HOME"]}/.local"
|
"#{ENV["HOME"]}/.local"
|
||||||
when :package
|
when :package
|
||||||
"#{sys_prefix}/pkg/#{@name}/#{@repository.branch}"
|
"#{sys_prefix}/pkg/#{@name}/#{@version}"
|
||||||
when :system
|
when :system
|
||||||
"#{sys_prefix}/"
|
"#{sys_prefix}/"
|
||||||
else
|
else
|
||||||
|
|
@ -122,6 +130,12 @@ module Make
|
||||||
"#{ENV["HOME"]}/.cache/dat/repo/#{@name}.git"
|
"#{ENV["HOME"]}/.cache/dat/repo/#{@name}.git"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def download_path
|
||||||
|
require 'addressable/uri'
|
||||||
|
uri = Addressable::URI.parse(archive.url)
|
||||||
|
File.join("#{ENV["HOME"]}/.cache/dat/downloads/", uri.domain, uri.path)
|
||||||
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
vars = instance_variables.map do |var|
|
vars = instance_variables.map do |var|
|
||||||
"#{var.to_s.delete('@')}: #{instance_variable_get(var).inspect}"
|
"#{var.to_s.delete('@')}: #{instance_variable_get(var).inspect}"
|
||||||
|
|
@ -183,10 +197,16 @@ module Make
|
||||||
end
|
end
|
||||||
|
|
||||||
def download_and_extract
|
def download_and_extract
|
||||||
archive = @context.archive
|
# gem install addressable
|
||||||
|
|
||||||
|
|
||||||
|
archive = @context.archive
|
||||||
|
puts @context.download_path
|
||||||
puts archive
|
puts archive
|
||||||
exit -1
|
|
||||||
|
require 'archive'
|
||||||
|
Archive.download_file(@context.archive.url, @context.download_path)
|
||||||
|
Archive.extract(@context.download_path, @cwd)
|
||||||
end
|
end
|
||||||
|
|
||||||
def checkout
|
def checkout
|
||||||
|
|
@ -214,13 +234,45 @@ module Make
|
||||||
def install
|
def install
|
||||||
System.install(context.packages)
|
System.install(context.packages)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_package(options)
|
||||||
|
puts "Creating packahge for options: #{options}"
|
||||||
|
puts @context
|
||||||
|
puts "Prefix #{@context.get_prefix}"
|
||||||
|
system("tar --zstd -Pcf #{@context.name}-#{@context.version}.pkg #{@context.get_prefix}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# dat make -t pkg --cache --name dry-run
|
# dat make -t pkg --cache --name dry-run
|
||||||
# dat make --name dry-run
|
# dat make --name dry-run
|
||||||
def self.command(options)
|
def self.command(options)
|
||||||
context = Context.new(options: options)
|
context = Context.new(options: options)
|
||||||
builder = Builder.new(context)
|
builder = Builder.new(context)
|
||||||
builder.build
|
builder.build
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# dat pkginstall {file-path}
|
||||||
|
# an example `dat pkginstall postgresql-17.5.pkg`
|
||||||
|
def self.install_package(path)
|
||||||
|
puts "Installing package: #{path}"
|
||||||
|
system("sudo tar --zstd -xf #{path} -C /")
|
||||||
|
end
|
||||||
|
|
||||||
|
# dat pkgmake {name}
|
||||||
|
def self.create_package(options)
|
||||||
|
options["target"] = :package if options["target"] == nil
|
||||||
|
context = Context.new(options: options)
|
||||||
|
builder = Builder.new(context)
|
||||||
|
builder.create_package(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: better name, it is just to obtain information
|
||||||
|
# about the package
|
||||||
|
def self.context(package_name, target = :package)
|
||||||
|
options = OpenStruct.new
|
||||||
|
options["target"] = target
|
||||||
|
options["name"] = package_name
|
||||||
|
Context.new(options: options)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,12 @@ require 'erb'
|
||||||
|
|
||||||
class NGINXProxy
|
class NGINXProxy
|
||||||
class << self
|
class << self
|
||||||
attr_accessor :domain, :port, :service, :user
|
attr_accessor :domain, :port, :service, :user, :willcard
|
||||||
|
|
||||||
|
def willcard(value = nil)
|
||||||
|
@willcard = value unless value.nil?
|
||||||
|
@willcard
|
||||||
|
end
|
||||||
|
|
||||||
def domain(value = nil)
|
def domain(value = nil)
|
||||||
@domain = value unless value.nil?
|
@domain = value unless value.nil?
|
||||||
|
|
@ -27,8 +32,11 @@ class NGINXProxy
|
||||||
@service
|
@service
|
||||||
end
|
end
|
||||||
|
|
||||||
|
## bundle exec rackup -s puma -b unix:///run/user/1000/http.sock
|
||||||
|
|
||||||
def generate
|
def generate
|
||||||
template = File.read("proxy.erb")
|
template_path = File.join(__dir__, 'data', 'templates', 'nginx', 'proxy.erb')
|
||||||
|
template = File.read(template_path)
|
||||||
template = ERB.new(template)
|
template = ERB.new(template)
|
||||||
template.result(binding)
|
template.result(binding)
|
||||||
end
|
end
|
||||||
|
|
@ -48,12 +56,3 @@ class NGINXProxy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ExampleProxy < NGINXProxy
|
|
||||||
domain "gurgul.org"
|
|
||||||
service "forgejo"
|
|
||||||
user "git"
|
|
||||||
port 3000
|
|
||||||
end
|
|
||||||
|
|
||||||
puts ExampleProxy.generate
|
|
||||||
puts ExampleProxy.path
|
|
||||||
83
lib/setup/postgres.rb
Normal file
83
lib/setup/postgres.rb
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
module Setup
|
||||||
|
require_relative '../templates'
|
||||||
|
require_relative "../user"
|
||||||
|
require_relative "../execute"
|
||||||
|
# dat execute postgres
|
||||||
|
# example.rcp
|
||||||
|
|
||||||
|
module PostgreSQL
|
||||||
|
extend Templates
|
||||||
|
|
||||||
|
def self.write_as(user, path, content)
|
||||||
|
puts "wriiting by #{user} to #{path}"
|
||||||
|
# If executed as root we can just use File.write
|
||||||
|
# File.write(postgresql_conf_path, postgresql_conf_content)
|
||||||
|
IO.popen(["sudo", "-u", user.to_s, "tee", path], "w") do |io|
|
||||||
|
io.write(content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# attr_accessor :te
|
||||||
|
|
||||||
|
def self.init_db(context)
|
||||||
|
puts "Mode, isForced #{context.forced}"
|
||||||
|
if Dir.exist?(context.data_dir)
|
||||||
|
if context.forced
|
||||||
|
puts("sudo rm -rf #{context.data_dir}")
|
||||||
|
else
|
||||||
|
raise "PostgreSQL data already exists"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
system("sudo mkdir -p #{context.data_dir}")
|
||||||
|
system("sudo chown #{context.user_name}:services #{context.data_dir}")
|
||||||
|
system("sudo -u postgres #{File.join(context.bin_dir, "/bin/initdb")} -D #{context.data_dir} --username=postgres")
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.setup_systemd(context)
|
||||||
|
puts "DataDir: #{context.data_dir}"
|
||||||
|
pg_hba = render("pg_hba.conf")
|
||||||
|
pg_hba_path = "#{File.join(context.data_dir, "pg_hba.conf")}"
|
||||||
|
write_as(context.user_name, pg_hba_path, pg_hba)
|
||||||
|
|
||||||
|
## TODO: move this to user module
|
||||||
|
#uid = Etc.getpwnam(context.user_name.to_s).uid
|
||||||
|
#socket_path = "/run/user/#{uid}"
|
||||||
|
socket_path = "/run/user/#{context.user_name}"
|
||||||
|
#socket_path = "/tmp"
|
||||||
|
|
||||||
|
system("sudo mkdir -p #{socket_path}")
|
||||||
|
system("sudo chown #{context.user_name}:services #{socket_path}")
|
||||||
|
system("sudo chmod 711 #{socket_path}")
|
||||||
|
|
||||||
|
postgresql_conf = render("postgresql.conf", unix_socket: socket_path)
|
||||||
|
|
||||||
|
postgresql_conf_path = "#{File.join(context.data_dir, "postgresql.conf")}"
|
||||||
|
write_as(context.user_name, postgresql_conf_path, postgresql_conf)
|
||||||
|
|
||||||
|
postgres_service = render(
|
||||||
|
"postgres.service",
|
||||||
|
postgres_bin: File.join(context.bin_dir, "/bin/postgres"),
|
||||||
|
version: context.version,
|
||||||
|
database_dir: context.data_dir
|
||||||
|
)
|
||||||
|
postgres_service_path = "/etc/systemd/system/postgres.service"
|
||||||
|
write_as("root", postgres_service_path, postgres_service)
|
||||||
|
system("sudo systemctl daemon-reexec")
|
||||||
|
system("sudo systemctl daemon-reload")
|
||||||
|
system("sudo systemctl enable postgres")
|
||||||
|
system("sudo systemctl start postgres")
|
||||||
|
|
||||||
|
# debug service
|
||||||
|
# sudo systemctl daemon-reexec && sudo systemctl daemon-reload && sudo systemctl restart postgresql.service
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.install(context)
|
||||||
|
user_context = Execute::UserInstallContext.new(context.user_name, :service)
|
||||||
|
User.install(user_context)
|
||||||
|
init_db(context)
|
||||||
|
setup_systemd(context)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
require_relative('system/architecture')
|
||||||
|
|
||||||
module System
|
module System
|
||||||
|
|
||||||
def self.detect_os
|
def self.detect_os
|
||||||
case RUBY_PLATFORM
|
case RUBY_PLATFORM
|
||||||
when /darwin/
|
when /darwin/
|
||||||
|
|
@ -29,7 +31,42 @@ module System
|
||||||
raise "Operating system not supported"
|
raise "Operating system not supported"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ARCH = normalize_architecture_string(arch)
|
||||||
|
|
||||||
def self.os_info
|
def self.os_info
|
||||||
puts os_name
|
puts os_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.qemu_paths
|
||||||
|
{
|
||||||
|
code_fd: qemu_code_fd_path,
|
||||||
|
vars_fd: qemu_vars_fd_path
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.arch_to_symbol(arch)
|
||||||
|
normalize_architecture_string(arch)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def self.exec_ssh(port)
|
||||||
|
require "socket"
|
||||||
|
|
||||||
|
host = "localhost"
|
||||||
|
cmd = "ssh -p #{port} user@#{host}"
|
||||||
|
|
||||||
|
# Wait until the port is open
|
||||||
|
puts "Waiting for #{host}:#{port}..."
|
||||||
|
until begin
|
||||||
|
TCPSocket.new(host, port).close
|
||||||
|
true
|
||||||
|
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
sleep 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Port open! Executing: #{cmd}"
|
||||||
|
exec cmd
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
55
lib/system/architecture.rb
Normal file
55
lib/system/architecture.rb
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
module System
|
||||||
|
def self.normalize_architecture_string(s)
|
||||||
|
str = s.to_s.strip.downcase
|
||||||
|
exact = {
|
||||||
|
"x86_64" => :x86_64, "amd64" => :x86_64,
|
||||||
|
"i386" => :x86_32, "i486" => :x86_32, "i586" => :x86_32, "i686" => :x86_32,
|
||||||
|
|
||||||
|
"arm64" => :arm64, "aarch64" => :arm64,
|
||||||
|
"armhf" => :armv7, "armel" => :armv5, "armv7l" => :armv7, "armv6l" => :armv6, "armv5tel" => :armv5,
|
||||||
|
|
||||||
|
"riscv64" => :riscv64,
|
||||||
|
|
||||||
|
"ppc64el" => :ppc64le, "ppc64le" => :ppc64le,
|
||||||
|
"ppc64" => :ppc64, "powerpc64" => :ppc64,
|
||||||
|
"ppc" => :ppc32, "powerpc" => :ppc32,
|
||||||
|
|
||||||
|
"s390x" => :s390x,
|
||||||
|
|
||||||
|
"mips64el" => :mips64el, "mips64" => :mips64,
|
||||||
|
"mipsel" => :mipsel, "mips" => :mips,
|
||||||
|
|
||||||
|
"loong64" => :loongarch64, "loongarch64" => :loongarch64,
|
||||||
|
|
||||||
|
"sparc64" => :sparc64,
|
||||||
|
|
||||||
|
"alpha" => :alpha,
|
||||||
|
"hppa" => :hppa,
|
||||||
|
"ia64" => :ia64,
|
||||||
|
}
|
||||||
|
return exact[str] if exact.key?(str)
|
||||||
|
|
||||||
|
return :x86_64 if str.include?("x64") || str.include?("amd64")
|
||||||
|
return :x86_32 if str =~ /\Ai[3-6]86\z/ || str.include?("x86")
|
||||||
|
return :arm64 if str.include?("aarch64") || str.include?("arm64")
|
||||||
|
return :armv7 if str.include?("armv7")
|
||||||
|
return :armv6 if str.include?("armv6")
|
||||||
|
return :armv5 if str.include?("armv5")
|
||||||
|
return :riscv64 if str.include?("riscv64")
|
||||||
|
return :ppc64le if str.include?("ppc64el") || str.include?("ppc64le")
|
||||||
|
return :ppc64 if str.include?("ppc64")
|
||||||
|
return :ppc32 if str.include?("ppc") || str.include?("powerpc")
|
||||||
|
return :s390x if str.include?("s390x")
|
||||||
|
return :mips64el if str.include?("mips64el")
|
||||||
|
return :mips64 if str.include?("mips64")
|
||||||
|
return :mipsel if str.include?("mipsel")
|
||||||
|
return :mips if str.start_with?("mips")
|
||||||
|
return :loongarch64 if str.include?("loong") || str.include?("loongarch")
|
||||||
|
return :sparc64 if str.include?("sparc64")
|
||||||
|
return :alpha if str.include?("alpha")
|
||||||
|
return :hppa if str.include?("hppa")
|
||||||
|
return :ia64 if str.include?("ia64")
|
||||||
|
|
||||||
|
:unknown
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
require 'open3'
|
require 'open3'
|
||||||
|
require_relative "utils"
|
||||||
|
|
||||||
module DebianSystem
|
module DebianSystem
|
||||||
def os_name
|
def os_name
|
||||||
|
|
@ -10,6 +11,10 @@ module DebianSystem
|
||||||
stdout.strip.to_i
|
stdout.strip.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def arch
|
||||||
|
sh("dpkg --print-architecture")
|
||||||
|
end
|
||||||
|
|
||||||
def install(packages)
|
def install(packages)
|
||||||
missing_packages = packages.reject { |pkg| package_installed?(pkg) }
|
missing_packages = packages.reject { |pkg| package_installed?(pkg) }
|
||||||
|
|
||||||
|
|
@ -49,4 +54,12 @@ module DebianSystem
|
||||||
puts "Failed to uninstall some packages."
|
puts "Failed to uninstall some packages."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def qemu_code_fd_path()
|
||||||
|
raise "not supported yet"
|
||||||
|
end
|
||||||
|
|
||||||
|
def qemu_vars_fd_path()
|
||||||
|
raise "not supported yet"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
require 'open3'
|
require 'open3'
|
||||||
|
require_relative "utils"
|
||||||
|
|
||||||
module MacOSSystem
|
module MacOSSystem
|
||||||
def os_name
|
def os_name
|
||||||
"macOS"
|
"macOS"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def arch
|
||||||
|
sh("sysctl -n hw.machine")
|
||||||
|
end
|
||||||
|
|
||||||
def cpus
|
def cpus
|
||||||
stdout, stderr, status = Open3.capture3("sysctl -n hw.ncpu")
|
stdout, stderr, status = Open3.capture3("sysctl -n hw.ncpu")
|
||||||
stdout.strip.to_i
|
stdout.strip.to_i
|
||||||
|
|
@ -49,4 +54,23 @@ module MacOSSystem
|
||||||
puts "Failed to uninstall some packages."
|
puts "Failed to uninstall some packages."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def qemu_code_fd_path()
|
||||||
|
case arch_to_symbol(arch)
|
||||||
|
when :arm64
|
||||||
|
"/opt/homebrew/share/qemu/edk2-aarch64-code.fd"
|
||||||
|
else
|
||||||
|
raise "not supported yet"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def qemu_vars_fd_path()
|
||||||
|
case arch_to_symbol(arch)
|
||||||
|
when :arm64
|
||||||
|
"/opt/homebrew/share/qemu/edk2-arm-vars.fd"
|
||||||
|
else
|
||||||
|
raise "not supported yet"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
6
lib/system/utils.rb
Normal file
6
lib/system/utils.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
def sh(cmd)
|
||||||
|
out = `#{cmd} 2>/dev/null`.to_s.strip
|
||||||
|
out.empty? ? "" : out
|
||||||
|
rescue
|
||||||
|
""
|
||||||
|
end
|
||||||
20
lib/templates.rb
Normal file
20
lib/templates.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
require 'erb'
|
||||||
|
|
||||||
|
module Templates
|
||||||
|
def render(name, locals = {})
|
||||||
|
# caller_module = Module.nesting.first.to_s.split('::').last&.downcase || 'common'
|
||||||
|
caller_file = caller_locations(1, 1)[0].absolute_path
|
||||||
|
inferred_dir = File.basename(caller_file).sub(/^install-/, '').sub(/\.rb$/, '')
|
||||||
|
puts "caller name: #{inferred_dir}"
|
||||||
|
|
||||||
|
template_path = File.join(__dir__, 'data', 'templates', inferred_dir, "#{name}.erb")
|
||||||
|
template = File.read(template_path)
|
||||||
|
erb = ERB.new(template)
|
||||||
|
|
||||||
|
# erb.result(binding)
|
||||||
|
|
||||||
|
context = Struct.new(*locals.keys).new(*locals.values)
|
||||||
|
erb.result(context.instance_eval { binding })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
41
lib/user.rb
Normal file
41
lib/user.rb
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
module User
|
||||||
|
require 'system'
|
||||||
|
|
||||||
|
def self.install(context)
|
||||||
|
puts "Creating #{context.type}: #{context.user_name}"
|
||||||
|
System.install(["zsh"])
|
||||||
|
|
||||||
|
user_exists = system("getent passwd #{context.user_name} > /dev/null")
|
||||||
|
|
||||||
|
group = case context.type
|
||||||
|
when :user
|
||||||
|
"users"
|
||||||
|
when :service
|
||||||
|
"services"
|
||||||
|
else
|
||||||
|
rise "Can not create user for unknow type: #{context.type}"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
group_exists = system("getent group #{group} > /dev/null")
|
||||||
|
unless group_exists
|
||||||
|
puts "Group '#{group}' does not exist. Creating it..."
|
||||||
|
system("sudo groupadd #{group}")
|
||||||
|
end
|
||||||
|
|
||||||
|
if user_exists
|
||||||
|
puts "User #{context.user_name} already exists. Updating shell and adding to group '#{group}'."
|
||||||
|
system("sudo usermod -s /usr/bin/zsh #{context.user_name}")
|
||||||
|
system("sudo usermod -g #{group} #{context.user_name}")
|
||||||
|
else
|
||||||
|
puts "User #{context.user_name} does not exist. Creating user..."
|
||||||
|
system("sudo adduser --disabled-login --gecos \"\" --ingroup #{group} --shell /usr/bin/zsh #{context.user_name}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def self.cache_path
|
||||||
|
ENV["DAT_CACHE_PATH"] || "#{ENV["HOME"]}/.cache/dat/"
|
||||||
|
end
|
||||||
|
end
|
||||||
169
lib/virtual-machine.rb
Normal file
169
lib/virtual-machine.rb
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
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[name][arch][type]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.image_id_dir(options)
|
||||||
|
File.join("#{options[:distro].to_s}-#{options[:arch].to_s}", options[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
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", image_id_dir(options))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.archive_dir(options)
|
||||||
|
File.join(vm_root_path, "archive", image_id_dir(options))
|
||||||
|
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"]
|
||||||
|
image_id = image_id_dir(options)
|
||||||
|
uri = Addressable::URI.parse(ENV["DAT_VM_REPO_URL"])
|
||||||
|
uri.path = File.join(uri.path, image_id, "archive.tar.zst")
|
||||||
|
return uri.to_s
|
||||||
|
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
|
||||||
|
|
||||||
|
if options[:arch] == nil
|
||||||
|
options[:arch] = System::ARCH
|
||||||
|
else
|
||||||
|
options[:arch] = System.arch_to_symbol(options[:arch])
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:detached] == nil
|
||||||
|
options[:detached] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:tpm] == nil
|
||||||
|
options[:tpm] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
unless options[:vars_fd]
|
||||||
|
options[:vars_fd] = File.join(vm_dir(options), "vars.fd")
|
||||||
|
end
|
||||||
|
|
||||||
|
unless options[:code_fd]
|
||||||
|
options[:code_fd] = File.join(vm_dir(options), "code.fd")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.archive(options)
|
||||||
|
fill_defaults(options)
|
||||||
|
Archive.create(vm_dir(options), out: create_archive_path(options))
|
||||||
|
end
|
||||||
|
|
||||||
|
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)
|
||||||
|
unless File.exist?(disk_img_path)
|
||||||
|
url = vm_archive_url(options)
|
||||||
|
Downloader.get(url, use_cache: false) do |path|
|
||||||
|
Archive.restore(path, vm_dir(options))
|
||||||
|
end
|
||||||
|
#raise "file do not exists"
|
||||||
|
end
|
||||||
|
# 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,
|
||||||
|
code_fd: options[:code_fd],
|
||||||
|
vars_fd: options[:vars_fd],
|
||||||
|
cpus: [1, System.cpus - 2].max,
|
||||||
|
detach: options[:detached],
|
||||||
|
tpm: options[:tpm],
|
||||||
|
shell: options[:shell]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# vm setup windows --arch arm64 --iso /Users/agurgul/Downloads/win.iso --tpm
|
||||||
|
# vm setup windows --tpm --cdrom /Users/agurgul/Downloads/win.iso
|
||||||
|
def self.setup(options)
|
||||||
|
fill_defaults(options)
|
||||||
|
|
||||||
|
# puts options
|
||||||
|
# exit -1
|
||||||
|
|
||||||
|
get_cdrom_image(options) do |path|
|
||||||
|
disk_img_path = root_img_path(options)
|
||||||
|
create_disk_image(disk_img_path, 64000 * 4)
|
||||||
|
|
||||||
|
Qemu.launch(
|
||||||
|
options[:arch],
|
||||||
|
disk_img_path,
|
||||||
|
code_fd: options[:code_fd],
|
||||||
|
vars_fd: options[:vars_fd],
|
||||||
|
cpus: [1, System.cpus - 2].max,
|
||||||
|
cdrom: path,
|
||||||
|
detach: options[:detached],
|
||||||
|
display: DisplayMode.window,
|
||||||
|
tpm: options[:tpm]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_cdrom_image(options)
|
||||||
|
if options[:cdrom] == nil
|
||||||
|
url = distro(options[:name], options[:arch], :install)
|
||||||
|
Downloader.get(url) do |path|
|
||||||
|
yield path
|
||||||
|
end
|
||||||
|
else
|
||||||
|
yield options[:cdrom]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# size in MB
|
||||||
|
# lsof /Users/artur/.cache/dat/vm/debian/arm64/debian/root.img
|
||||||
|
def self.create_disk_image(path, size)
|
||||||
|
size_in_bytes = 1024 * 1024 * size
|
||||||
|
|
||||||
|
# Ensure the directory exists
|
||||||
|
dir = File.dirname(path)
|
||||||
|
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
||||||
|
|
||||||
|
File.open(path, "wb") do |f|
|
||||||
|
f.truncate(size_in_bytes)
|
||||||
|
# f.seek(size_in_bytes - 1)
|
||||||
|
# f.write("\0")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
37
lib/vm/archive.rb
Normal file
37
lib/vm/archive.rb
Normal 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
|
||||||
344
lib/vm/qemu.rb
Normal file
344
lib/vm/qemu.rb
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
require "fileutils"
|
||||||
|
require "ostruct"
|
||||||
|
|
||||||
|
module DisplayMode
|
||||||
|
def self.none
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.fullscreen
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.window
|
||||||
|
2
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.vnc
|
||||||
|
3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Qemu
|
||||||
|
def self.qemu_bin_for(arch)
|
||||||
|
{
|
||||||
|
x86_64: "qemu-system-x86_64",
|
||||||
|
x86_32: "qemu-system-i386",
|
||||||
|
arm64: "qemu-system-aarch64",
|
||||||
|
armv7: "qemu-system-arm",
|
||||||
|
armv6: "qemu-system-arm",
|
||||||
|
armv5: "qemu-system-arm",
|
||||||
|
riscv64: "qemu-system-riscv64",
|
||||||
|
ppc64le: "qemu-system-ppc64",
|
||||||
|
ppc64: "qemu-system-ppc64",
|
||||||
|
ppc32: "qemu-system-ppc",
|
||||||
|
s390x: "qemu-system-s390x",
|
||||||
|
mips64el: "qemu-system-mips64el",
|
||||||
|
mips64: "qemu-system-mips64",
|
||||||
|
mipsel: "qemu-system-mipsel",
|
||||||
|
mips: "qemu-system-mips",
|
||||||
|
loongarch64: "qemu-system-loongarch64",
|
||||||
|
sparc64: "qemu-system-sparc64",
|
||||||
|
alpha: "qemu-system-alpha",
|
||||||
|
hppa: "qemu-system-hppa",
|
||||||
|
ia64: "qemu-system-ia64",
|
||||||
|
}.fetch(arch) { raise "Unsupported arch: #{arch.inspect}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.accel_args
|
||||||
|
host = RbConfig::CONFIG["host_os"]
|
||||||
|
if host =~ /linux/i && File.exist?("/dev/kvm")
|
||||||
|
["-accel", "kvm"]
|
||||||
|
elsif host =~ /darwin/i
|
||||||
|
# hvf exists on Apple Silicon + Intel macOS; QEMU falls back if not available
|
||||||
|
["-accel", "hvf"]
|
||||||
|
elsif host =~ /freebsd/i
|
||||||
|
# if QEMU was built with it; otherwise it will ignore
|
||||||
|
["-accel", "bhyve"]
|
||||||
|
else
|
||||||
|
["-accel", "tcg"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.machine_args_for(arch)
|
||||||
|
case arch
|
||||||
|
when :x86_64, :x86_32
|
||||||
|
[]
|
||||||
|
when :arm64
|
||||||
|
# -machine type=virt
|
||||||
|
# -cpu cortex-a72
|
||||||
|
["-machine", "virt", "-cpu", "max"]
|
||||||
|
when :armv7, :armv6, :armv5
|
||||||
|
["-machine", "virt", "-cpu", "cortex-a15"]
|
||||||
|
when :riscv64
|
||||||
|
["-machine", "virt"]
|
||||||
|
when :loongarch64
|
||||||
|
["-machine", "virt"]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#def self.launch(arch, disk_path, cdrom = nil, detach = true)
|
||||||
|
def self.launch(arch, disk_path, **options)
|
||||||
|
defaults = {
|
||||||
|
arch: System::ARCH,
|
||||||
|
cdrom: nil,
|
||||||
|
detach: true,
|
||||||
|
shell: false,
|
||||||
|
ram: 2048 * 8,
|
||||||
|
cpus: 1,
|
||||||
|
display: DisplayMode::none,
|
||||||
|
mount: {
|
||||||
|
wd: nil,
|
||||||
|
home: nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# for testing only
|
||||||
|
defaults[:detach] = false
|
||||||
|
|
||||||
|
defaults[:display] = DisplayMode.fullscreen
|
||||||
|
defaults[:display] = DisplayMode.window
|
||||||
|
# defaults[:display] = DisplayMode.none
|
||||||
|
#defaults[:display] = DisplayMode.vnc
|
||||||
|
|
||||||
|
opts = defaults.merge(options)
|
||||||
|
|
||||||
|
puts options
|
||||||
|
puts opts
|
||||||
|
|
||||||
|
qemu = qemu_bin_for(arch)
|
||||||
|
args = []
|
||||||
|
|
||||||
|
if System::OS == :macos && arch == :arm64
|
||||||
|
# args += ["-bios", "/opt/homebrew/share/qemu/edk2-aarch64-code.fd"]
|
||||||
|
# cp /opt/homebrew/share/qemu/edk2-arm-vars.fd ~/edk2-arm-vars.fd
|
||||||
|
|
||||||
|
|
||||||
|
unless File.exist?(opts[:vars_fd])
|
||||||
|
#System.qemu_paths
|
||||||
|
FileUtils.cp(System.qemu_vars_fd_path, opts[:vars_fd])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
unless File.exist?(opts[:code_fd])
|
||||||
|
FileUtils.cp(System.qemu_code_fd_path, opts[:code_fd])
|
||||||
|
end
|
||||||
|
|
||||||
|
args += ["-drive", "if=pflash,format=raw,unit=0,readonly=on,file=#{opts[:code_fd]}"]
|
||||||
|
args += ["-drive", "if=pflash,format=raw,unit=1,file=#{opts[:vars_fd]}"]
|
||||||
|
|
||||||
|
ssh_port = nil
|
||||||
|
|
||||||
|
if opts[:shell]
|
||||||
|
ssh_port = rand(4000..9999)
|
||||||
|
# args += ['-netdev', "user,id=net0,hostfwd=tcp:127.0.0.1:#{ssh_port}-:22"]
|
||||||
|
# args += ['-device', 'virtio-net-device,netdev=net0']
|
||||||
|
|
||||||
|
# args += ['-netdev', "user,id=n0,hostfwd=tcp:127.0.0.1:#{ssh_port}-10.0.2.15:22"]
|
||||||
|
# args += ['-device', 'virtio-net,netdev=n0']
|
||||||
|
|
||||||
|
# args += ['-netdev', "user,id=net0,hostfwd=tcp:127.0.0.1:#{ssh_port}-10.0.2.15:22"]
|
||||||
|
# args += ['-device', 'virtio-net-device,netdev=net0"']
|
||||||
|
|
||||||
|
args += ['-nic', "user,model=virtio-net-pci,hostfwd=tcp:127.0.0.1:#{ssh_port}-:22"]
|
||||||
|
|
||||||
|
puts "ssh -p #{ssh_port} user@localhost"
|
||||||
|
|
||||||
|
# conf that works
|
||||||
|
#args += ["-device", "virtio-net,netdev=n0", "-netdev", "user,id=n0"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# -virtfs local,path=.,mount_tag=hostfs,security_model=passthrough,id=hostfs
|
||||||
|
# mount -t 9p -o trans=virtio,version=9p2000.L hostfs /mnt
|
||||||
|
# sudo mount -t 9p hostfs /home/user/Share -o trans=virtio,version=9p2000.L,uid=1000,gid=1000,msize=262144,cache=mmap
|
||||||
|
|
||||||
|
# hostfs /home 9p trans=virtio,version=9p2000.L,uid=1000,gid=1000,msize=262144,cache=mmap,nofail 0 0
|
||||||
|
# hostfs /share 9p trans=virtio,version=9p2000.L,uid=1000,gid=1000,msize=262144,cache=mmap,nofail 0 0
|
||||||
|
|
||||||
|
if opts[:mount][:wd]
|
||||||
|
args += ['-virtfs', 'local,path=.,mount_tag=hostfs,security_model=passthrough,id=hostfs']
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts[:mount][:home]
|
||||||
|
#args += ['-homefs', "local,path=#{VMDATA},mount_tag=hostfs,security_model=passthrough,id=hostfs"]
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts[:display] == DisplayMode::none
|
||||||
|
port = 2222
|
||||||
|
args += ['-nographic']
|
||||||
|
args += ['-netdev', "user,id=net0,hostfwd=tcp:127.0.0.1:#{port}-:22,udp:127.0.0.1:6544-:6544=on"]
|
||||||
|
#args += ['-device', 'e1000,netdev=net0']
|
||||||
|
args += ['-device', 'virtio-net-pci,netdev=net0']
|
||||||
|
puts "ssh -p #{port} user@localhost"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
elsif opts[:display] == DisplayMode::vnc
|
||||||
|
# Note: this outputs serial on the console
|
||||||
|
#args += ['-nographic']
|
||||||
|
|
||||||
|
args += ["-display", "none"]
|
||||||
|
args += ["-device", "virtio-gpu-pci"]
|
||||||
|
args += ["-device", "virtio-keyboard-pci"]
|
||||||
|
args += ["-device", "virtio-mouse-pci"]
|
||||||
|
|
||||||
|
args += ['-vnc', '127.0.0.1:0,password=on']
|
||||||
|
|
||||||
|
# tunnel ssh -L 5900:127.0.0.1:5900 user@your-host
|
||||||
|
# -monitor unix:/tmp/qemu-mon,server,nowait
|
||||||
|
# -vnc 127.0.0.1:0,password=on
|
||||||
|
# printf 'change vnc password\nMySecret\n' | socat - UNIX-CONNECT:/tmp/qemu-mon
|
||||||
|
|
||||||
|
|
||||||
|
# SASL auth (username + password)
|
||||||
|
# -vnc :0,sasl
|
||||||
|
|
||||||
|
# TLS (certificates, optional password)
|
||||||
|
# -object tls-creds-x509,id=tls0,...
|
||||||
|
# -vnc :0,tls-creds=tls0
|
||||||
|
|
||||||
|
# qemu-system-x86_64 \
|
||||||
|
# -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server \
|
||||||
|
# -vnc :0,tls-creds=tls0,sasl
|
||||||
|
else
|
||||||
|
#args += ["-device", "virtio-gpu-device"]
|
||||||
|
if opts[:display] == DisplayMode::fullscreen
|
||||||
|
# #args += ["-display", "cocoa,full-screen=on"]
|
||||||
|
# # attempts:
|
||||||
|
# #args += ["-display", "cocoa,full-screen=on,retina=on"]
|
||||||
|
# # brew install gtk+3 sdl2
|
||||||
|
# # args += ["-display", "sdl,gl=on,full-screen=on"]
|
||||||
|
# #args += ["-display", "gtk,gl=on,full-screen=on"]
|
||||||
|
# #args += ["-display", "cocoa,full-screen=on"]
|
||||||
|
# #args += ["-display", "cocoa,gl=es,full-screen=on"]
|
||||||
|
|
||||||
|
#### TODO: try make it work with custom build
|
||||||
|
# args += ["-device", "virtio-gpu-gl-pci"]
|
||||||
|
# args += ["-display", "sdl,gl=on,full-screen=on"]
|
||||||
|
args += ["-display", "cocoa,full-screen=on"]
|
||||||
|
else
|
||||||
|
args += ["-display", "cocoa"]
|
||||||
|
end
|
||||||
|
|
||||||
|
args += ["-device", "qemu-xhci,id=xhci"]
|
||||||
|
args += ["-device", "usb-kbd"]
|
||||||
|
args += ["-device", "usb-tablet"]
|
||||||
|
|
||||||
|
args += ["-device", "virtio-keyboard-device"]
|
||||||
|
args += ["-device", "virtio-mouse-device"]
|
||||||
|
args += ["-device", "virtio-gpu"]
|
||||||
|
|
||||||
|
#args += ['-nic', 'user,model=virtio-net-pci']
|
||||||
|
unless opts[:shell]
|
||||||
|
args += ["-device", "virtio-net,netdev=n0", "-netdev", "user,id=n0"]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
### TODO: remove
|
||||||
|
port = 2222
|
||||||
|
args += ['-device', 'virtio-net-pci,netdev=net0']
|
||||||
|
args += ['-netdev', "user,id=net0,hostfwd=tcp:127.0.0.1:#{port}-:22,hostfwd=udp:127.0.0.1:6544-:6544"]
|
||||||
|
args += ['-virtfs', 'local,path=.,mount_tag=hostfs,security_model=passthrough,id=hostfs']
|
||||||
|
### TODO END
|
||||||
|
|
||||||
|
|
||||||
|
# macOS vmnet (shares Mac’s LAN)
|
||||||
|
# -netdev vmnet-shared,id=n1 \
|
||||||
|
# -device virtio-net-pci,netdev=n1
|
||||||
|
end
|
||||||
|
|
||||||
|
# copy to /Users/artur/.cache/dat/vm/debian/arm64/debian/vars.fd
|
||||||
|
# /opt/homebrew/share/qemu/edk2-aarch64-vars.fd
|
||||||
|
# args += ["-drive", "if=pflash,format=raw,unit=1,file=/Users/artur/.cache/dat/vm/debian/arm64/debian/vars.fd"]
|
||||||
|
end
|
||||||
|
|
||||||
|
args += accel_args
|
||||||
|
args += machine_args_for(arch)
|
||||||
|
args += ["-m", opts[:ram].to_s, "-smp", opts[:cpus].to_s]
|
||||||
|
args += ["-name", "FirstVM", "-boot", "order=d"] # boot from CD first
|
||||||
|
args += ["-drive", "file=#{disk_path},if=virtio,cache=writeback,format=raw,id=nvme0"]
|
||||||
|
#args += ["-device", "nvme,serial=nvme0,drive=nvme0,bootindex=2"]
|
||||||
|
|
||||||
|
if opts[:cdrom] != nil
|
||||||
|
#args += ["-cdrom", opts[:cdrom]]
|
||||||
|
|
||||||
|
# args += ["-device", "virtio-scsi-pci,id=scsi"]
|
||||||
|
# args += ["-drive", "if=none,id=cd,format=raw,file=#{opts[:cdrom]},media=cdrom"]
|
||||||
|
# args += ["-device", "scsi-cd,drive=cd,bootindex=1"]
|
||||||
|
|
||||||
|
|
||||||
|
args += ["-drive", "id=cd,format=raw,file=#{opts[:cdrom]},media=cdrom"]
|
||||||
|
args += ["-device", "usb-storage,drive=cd,bootindex=1"]
|
||||||
|
|
||||||
|
args += ["-device", "ramfb"]
|
||||||
|
# args += ["-device", "virtio-gpu-pci"]
|
||||||
|
# args += ["-display", "default,show-cursor=on"]
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts[:tpm]
|
||||||
|
# brew install swtpm
|
||||||
|
# swtpm socket --tpm2 --ctrl type=unixio,path=./tpm/tpm.sock --tpmstate dir=./tpm --daemon
|
||||||
|
|
||||||
|
|
||||||
|
["swtpm", "socket", "--tpm2", "--ctrl", "type=unixio,path=./tpm/tpm.sock", "--tpmstate", "dir=./tpm"]
|
||||||
|
|
||||||
|
# args += ["-chardev", "socket,id=chrtpm,path=/Users/agurgul/Downloads/tpm/tpm.sock"]
|
||||||
|
# args += ["-tpmdev", "emulator,id=tpm0,chardev=chrtpm"]
|
||||||
|
# args += ["-device", "tpm-crb-device,tpmdev=tpm0"]
|
||||||
|
|
||||||
|
args += ["-chardev", "socket,id=chrtpm,path=/Users/agurgul/Downloads/tpm/tpm.sock"]
|
||||||
|
args += ["-tpmdev", "emulator,id=tpm0,chardev=chrtpm"]
|
||||||
|
#args += ["-device", "tpm-tis,tpmdev=tpm0"]
|
||||||
|
args += ["-device", "tpm-tis-device,tpmdev=tpm0"]
|
||||||
|
# nic user,ipv6=off,model=rtl8139,mac=84:1b:77:c9:03:a6
|
||||||
|
|
||||||
|
# TODO: Shared network on macOS
|
||||||
|
# -netdev vmnet-shared,id=net0
|
||||||
|
end
|
||||||
|
|
||||||
|
args += ['-monitor', 'stdio']
|
||||||
|
|
||||||
|
# args += ["-device", "virtio-net,netdev=n0", "-netdev", "user,id=n0"] # user-mode NAT
|
||||||
|
# optional: uncomment to run headless with VNC on :5901
|
||||||
|
# args += ["-display", "none", "-vnc", "127.0.0.1:1"]
|
||||||
|
|
||||||
|
cmd = [qemu, *args]
|
||||||
|
|
||||||
|
puts "Launching: #{cmd.join(' ')}"
|
||||||
|
|
||||||
|
if opts[:detach]
|
||||||
|
log = File.open("log.txt", "w")
|
||||||
|
pid = Process.spawn(*cmd, pgroup: false, out: log, err: log)
|
||||||
|
Process.detach(pid)
|
||||||
|
puts "QEMU pid=#{pid}"
|
||||||
|
|
||||||
|
if opts[:shell]
|
||||||
|
System.exec_ssh(ssh_port)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
pid = Process.spawn(*cmd, pgroup: true, out: $stdout, err: $stderr)
|
||||||
|
Process.wait(pid)
|
||||||
|
status = $?
|
||||||
|
puts "Exit status: #{status.exitstatus}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Works on MacOS=
|
||||||
|
# -monitor unix:/tmp/qemu-monitor.sock,server,nowait
|
||||||
|
# nc -U /tmp/qemu-monitor.sock
|
||||||
|
# instead of args += ['-monitor', 'stdio']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 9P
|
||||||
|
# sudo mount -t 9p hostfs /home/user/Share \
|
||||||
|
# -o trans=virtio,version=9p2000.L,msize=262144,cache=mmap,access=any,dfltuid=1000,dfltgid=1000
|
||||||
|
# sudo chown -hR 1000:1000 /home/user/Share
|
||||||
|
|
@ -4,3 +4,12 @@
|
||||||
```bash
|
```bash
|
||||||
curl -sSL https://gurgul.pro/artur/environment/raw/branch/main/install | bash
|
curl -sSL https://gurgul.pro/artur/environment/raw/branch/main/install | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Config:
|
||||||
|
|
||||||
|
| Variable Name | Default Value | Description |
|
||||||
|
|---------------------------|--------------------------------|-------------|
|
||||||
|
| `DAT_CACHE_PATH` | `${HOME}/.cache/dat/` | Path where cached data is stored. |
|
||||||
|
| `DEFAULT_INTERNET_LOGIN` | not set | |
|
||||||
|
| `DAT_VM_DATA` | `${DAT_CACHE_PATH}/vm` | Directory for storing VM-related data. |
|
||||||
21
recipes/certbot/debian.yml
Normal file
21
recipes/certbot/debian.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
environment:
|
||||||
|
PYTHONPATH: /home/artur/test
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- python
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- libffi-dev
|
||||||
|
- libssl-dev
|
||||||
|
|
||||||
|
repository:
|
||||||
|
url: https://github.com/certbot/certbot
|
||||||
|
branch: v4.2.0
|
||||||
|
version: 4.2.0
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- $SUDO pip3 install --prefix=$PREFIX certbot
|
||||||
|
- $SUDO pip3 install --prefix=$PREFIX certbot-nginx
|
||||||
|
|
||||||
|
# can be executed like: pip install --prefix=$PREFIX certbot certbot-nginx
|
||||||
|
# to see installed plugins: `certbot plugins`
|
||||||
11
recipes/example-roda.rb
Normal file
11
recipes/example-roda.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
require 'nginx'
|
||||||
|
|
||||||
|
class ExampleProxy < NGINXProxy
|
||||||
|
domain "gurgul.org"
|
||||||
|
service "forgejo"
|
||||||
|
user "git"
|
||||||
|
port 3000
|
||||||
|
end
|
||||||
|
|
||||||
|
puts ExampleProxy.generate
|
||||||
|
puts ExampleProxy.available_path
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
service:
|
||||||
|
name: forgejo
|
||||||
|
|
||||||
archive:
|
archive:
|
||||||
url: https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz
|
url: https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- echo "ls"
|
- mv forgejo-12.0.1-linux-amd64 ~/.local/bin/forgejo
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,6 @@ repository:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- ./contrib/download_prerequisites
|
- ./contrib/download_prerequisites
|
||||||
- ./configure --prefix=$HOME/.local --enable-languages=c,c++ --disable-multilib
|
- ./configure --prefix=$PREFIX --enable-languages=c,c++ --disable-multilib
|
||||||
- make -j$(nproc)
|
- make -j$(nproc)
|
||||||
- make install
|
- $SUDO make install
|
||||||
|
|
|
||||||
40
recipes/nginx/debian.yml
Normal file
40
recipes/nginx/debian.yml
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- build-essential
|
||||||
|
- libpcre2-dev
|
||||||
|
- zlib1g
|
||||||
|
- zlib1g-dev
|
||||||
|
- libssl-dev
|
||||||
|
|
||||||
|
repository:
|
||||||
|
url: https://github.com/nginx/nginx.git
|
||||||
|
branch: release-1.29.0
|
||||||
|
version: 1.29.0
|
||||||
|
|
||||||
|
# TODO: finish the configuration: last message of 6898551e-70a0-8331-8617-bcfc9bcf6af8
|
||||||
|
steps:
|
||||||
|
- echo "starting"
|
||||||
|
- |
|
||||||
|
./auto/configure \
|
||||||
|
--prefix=$PREFIX \
|
||||||
|
--with-http_ssl_module \
|
||||||
|
--with-http_gzip_static_module \
|
||||||
|
--with-stream \
|
||||||
|
--with-http_v2_module \
|
||||||
|
--with-pcre-jit \
|
||||||
|
--with-threads \
|
||||||
|
--with-file-aio \
|
||||||
|
--with-http_ssl_module \
|
||||||
|
--with-http_v2_module \
|
||||||
|
--with-http_gzip_static_module \
|
||||||
|
--with-stream=dynamic \
|
||||||
|
--with-stream_ssl_module \
|
||||||
|
--sbin-path=$PREFIX/nginx/sbin/nginx \
|
||||||
|
--conf-path=$PREFIX/nginx/conf/nginx.conf \
|
||||||
|
--pid-path=$PREFIX/nginx/run/nginx.pid \
|
||||||
|
--lock-path=$PREFIX/nginx/run/nginx.lock \
|
||||||
|
--error-log-path=$PREFIX/nginx/logs/error.log \
|
||||||
|
--http-log-path=$PREFIX/nginx/logs/access.log
|
||||||
|
|
||||||
|
- make
|
||||||
|
- $SUDO make install
|
||||||
23
recipes/nginx/nginx.service.erb
Normal file
23
recipes/nginx/nginx.service.erb
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
sudo tee /etc/systemd/system/nginx-custom.service >/dev/null <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=nginx (custom prefix)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
PIDFile=/pkg/nginx/run/nginx.pid
|
||||||
|
ExecStart=/pkg/nginx/sbin/nginx
|
||||||
|
ExecReload=/pkg/nginx/sbin/nginx -s reload
|
||||||
|
ExecStop=/pkg/nginx/sbin/nginx -s quit
|
||||||
|
TimeoutStopSec=5
|
||||||
|
#User=nginx
|
||||||
|
#Group=nginx
|
||||||
|
LimitNOFILE=65535
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# sudo systemctl daemon-reload
|
||||||
|
# sudo systemctl enable --now nginx-custom
|
||||||
|
|
||||||
|
|
@ -5,8 +5,9 @@ packages:
|
||||||
repository:
|
repository:
|
||||||
url: https://github.com/neovim/neovim.git
|
url: https://github.com/neovim/neovim.git
|
||||||
branch: release-0.11
|
branch: release-0.11
|
||||||
|
version: 0.11
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- make distclean
|
- make distclean
|
||||||
- make CMAKE_BUILD_TYPE=Release CMAKE_INSTALL_PREFIX=$HOME/.local
|
- make CMAKE_BUILD_TYPE=Release CMAKE_INSTALL_PREFIX=$PREFIX
|
||||||
- make install
|
- $SUDO make install
|
||||||
|
|
|
||||||
24
recipes/postgres/debian-setup.yml
Normal file
24
recipes/postgres/debian-setup.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
environment:
|
||||||
|
PG_DOMAIN: gurgul.org
|
||||||
|
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- postgresql
|
||||||
|
- postgresql-contrib
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- $SUDO systemctl enable postgresql
|
||||||
|
- $SUDO systemctl start postgresql
|
||||||
|
# Installing certificates
|
||||||
|
- $SUDO mkdir /etc/postgresql/ssl
|
||||||
|
- $SUDO cp /etc/letsencrypt/live/$PG_DOMAIN/fullchain.pem /etc/postgresql/ssl/server.crt
|
||||||
|
- $SUDO cp /etc/letsencrypt/live/$PG_DOMAIN/privkey.pem /etc/postgresql/ssl/server.key
|
||||||
|
- $SUDO chown postgres:postgres /etc/postgresql/ssl/server.*
|
||||||
|
- $SUDO chmod 600 /etc/postgresql/ssl/server.key
|
||||||
|
|
||||||
|
|
||||||
|
actions:
|
||||||
|
# dat action postgresql:add-user -u user
|
||||||
|
add-user:
|
||||||
|
- sudo -u postgres createuser --no-superuser --no-createdb --no-createrole $DB_USER
|
||||||
|
- sudo -u postgres createdb -O $DB_USER $DB_USER
|
||||||
25
recipes/postgres/debian.yml
Normal file
25
recipes/postgres/debian.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- build-essential
|
||||||
|
- libreadline-dev
|
||||||
|
- zlib1g-dev
|
||||||
|
- flex
|
||||||
|
- bison
|
||||||
|
- libssl-dev
|
||||||
|
- libxml2-dev
|
||||||
|
- libxslt1-dev
|
||||||
|
- libpam0g-dev
|
||||||
|
- libedit-dev
|
||||||
|
|
||||||
|
repository:
|
||||||
|
# Original repository
|
||||||
|
# https://git.postgresql.org/gitweb/?p=postgresql.git
|
||||||
|
url: https://github.com/postgres/postgres.git
|
||||||
|
branch: REL_17_5
|
||||||
|
version: 17.5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- ./configure --prefix=$PREFIX --with-openssl --with-systemd
|
||||||
|
- make -j$CPUS
|
||||||
|
- $SUDO mkdir -p $PREFIX
|
||||||
|
- $SUDO make install
|
||||||
28
recipes/qemu/macos.yml
Normal file
28
recipes/qemu/macos.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
packages:
|
||||||
|
- meson
|
||||||
|
- ninja
|
||||||
|
- pkg-config
|
||||||
|
- glib
|
||||||
|
- pixman
|
||||||
|
- sdl2
|
||||||
|
- libepoxy
|
||||||
|
- libslirp
|
||||||
|
- gettext
|
||||||
|
|
||||||
|
|
||||||
|
# pkg-config --modversion sdl2 # should print a version
|
||||||
|
# pkg-config --modversion epoxy # should print a version
|
||||||
|
|
||||||
|
repository:
|
||||||
|
url: https://gitlab.com/qemu-project/qemu.git
|
||||||
|
branch: v10.0.3
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- |
|
||||||
|
../configure \
|
||||||
|
--enable-sdl \
|
||||||
|
--enable-opengl \
|
||||||
|
--target-list=aarch64-softmmu,x86_64-softmmu \
|
||||||
|
--prefix="$HOME/.local/qemu-sdl"
|
||||||
|
|
@ -16,6 +16,7 @@ packages:
|
||||||
repository:
|
repository:
|
||||||
url: https://github.com/ruby/ruby.git
|
url: https://github.com/ruby/ruby.git
|
||||||
branch: v3_4_5
|
branch: v3_4_5
|
||||||
|
version: 3.4.5
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- ./autogen.sh
|
- ./autogen.sh
|
||||||
|
|
|
||||||
45
recipes/vnc-viewer.yml
Normal file
45
recipes/vnc-viewer.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# # 1) Build & install FLTK 1.4 to /opt/fltk-1.4
|
||||||
|
# git clone https://github.com/fltk/fltk.git
|
||||||
|
# cd fltk
|
||||||
|
# git checkout branch-1.4
|
||||||
|
# cmake -S . -B build \
|
||||||
|
# -DOPTION_BUILD_SHARED_LIBS=ON \
|
||||||
|
# -DOPTION_USE_SYSTEM_LIBPNG=ON \
|
||||||
|
# -DOPTION_USE_SYSTEM_LIBJPEG=ON \
|
||||||
|
# -DOPTION_USE_SYSTEM_ZLIB=ON \
|
||||||
|
# -DCMAKE_INSTALL_PREFIX=/opt/fltk-1.4
|
||||||
|
# cmake --build build -j
|
||||||
|
# sudo cmake --install build
|
||||||
|
|
||||||
|
# # 2) Point pkg-config and CMake at the new install
|
||||||
|
# export PKG_CONFIG_PATH=/opt/fltk-1.4/lib/pkgconfig:$PKG_CONFIG_PATH
|
||||||
|
# export CMAKE_PREFIX_PATH=/opt/fltk-1.4:$CMAKE_PREFIX_PATH
|
||||||
|
# # (optional but sometimes necessary)
|
||||||
|
# export FLTK_DIR=/opt/fltk-1.4/lib/cmake/FLTK
|
||||||
|
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- ninja
|
||||||
|
- pkg-config
|
||||||
|
- fltk
|
||||||
|
- jpeg-turbo
|
||||||
|
- libpng
|
||||||
|
- zlib
|
||||||
|
- gnutls
|
||||||
|
- ffmpeg
|
||||||
|
|
||||||
|
# --recursive
|
||||||
|
repository:
|
||||||
|
url: https://github.com/TigerVNC/tigervnc.git
|
||||||
|
url: v1.15.0
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- mkdir build && cd build
|
||||||
|
- |
|
||||||
|
cmake -G Ninja .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DBUILD_VIEWER=ON \
|
||||||
|
-DBUILD_SERVER=OFF \
|
||||||
|
-DWITH_GNUTLS=ON
|
||||||
|
- ninja
|
||||||
Loading…
Add table
Add a link
Reference in a new issue