diff --git a/generate_qemu_img.pl b/generate_qemu_img.pl index 8f2b857..c93ce72 100644 --- a/generate_qemu_img.pl +++ b/generate_qemu_img.pl @@ -10,6 +10,7 @@ use Path::Tiny; use lib path(__FILE__)->parent->child('lib') . ''; use BaseUtils; +use Digest::SHA qw/sha512_base64/; my $utils = BaseUtils->new; @@ -17,23 +18,154 @@ main(); sub main() { die 'Must be superuser.' if $< != 0; - my $source_dir = shift @ARGV or die 'No source dir passed.'; + my $source_dir = shift @ARGV or die 'No source dir passed.'; $source_dir = path $source_dir; my $dest_img = shift @ARGV // 'gentoo.qcow2'; - if (-e $dest_img) { + if ( -e $dest_img ) { die "Image $dest_img already exists."; } $dest_img = path $dest_img; - my $size_img = shift @ARGV // 1000; + my $size_img = shift @ARGV // 1000; + my $tempdir_installation = path '/mnt/image'; + $tempdir_installation->mkpath; + if ( $tempdir_installation->children ) { + die "$tempdir_installation is not empty."; + } + eval { + modprobeNbd(); + createQemuImage( $dest_img, $size_img ); + say 4; + mountQemuNbd($dest_img); + say 5; + createPartitionTable(); + formatPartitions(); + my $root_partuuid = retrieveRootPartuuid(); + my $root_uuid = retrieveRootUuid(); + my $boot_partuuid = retrieveBootPartuuid(); + mountTempDir($tempdir_installation); + copySystem( $source_dir, $tempdir_installation ); + generateFstab( $tempdir_installation, $boot_partuuid, $root_partuuid ); + my $vmlinuz = $utils->getVmlinuz($tempdir_installation); + generateExtlinuxConf( $tempdir_installation, $root_partuuid, $vmlinuz ); + installRootUser($tempdir_installation); + }; + if ($@) { + say STDERR $@; + } umountQemuNbd(); - modprobeNbd(); - createQemuImage($dest_img, $size_img); - mountQemuNbd($dest_img); - createPartitionTable(); +} + +sub installRootUser($tempdir_installation) { + my $passwd = $tempdir_installation->child('etc/passwd'); + my $passwd_contents = ''; + open my $fh, '<', $passwd; + while (my $line = <$fh>) { + say $line; + if ($line =~ /^root:/) { + my @fields = split ':', $line; + $fields[1] = 'x'; + $line = join ':', @fields; + } + $passwd_contents .= $line; + } + $passwd->spew_utf8($passwd_contents); + my $shadow = $tempdir_installation->child('etc/shadow'); + $shadow->spew_utf8(<<"EOF"); +root::10770:0::::: +EOF + system 'chmod', '640', $shadow; +} + +sub generateExtlinuxConf ( $tempdir_installation, $root_partuuid, $vmlinuz ) { + $root_partuuid =~ s/"//g; + my $extlinux_conf = <<"EOF"; +DEFAULT gentoo +LABEL gentoo + LINUX /$vmlinuz + APPEND root=$root_partuuid net.ifnames=0 biosdevname=0 +EOF + $tempdir_installation->child('boot/EFI/BOOT/extlinux.conf') + ->spew_utf8($extlinux_conf); +} + +sub copySystem ( $source_dir, $tempdir_installation ) { + my $return_code = system 'rsync', '-avHAX', '--numeric-ids', '--progress', + "$source_dir/", "$tempdir_installation/"; + if ( $return_code != 0 ) { + die 'Unable to copy system in disk.'; + } +} + +sub umountTempDir ($tempdir_installation) { + system 'umount', '-R', $tempdir_installation; +} + +sub mountTempDir ($tempdir_installation) { + my $return_code = system 'mount', '/dev/nbd5p2', $tempdir_installation; + if ( $return_code != 0 ) { + die 'Unable to mount nbd5p2'; + } + my $boot = $tempdir_installation->child('boot'); + $boot->mkpath; + $return_code = system 'mount', '/dev/nbd5p1', $boot; + if ( $return_code != 0 ) { + die 'Unable to mount nbd5p1'; + } +} + +sub retrieveRootUuid { + open my $fh, '-|', 'blkid'; + while ( my $line = <$fh> ) { + if ( $line !~ m{/dev/nbd5p2} ) { + next; + } + my ($return) = $line =~ /(UUID=\S+)/; + return $return; + } + die 'Unable to find root partuuid.'; +} + +sub retrieveRootPartuuid { + open my $fh, '-|', 'blkid'; + while ( my $line = <$fh> ) { + if ( $line !~ m{/dev/nbd5p2} ) { + next; + } + my ($return) = $line =~ /(PARTUUID=\S+)/; + return $return; + } + die 'Unable to find root partuuid.'; +} + +sub retrieveBootPartuuid { + open my $fh, '-|', 'blkid'; + while ( my $line = <$fh> ) { + if ( $line !~ m{/dev/nbd5p1} ) { + next; + } + my ($return) = $line =~ /(PARTUUID=\S+)/; + return $return; + } + die 'Unable to find boot partuuid.'; +} + +sub generateFstab ( $tempdir_installation, $boot, $root ) { + my $fstab_contents = <<"EOF"; +$boot\t/boot\tvfat\tnoauto,noatime\t1 2 +$root\t/\text4\tnoatime\t0 1 +EOF + my $fstab = $tempdir_installation->child('etc/fstab'); + say $fstab; + $fstab->spew_utf8($fstab_contents); +} + +sub formatPartitions { + system 'mkfs.vfat', '/dev/nbd5p1'; + system 'mkfs.ext4', '/dev/nbd5p2'; } sub createPartitionTable { - open my $fh, "|-", 'fdisk', '/dev/nbd1'; + open my $fh, "|-", 'fdisk', '/dev/nbd5'; print $fh <<'EOF'; g n @@ -51,9 +183,10 @@ EOF close $fh; } -sub createQemuImage($dest_img, $size_img) { - my $return_code = system 'qemu-img', 'create', '-f', 'qcow2', $dest_img, $size_img.'M'; - if ($return_code != 0) { +sub createQemuImage ( $dest_img, $size_img ) { + my $return_code = system 'qemu-img', 'create', '-f', 'qcow2', $dest_img, + $size_img . 'M'; + if ( $return_code != 0 ) { die 'Unable to create qemu-img.'; } } @@ -63,13 +196,14 @@ sub modprobeNbd { system 'modprobe', 'nbd'; } -sub mountQemuNbd($dest_img) { - my $return_code = system 'qemu-nbd', '--connect=/dev/nbd1', $dest_img; - if ($return_code != 0) { +sub mountQemuNbd ($dest_img) { + my $return_code = system 'qemu-nbd', '--connect=/dev/nbd5', $dest_img; + if ( $return_code != 0 ) { die 'Unable to mount qemu-nbd.'; } } sub umountQemuNbd { - system 'qemu-nbd', '--disconnect', '/dev/nbd1'; + system 'umount', '-R', '/mnt/image'; + system 'qemu-nbd', '--disconnect', '/dev/nbd5'; } diff --git a/install_system.pl b/install_system.pl index e7b52e0..f7ed8d8 100644 --- a/install_system.pl +++ b/install_system.pl @@ -30,12 +30,39 @@ sub main() { my $packages = $utils->readPackagesToInstall(); $utils->execChroot($target_dir, 'emerge', '--root', '/mnt/gentoo', '--noreplace', '-K', @$packages); $utils->execChroot($mnt_gentoo, 'rc-update add nginx default'); + $utils->execChroot($mnt_gentoo, 'rc-update add local default'); + my @boot_services = qw( hwclock modules fsck root mtab swap localmount systemd-tmpfiles-setup + termencoding seedrng sysctl bootmisc save-termencoding keymaps save-keymaps procfs binfmt + loopback hostname ); + my @sysinit_services = qw( sysfs devfs udev kmod systemd-tmpfiles-setup-dev dmesg udev cgroups ); + for my $service (@boot_services) { + $utils->execChroot($mnt_gentoo, 'rc-update', 'add', $service, 'boot'); + } + for my $service (@sysinit_services) { + $utils->execChroot($mnt_gentoo, 'rc-update', 'add', $service, 'sysinit'); + } + $utils->install('nginx.conf', $mnt_gentoo->child('etc/nginx/nginx.conf')); _installEfiSyslinux($target_dir, $mnt_gentoo); + _installKernel($target_dir, $mnt_gentoo); + _configureNetwork($mnt_gentoo); +} + +sub _configureNetwork($mnt_gentoo) { +# $mnt_gentoo->child('etc/conf.d/net')->spew_utf8(<<'EOF'); +#config_eth0="192.168.1.1/24" +#EOF + system 'ln', '-sv', '/etc/init.d/net.lo', $mnt_gentoo->child('etc/init.d/net.eth0'); + $utils->execChroot($mnt_gentoo, 'rc-update', 'add', 'net.eth0', 'default'); +} + +sub _installKernel($target_dir, $mnt_gentoo) { + my $vmlinuz = $utils->getVmlinuz($target_dir); + my $return_code = system 'cp', '-v', $target_dir->child("boot/$vmlinuz"), $mnt_gentoo->child('boot'); } sub _installEfiSyslinux($target_dir, $mnt_gentoo) { my @files = grep { -f $_ } $target_dir->child('usr/share/syslinux/efi64')->children; - my $syslinux_dir = $mnt_gentoo->child('boot/efi/EFI/BOOT'); + my $syslinux_dir = $mnt_gentoo->child('boot/EFI/BOOT'); $syslinux_dir->mkpath; for my $file (@files) { if ($file =~ /\.efi$/i) { diff --git a/lib/BaseUtils.pm b/lib/BaseUtils.pm index d643eb0..13761f8 100644 --- a/lib/BaseUtils.pm +++ b/lib/BaseUtils.pm @@ -9,6 +9,30 @@ use utf8; use Moo; use Path::Tiny; +sub install ( $self, $source, $dest ) { + if ( -e $dest + && _getSha512SumFile($dest) eq _getSha512SumFile($source) ) + { + say "$source is already installed, skipping."; + return; + } + say "Target $source differs, installing..."; + my $return_code = system 'sudo', 'cp', '-L', $source, $dest; + if ( $return_code != 0 ) { + die "Unable to install $dest"; + } + return 1; +} + +sub _getSha512SumFile ($file) { + open my $fh, '-|', 'sha512sum', $file; + my $text = <$fh>; + close $fh; + + my ($sha512sum) = $text =~ /^(\S+)/; + return $sha512sum; +} + sub forkWait($self) { my $pid = fork; if ($pid) { @@ -21,6 +45,18 @@ sub forkWait($self) { return; } +sub getVmlinuz ($self, $source) { + my $boot = $source->child('boot'); + open my $fh, '-|', 'ls', '-t', $boot; + while ( my $file = <$fh> ) { + chomp($file); + if ( $file =~ /^vmlinuz/ ) { + return $file; + } + } + die 'Unable to find vmlinuz.'; +} + sub chroot($self, $target) { chroot "$target"; chdir '/'; @@ -91,10 +127,12 @@ sub createBasicMountsChroot ($self, $target) { my $dest_proc = $target->child('proc'); my $dest_dev = $target->child('dev'); my $dest_sys = $target->child('sys'); + my $dest_run = $target->child('run'); $dest_proc->mkpath; $dest_dev->mkpath; $dest_sys->mkpath; + $dest_run->mkpath; $self->mountType( 'proc', $dest_proc ); $self->mountType( 'sysfs', $dest_sys ); diff --git a/make.conf b/make.conf index 6542a58..a9383e6 100644 --- a/make.conf +++ b/make.conf @@ -11,7 +11,7 @@ MAKEOPTS="-j12" FEATURES="buildpkg nodoc noman -nostrip" LINGUAS="en" L10N="en-GB" -USE="-ncurses -doc" +USE="-ncurses -doc -pam" # NOTE: This stage was built with the bindist Use flag enabled diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..bf0997e --- /dev/null +++ b/nginx.conf @@ -0,0 +1,70 @@ +user nginx nginx; +worker_processes 1; + +error_log /var/log/nginx/error_log info; + +events { + worker_connections 1024; + use epoll; +} + +http { + include /etc/nginx/mime.types.nginx; + types_hash_max_size 4096; + default_type application/octet-stream; + + log_format main + '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$gzip_ratio"'; + + client_header_timeout 10m; + client_body_timeout 10m; + send_timeout 10m; + + connection_pool_size 256; + client_header_buffer_size 1k; + large_client_header_buffers 4 2k; + request_pool_size 4k; + + gzip off; + + output_buffers 1 32k; + postpone_output 1460; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + keepalive_timeout 75 20; + + ignore_invalid_headers on; + + index index.html; + + server { + listen 0.0.0.0; + server_name localhost; + + access_log /var/log/nginx/localhost.access_log main; + error_log /var/log/nginx/localhost.error_log info; + + root /var/www/localhost/htdocs; + } + + # SSL example + #server { + # listen 127.0.0.1:443; + # server_name localhost; + + # ssl on; + # ssl_certificate /etc/ssl/nginx/nginx.pem; + # ssl_certificate_key /etc/ssl/nginx/nginx.key; + + # access_log /var/log/nginx/localhost.ssl_access_log main; + # error_log /var/log/nginx/localhost.ssl_error_log info; + + # root /var/www/localhost/htdocs; + #} +} diff --git a/packages b/packages index 8aca795..d8da5c5 100644 --- a/packages +++ b/packages @@ -4,3 +4,24 @@ coreutils perl openrc gentoo-kernel +grep +kbd +procps +net-tools +sed +pam +shadow +acct-user/colord +acct-user/cron +acct-user/man +acct-user/messagebus +acct-user/nginx +acct-user/ntp +acct-user/nullmail +acct-user/polkitd +acct-user/portage +acct-user/radvd +acct-user/sshd +acct-user/tss +acct-user/root +acct-group/root diff --git a/prepare_system.pl b/prepare_system.pl index 58e70a6..9fc1b98 100644 --- a/prepare_system.pl +++ b/prepare_system.pl @@ -105,7 +105,7 @@ sub _checkValidSystem ($target) { sub _installResolvConf ( $target, $resolv_conf ) { my $dest_resolv_conf = $target->child('etc/resolv.conf'); - _install( $resolv_conf, $dest_resolv_conf ); + $utils->install( $resolv_conf, $dest_resolv_conf ); } sub _installGentooConf ( $target, $gentoo_conf ) { @@ -115,7 +115,7 @@ sub _installGentooConf ( $target, $gentoo_conf ) { if ( $return_code != 0 ) { say "Unable to create $repos_conf."; } - _install( $gentoo_conf, $dest_gentoo_conf ); + $utils->install( $gentoo_conf, $dest_gentoo_conf ); } sub _installPackageUse ( $target, $zz_use ) { @@ -125,34 +125,10 @@ sub _installPackageUse ( $target, $zz_use ) { if ( $return_code != 0 ) { say "Unable to create $package_use."; } - _install( $zz_use, $dest_zz_use ); + $utils->install( $zz_use, $dest_zz_use ); } sub _installMakeConf ( $target, $make_conf ) { my $dest_make_conf = $target->child('etc/portage/make.conf'); - return _install( $make_conf, $dest_make_conf ); -} - -sub _install ( $source, $dest ) { - if ( -e $dest - && _getSha512SumFile($dest) eq _getSha512SumFile($source) ) - { - say "$source is already installed, skipping."; - return; - } - say "Target $source differs, installing..."; - my $return_code = system 'sudo', 'cp', '-L', $source, $dest; - if ( $return_code != 0 ) { - die "Unable to install $dest"; - } - return 1; -} - -sub _getSha512SumFile ($file) { - open my $fh, '-|', 'sha512sum', $file; - my $text = <$fh>; - close $fh; - - my ($sha512sum) = $text =~ /^(\S+)/; - return $sha512sum; + return $utils->install( $make_conf, $dest_make_conf ); } diff --git a/zz-use b/zz-use index 4abe1c2..c72463e 100644 --- a/zz-use +++ b/zz-use @@ -1,2 +1,3 @@ app-misc/mime-types nginx sys-kernel/gentoo-kernel -initramfs +sys-apps/util-linux -su