Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Hvornum <anton.feeds@gmail.com>2018-05-24 20:30:46 +0200
committerGitHub <noreply@github.com>2018-05-24 20:30:46 +0200
commitf85301544827b20a2ba206092affd3da379842a1 (patch)
tree7f2dc83a9af0fa53085538ffb1210fa5840047c8
parent4031af07597002747ae344dd3e8594520688f4e9 (diff)
parent30010a418a0338ba3f513028794552469a9dae11 (diff)
Merge pull request #3 from Torxed/net-deploy
Network deployment features added.
-rw-r--r--README.md30
-rw-r--r--archinstall.py263
-rw-r--r--deployments/00_11_22_33_44_55.json20
-rw-r--r--deployments/08:00:27:36:83:9b.json21
-rw-r--r--deployments/08:00:27:6f:0c:25.json29
-rw-r--r--deployments/08:00:27:e0:e0:e6.json31
-rw-r--r--deployments/default.json37
-rw-r--r--deployments/workstation.json35
-rw-r--r--install_aur (renamed from make_offline)27
9 files changed, 405 insertions, 88 deletions
diff --git a/README.md b/README.md
index ea7eb7b9..8f04d45b 100644
--- a/README.md
+++ b/README.md
@@ -5,25 +5,30 @@ Just a bare bone automated [Arch](https://wiki.archlinux.org/index.php/Arch_Linu
# cd ~/archlive
# echo -e "git\npython-psutil" >> packages.both
- # echo "cd /root; git clone https://github.com/Torxed/archinstall.git" >> ./airootfs/root/customize_airootfs.sh
+ # echo "cd /root" >> ./airootfs/root/customize_airootfs.sh
+ # echo "git clone https://github.com/Torxed/archinstall.git" >> ./airootfs/root/customize_airootfs.sh
+ # echo "cd archinstall; git checkout net-deploy; cd /root" >> ./airootfs/root/customize_airootfs.sh
# echo "chmod +x ~/archinstall/archinstall.py" >> ./airootfs/root/customize_airootfs.sh
# mkdir ./airootfs/etc/skel
# echo '[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && sh -c ~/archinstall/archinstall.py' >> ./airootfs/etc/skel/.zprofile
- # rm -v work/build.make_* && ./build.sh -v
+ # rm -v work*; ./build.sh -v
> Note: `~/archlive` might be different on your system, see [ArchISO#Setup](https://wiki.archlinux.org/index.php/archiso#Setup) for more info.
-Whenever this live-cd boots, from here on now - it'll run `archinstall.py`.
+Whenever this live-cd boots, from here on now - it'll run `archinstall.py` with the `net-deploy` branch.
-> CAUTION: If no parameters are given, it will devour the first disk in your system (/dev/sda, /dev/nvme0n1p2 etc).
+> CAUTION: If no parameters are given, it will devour the first disk in your system (/dev/sda, /dev/nvme0n1 etc).
# Manually run it on a booted Live CD
- # pacman -Sy git
- # git clone https://github.com/Torxed/archinstall.git
- # python3 ./archinstall/archinstall.py
+ # wget https://raw.githubusercontent.com/Torxed/archinstall/net-deploy/archinstall.py
+ # python3 archinstall.py
+
+# Rerunning a installation
-> Note: *(You could also wget the `archinstall.py` script and skip installing git)*
+ # umount -R /mnt; cryptsetup close /dev/mapper/luksdev
+ # python3 ./archinstall/archinstall.py
+> Note: This assumes `--post=stay` is set to avoid instant reboot at the end.
# Some parameters you can give it
@@ -37,8 +42,11 @@ Whenever this live-cd boots, from here on now - it'll run `archinstall.py`.
Sets the starting location of the root partition
(TODO: /boot will take up space from 1MiB - <start>, make sure boot is no larger than 513MiB)
+ --password=0000 (Default)
+ Which disk password to use, --password="<STDIN>" for prompt of password.
+
--pwfile=/tmp/diskpw (Default)
- Which file to use as the disk encryption password
+ Which file to store the disk encryption password while sending it to cryptsetup
--hostname=Arcinstall (Default)
Sets the hostname of the box
@@ -54,7 +62,9 @@ Whenever this live-cd boots, from here on now - it'll run `archinstall.py`.
Adds an additional username to the system (default group Wheel)
--post=reboot (Default)
- After a successful install, reboots into the system.
+ After a successful install, reboots into the system. Use --post=stay to not reboot.
+
+net-deployment structs support all these and more. Custom arguments with string formatting. See [deployments/workstation.json](https://github.com/Torxed/archinstall/blob/net-deploy/deployments/workstation.json) for examples.
## End note
diff --git a/archinstall.py b/archinstall.py
index 2d8ad2c4..66d0f6c3 100644
--- a/archinstall.py
+++ b/archinstall.py
@@ -1,15 +1,21 @@
#!/usr/bin/python3
+import traceback
import psutil, os, re, struct, sys, json
-import urllib.request, urllib.parse
+import urllib.request, urllib.parse, ssl
from glob import glob
#from select import epoll, EPOLLIN, EPOLLHUP
from socket import socket, inet_ntoa, AF_INET, AF_INET6, AF_PACKET
from collections import OrderedDict as oDict
from subprocess import Popen, STDOUT, PIPE
+from time import sleep
+
+## FIXME: dependency checks (fdisk, lsblk etc)
rootdir_pattern = re.compile('^.*?/devices')
harddrives = oDict()
+deploy_target = 'https://raw.githubusercontent.com/Torxed/archinstall/net-deploy/deployments'
+
args = {}
positionals = []
for arg in sys.argv[1:]:
@@ -41,19 +47,21 @@ def get_local_MACs():
macs[addr.address] = nic
return macs
-def run(cmd, echo=False, *args, **kwargs):
- #print('[!] {}'.format(cmd))
+def run(cmd, echo=False, opts=None, *args, **kwargs):
+ if not opts: opts = {}
+ if echo or 'debug' in opts:
+ print('[!] {}'.format(cmd))
handle = Popen(cmd, shell='True', stdout=PIPE, stderr=STDOUT, **kwargs)
output = b''
while handle.poll() is None:
data = handle.stdout.read()
if len(data):
- if echo and 'flush':
+ if echo or 'debug' in opts:
print(data.decode('UTF-8'), end='')
# print(data.decode('UTF-8'), end='')
output += data
data = handle.stdout.read()
- if echo:
+ if echo or 'debug' in opts:
print(data.decode('UTF-8'), end='')
output += data
handle.stdout.close()
@@ -101,10 +109,11 @@ def grab_partitions(dev):
parts = oDict()
o = run('lsblk -o name -J -b {dev}'.format(dev=dev))
r = json.loads(o)
- for part in r['blockdevices'][0]['children']:
- parts[part['name'][len(drive_name):]] = {
- # TODO: Grab partition info and store here?
- }
+ if len(r['blockdevices']) and 'children' in r['blockdevices'][0]:
+ for part in r['blockdevices'][0]['children']:
+ parts[part['name'][len(drive_name):]] = {
+ # TODO: Grab partition info and store here?
+ }
return parts
@@ -130,35 +139,109 @@ def multisplit(s, splitters):
def grab_url_data(path):
safe_path = path[:path.find(':')+1]+''.join([item if item in ('/', '?', '=', '&') else urllib.parse.quote(item) for item in multisplit(path[path.find(':')+1:], ('/', '?', '=', '&'))])
- response = urllib.request.urlopen(safe_path)
+ ssl_context = ssl.create_default_context()
+ ssl_context.check_hostname = False
+ ssl_context.verify_mode=ssl.CERT_NONE
+ response = urllib.request.urlopen(safe_path, context=ssl_context)
return response.read()
+def get_instructions(target):
+ instructions = {}
+ try:
+ instructions = grab_url_data('{}/{}.json'.format(deploy_target, target))
+ except urllib.error.HTTPError:
+ print('[N] No instructions found called: {}'.format(target))
+ return instructions
+
+ print('[N] Found net-deploy instructions called: {}'.format(target))
+ try:
+ instructions = json.loads(instructions.decode('UTF-8'), object_pairs_hook=oDict)
+ except:
+ print('[E] JSON instructions failed to load for {}'.format(target))
+ traceback.print_exc()
+ sleep(5)
+
+ return instructions
+
+def merge_dicts(d1, d2, before=True, overwrite=False):
+ """ Merges d2 into d1 """
+ if before:
+ d1, d2 = d2.copy(), d1.copy()
+ overwrite = True
+
+ for key, val in d2.items():
+ if key in d1:
+ if type(d1[key]) in [dict, oDict] and type(d2[key]) in [dict, oDict]:
+ d1[key] = merge_dicts(d1[key] if not before else d2[key], d2[key] if not before else d1[key], before=before, overwrite=overwrite)
+ elif overwrite:
+ d1[key] = val
+ else:
+ d1[key] = val
+
+ return d1
+
if __name__ == '__main__':
update_git() # Breaks and restarts the script if an update was found.
update_drive_list()
+ if not os.path.isdir('/sys/firmware/efi'):
+ print('[E] This script only supports UEFI-booted machines.')
+ exit(1)
+ ## Setup some defaults (in case no command-line parameters or netdeploy-params were given)
if not 'drive' in args: args['drive'] = list(harddrives.keys())[0] # First drive found
if not 'size' in args: args['size'] = '100%'
if not 'start' in args: args['start'] = '513MiB'
if not 'pwfile' in args: args['pwfile'] = '/tmp/diskpw'
if not 'hostname' in args: args['hostname'] = 'Arcinstall'
- if not 'country' in args: args['country'] = 'SE' #all
- if not 'packages' in args: args['packages'] = ''
+ if not 'country' in args: args['country'] = 'SE' # 'all' if we don't want country specific mirrors.
+ if not 'packages' in args: args['packages'] = '' # extra packages other than default
if not 'post' in args: args['post'] = 'reboot'
+ if not 'password' in args: args['password'] = '0000' # Default disk passord, can be <STDIN> or a fixed string
+
+ ## == If we got networking,
+ # Try fetching instructions for this box and execute them.
+ instructions = {}
+ if get_default_gateway_linux():
+ locmac = get_local_MACs()
+ if not len(locmac):
+ print('[N] No network interfaces - No net deploy.')
+ else:
+ for mac in locmac:
+ instructions = get_instructions(mac)
+
+ if 'args' in instructions:
+ ## == Recursively fetch instructions if "include" is found under {args: ...}
+ while 'include' in instructions['args']:
+ includes = instructions['args']['include']
+ print('[!] Importing net-deploy target: {}'.format(includes))
+ del(instructions['args']['include'])
+ if type(includes) in (dict, list):
+ for include in includes:
+ instructions = merge_dicts(instructions, get_instructions(include), before=True)
+ else:
+ instructions = merge_dicts(instructions, get_instructions(includes), before=True)
+
+ ## Update arguments if we found any
+ for key, val in instructions['args'].items():
+ args[key] = val
+ else:
+ print('[N] No gateway - No net deploy')
+
+ if args['password'] == '<STDIN>': args['password'] = input('Enter a disk (and root) password: ')
print(args)
if not os.path.isfile(args['pwfile']):
- PIN = '0000'
+ #PIN = '0000'
with open(args['pwfile'], 'w') as pw:
- pw.write(PIN)
- else:
- ## TODO: Convert to `rb` instead.
- # We shouldn't discriminate \xfu from being a passwd phrase.
- with open(args['pwfile'], 'r') as pw:
- PIN = pw.read().strip()
+ pw.write(args['password'])
+ #else:
+ # ## TODO: Convert to `rb` instead.
+ # # We shouldn't discriminate \xfu from being a passwd phrase.
+ # with open(args['pwfile'], 'r') as pw:
+ # PIN = pw.read().strip()
print()
- print('[!] Disk PASSWORD is: {}'.format(PIN))
+ print('[!] Disk PASSWORD is: {}'.format(args['password']))
print()
print('[N] Setting up {drive}.'.format(**args))
# dd if=/dev/random of=args['drive'] bs=4096 status=progress
@@ -170,37 +253,87 @@ if __name__ == '__main__':
o = run('parted -s {drive} set 1 boot on'.format(**args))
o = run('parted -s {drive} mkpart primary {start} {size}'.format(**args))
- first, second = grab_partitions(args['drive']).keys()
- o = run('mkfs.vfat -F32 {drive}{part1}'.format(**args, part1=first))
+ args['paritions'] = grab_partitions(args['drive'])
+ if len(args['paritions']) <= 0:
+ print('[E] No paritions were created on {drive}'.format(**args), o)
+ exit(1)
+ for index, part_name in enumerate(args['paritions']):
+ args['partition_{}'.format(index+1)] = part_name
+
+ o = run('mkfs.vfat -F32 {drive}{partition_1}'.format(**args))
+ if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o:
+ print('[E] Could not setup {drive}{partition_1}'.format(**args), o)
+ exit(1)
# "--cipher sha512" breaks the shit.
# TODO: --use-random instead of --use-urandom
- print('[N] Adding encryption to {drive}{part2}.'.format(**args, part2=second))
- o = run('cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {pwfile} --use-urandom luksFormat {drive}{part2}'.format(**args, part2=second))
+ print('[N] Adding encryption to {drive}{partition_2}.'.format(**args))
+ o = run('cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {pwfile} --use-urandom luksFormat {drive}{partition_2}'.format(**args))
if not o.decode('UTF-8').strip() == 'Command successful.':
- print('[E] Failed to setup disk encryption.')
+ print('[E] Failed to setup disk encryption.', o)
exit(1)
- o = run('cryptsetup open {drive}{part2} luksdev --key-file {pwfile} --type luks2'.format(**args, part2=second))
+ o = run('cryptsetup open {drive}{partition_2} luksdev --key-file {pwfile} --type luks2'.format(**args))
o = run('file /dev/mapper/luksdev') # /dev/dm-0
if b'cannot open' in o:
- print('[E] Could not mount encrypted device.')
+ print('[E] Could not mount encrypted device.', o)
exit(1)
+ print('[N] Creating btrfs filesystem inside {drive}{partition_2}'.format(**args))
o = run('mkfs.btrfs /dev/mapper/luksdev')
+ if not b'UUID' in o:
+ print('[E] Could not setup btrfs filesystem.', o)
+ exit(1)
o = run('mount /dev/mapper/luksdev /mnt')
- print('[N] Reordering mirrors.')
os.makedirs('/mnt/boot')
- o = run('mount {drive}{part1} /mnt/boot'.format(**args, part1=first))
- o = run("wget 'https://www.archlinux.org/mirrorlist/?country={country}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist".format(**args))
- o = run("sed -i 's/#Server/Server/' /root/mirrorlist")
- o = run('rankmirrors -n 6 /root/mirrorlist > /etc/pacman.d/mirrorlist')
+ o = run('mount {drive}{partition_1} /mnt/boot'.format(**args))
+
+ print('[N] Reordering mirrors.')
+ if 'mirrors' in args and args['mirrors'] and get_default_gateway_linux():
+ o = run("wget 'https://www.archlinux.org/mirrorlist/?country={country}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist".format(**args))
+ o = run("sed -i 's/#Server/Server/' /root/mirrorlist")
+ o = run('rankmirrors -n 6 /root/mirrorlist > /etc/pacman.d/mirrorlist')
+
+ pre_conf = {}
+ if 'pre' in instructions:
+ pre_conf = instructions['pre']
+ elif 'prerequisits' in instructions:
+ pre_conf = instructions['prerequisits']
+
+ ## Prerequisit steps needs to NOT be executed in arch-chroot.
+ ## Mainly because there's no root structure to chroot into.
+ ## But partly because some configurations need to be done against the live CD.
+ ## (For instance, modifying mirrors are done on LiveCD and replicated intwards)
+ for title in pre_conf:
+ print('[N] Network prerequisit step: {}'.format(title))
+ for command in pre_conf[title]:
+ raw_command = command
+ opts = pre_conf[title][raw_command] if type(pre_conf[title][raw_command]) in (dict, oDict) else {}
+ if len(opts):
+ if 'pass-args' in opts or 'format' in opts:
+ command = command.format(**args)
+ if 'pass-args' in opts:
+ del(opts['pass-args'])
+ elif 'format' in opts:
+ del(opts['format'])
+ else:
+ print('[-] Options: {}'.format(opts))
+
+ #print('[N] Command: {} ({})'.format(raw_command, opts))
+ o = run('{c}'.format(c=command), opts)
+ if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in o:
+ print('[W] Prerequisit step failed: {}'.format(o.decode('UTF-8')))
+ #print(o)
print('[N] Straping in packages.')
o = run('pacman -Syy')
o = run('pacstrap /mnt base base-devel btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args))
+ if not os.path.isdir('/mnt/etc'):
+ print('[E] Failed to strap in packages', o)
+ exit(1)
+
o = run('genfstab -pU /mnt >> /mnt/etc/fstab')
with open('/mnt/etc/fstab', 'a') as fstab:
fstab.write('\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n') # Redundant \n at the start? who knoes?
@@ -211,17 +344,18 @@ if __name__ == '__main__':
#o = run('arch-chroot /mnt echo "{hostname}" > /etc/hostname'.format(**args))
#o = run("arch-chroot /mnt sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen")
o = run("arch-chroot /mnt sh -c \"echo '{hostname}' > /etc/hostname\"".format(**args))
- o = run("arch-chroot /mnt sh -c \"echo -n 'en_US.UTF-8' > /etc/locale.gen\"")
+ o = run("arch-chroot /mnt sh -c \"echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen\"")
+ o = run("arch-chroot /mnt sh -c \"echo 'LANG=en_US.UTF-8' > /etc/locale.conf\"")
o = run('arch-chroot /mnt locale-gen')
o = run('arch-chroot /mnt chmod 700 /root')
## == Passwords
- # o = run('arch-chroot /mnt usermod --password {} root'.format(PIN))
- # o = run("arch-chroot /mnt sh -c 'echo {pin} | passwd --stdin root'".format(pin='"{pin}"'.format(**args, pin=PIN)), echo=True)
- o = run("arch-chroot /mnt sh -c \"echo 'root:{pin}' | chpasswd\"".format(**args, pin=PIN))
+ # o = run('arch-chroot /mnt usermod --password {} root'.format(args['password']))
+ # o = run("arch-chroot /mnt sh -c 'echo {pin} | passwd --stdin root'".format(pin='"{pin}"'.format(**args, pin=args['password'])), echo=True)
+ o = run("arch-chroot /mnt sh -c \"echo 'root:{pin}' | chpasswd\"".format(**args, pin=args['password']))
if 'user' in args:
o = run('arch-chroot /mnt useradd -m -G wheel {user}'.format(**args))
- o = run("arch-chroot /mnt sh -c \"echo '{user}:{pin}' | chpasswd\"".format(**args, pin=PIN))
+ o = run("arch-chroot /mnt sh -c \"echo '{user}:{pin}' | chpasswd\"".format(**args, pin=args['password']))
with open('/mnt/etc/mkinitcpio.conf', 'w') as mkinit:
## TODO: Don't replace it, in case some update in the future actually adds something.
@@ -238,41 +372,38 @@ if __name__ == '__main__':
## For some reason, blkid and /dev/disk/by-uuid are not getting along well.
## And blkid is wrong in terms of LUKS.
- #UUID = run('blkid -s PARTUUID -o value {drive}{part2}'.format(**args, part2=second)).decode('UTF-8').strip()
- UUID = run("ls -l /dev/disk/by-uuid/ | grep {basename}{part2} | awk '{awk}'".format(basename=os.path.basename(args['drive']), part2=second, awk='{print $9}')).decode('UTF-8').strip()
+ #UUID = run('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip()
+ UUID = run("ls -l /dev/disk/by-uuid/ | grep {basename}{partition_2} | awk '{{print $9}}'".format(basename=os.path.basename(args['drive']), **args)).decode('UTF-8').strip()
with open('/mnt/boot/loader/entries/arch.conf', 'w') as entry:
entry.write('title Arch Linux\n')
entry.write('linux /vmlinuz-linux\n')
entry.write('initrd /initramfs-linux.img\n')
entry.write('options cryptdevice=UUID={UUID}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n'.format(UUID=UUID))
- ## == If we got networking,
- # Try fetching instructions for this box and execute them.
- if get_default_gateway_linux():
- locmac = get_local_MACs()
- for mac in locmac:
- try:
- instructions = grab_url_data('https://raw.githubusercontent.com/Torxed/archinstall/net-deploy/deployments/{}.json'.format(mac))
- except (urllib.error.HTTPError, urllib.error.URLError) as e:
- print('[N] No instructions for this box on this mac: {}'.format(mac))
- continue
-
- #print('Decoding:', instructions)
- instructions = json.loads(instructions.decode('UTF-8'), object_pairs_hook=oDict)
-
- for title in instructions:
- print('[N] Network Deploy: {}'.format(title))
- for command in instructions[title]:
- opts = instructions[title][command] if type(instructions[title][command]) in (dict, oDict) else {}
-
- #print('[N] Command: {} ({})'.format(command, opts))
- o = run('arch-chroot /mnt {c}'.format(c=command), **opts)
- if type(instructions[title][command]) == bytes and len(instructions[title][command]) and not instructions[title][command] in o:
- print('[W] Post install command failed: {}'.format(o.decode('UTF-8')))
- #print(o)
-
- o = run('umount -R /mnt')
+ conf = {}
+ if 'post' in instructions:
+ conf = instructions['post']
+ elif not 'args' in instructions and len(instructions):
+ conf = instructions
+
+ for title in conf:
+ print('[N] Network Deploy: {}'.format(title))
+ for command in conf[title]:
+ raw_command = command
+ opts = conf[title][command] if type(conf[title][command]) in (dict, oDict) else {}
+ if len(opts):
+ print('[-] Options: {}'.format(opts))
+ if 'pass-args' in opts and opts['pass-args']:
+ command = command.format(**args)
+
+ #print('[N] Command: {} ({})'.format(command, opts))
+ o = run('arch-chroot /mnt {c}'.format(c=command), opts)
+ if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in o:
+ print('[W] Post install command failed: {}'.format(o.decode('UTF-8')))
+ #print(o)
+
if args['post'] == 'reboot':
+ o = run('umount -R /mnt')
o = run('reboot now')
else:
- print('Done. "reboot" when you\'re done tinkering.')
+ print('Done. "umount -R /mnt; reboot" when you\'re done tinkering.')
diff --git a/deployments/00_11_22_33_44_55.json b/deployments/00_11_22_33_44_55.json
new file mode 100644
index 00000000..5526629e
--- /dev/null
+++ b/deployments/00_11_22_33_44_55.json
@@ -0,0 +1,20 @@
+{
+ "args" : {
+ "include" : "workstation",
+ "user" : "anton",
+ "password" : "1111",
+ "drive" : "/dev/sdb",
+ "post" : "don't reboot"
+ },
+ "post" : {
+ "Setup a basic virtual environment": {
+ "mkdir -p /home/{user}/virts" : {"pass-args" : true},
+ "qemu-img create -f qcow2 /home/{user}/virts/test_deploy.qcow2 4G" : {"pass-args" : true},
+ "chown -R {user}.{user} /home/{user}/virts" : {"pass-args" : true}
+ },
+ "Setup user" : {
+ "useradd -m -G wheel -s /bin/bash anton" : null,
+ "sh -c \"echo {user}:{password} | chpasswd\"" : {"pass-args" : true}
+ }
+ }
+}
diff --git a/deployments/08:00:27:36:83:9b.json b/deployments/08:00:27:36:83:9b.json
new file mode 100644
index 00000000..c6e4f698
--- /dev/null
+++ b/deployments/08:00:27:36:83:9b.json
@@ -0,0 +1,21 @@
+{
+ "args" : {
+ "password" : "0000"
+ },
+ "pre" : {
+ "sh -c \"echo -n -e '[arch_offline]\nSigLevel = Optional TrustAll\nServer = http://localmirror.lan/archlinux/os/${arch}' >> /etc/pacman.conf\"" : null
+ },
+ "post" : {
+ "Setup openssh": {
+ "pacman -Syy --noconfirm openssh" : null
+ },
+ "Setup OpenVPN": {
+ "pacman -Syy --noconfirm openvpn" : null
+ },
+ "Setup autostarts": {
+ "systemctl enable dhcpcd" : null,
+ "systemctl enable openssh" : null,
+ "systemctl enable openvpn-client@testclient" : null
+ }
+ }
+}
diff --git a/deployments/08:00:27:6f:0c:25.json b/deployments/08:00:27:6f:0c:25.json
new file mode 100644
index 00000000..423fe872
--- /dev/null
+++ b/deployments/08:00:27:6f:0c:25.json
@@ -0,0 +1,29 @@
+{
+ "args" : {
+ "password" : "0000",
+ "post" : "stay"
+ },
+ "post" : {
+ "Installing DNS + Database": {
+ "pacman -Syy --noconfirm powerdns postgresql" : null
+ },
+ "Setup Database": {
+ "sh -c \"echo 'postgres:{pin}' | chpasswd\"" : null,
+ "su - postgres -c \"initdb --locale $LANG -E UTF8 -D '/var/lib/postgres/data'\"" : null,
+ "systemctl start postgresql" : null,
+ "su - postgres -c \"psql -c \\\"CREATE USER pdns WITH PASSWORD 'SomePassword';\\\"\"" : {"debug" : true}
+ },
+ "Setup DNS": {
+ "sh -c \"echo -e 'launch=gpgsql\ngpgsql-host=127.0.0.1\ngpgsql-user=pdns\ngpgsql-dbname=pdns\ngpgsql-password={PIN}' >> /etc/powerdns/pdns.conf\"" : null,
+ "psql -U pdns -d pdns -a -f /usr/share/doc/powerdns/schema.pgsql.sql" : null
+ },
+ "Install DNS Entries": {
+
+ },
+ "Setup autostarts": {
+ "systemctl enable dhcpcd" : null,
+ "systemctl enable postgresql" : null,
+ "systemctl enable powerdns" : null
+ }
+ }
+}
diff --git a/deployments/08:00:27:e0:e0:e6.json b/deployments/08:00:27:e0:e0:e6.json
new file mode 100644
index 00000000..79347f8b
--- /dev/null
+++ b/deployments/08:00:27:e0:e0:e6.json
@@ -0,0 +1,31 @@
+{
+ "args" : {
+ "password" : "0001"
+ },
+ "post" : {
+ "Setup temp build env": {
+ "pacman -Syy --noconfirm git" : null,
+ "useradd -m -G wheel builder" : null,
+ "sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /etc/sudoers" : null
+ },
+ "install lighttpd2-git": {
+ "git clone https://aur.archlinux.org/lighttpd2-git.git /home/builder/lighttpd2" : null,
+ "chown -R builder.builder /home/builder/lighttpd2" : null,
+ "su - builder -c \"(cd /home/builder/lighttpd2/; /usr/bin/makepkg -s --noconfirm)\"" : null,
+ "sh -c 'pacman -U --noconfirm /home/builder/lighttpd2/*.xz'" : null
+ },
+ "Remove temp build env": {
+ "rm -rf /home/builder/lighttpd2" : null,
+ "sed -i 's/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/' /etc/sudoers" : null
+ },
+ "Create mirror": {
+ "mkdir -p /srv/http/archlinux/arch_offline/os/x86_64" : null,
+ "pacman --noconfirm --dbpath /tmp/ -Syu -w --cachedir /srv/http/archlinux/arch_offline/os/x86_64 base base-devel git python python-systemd awesome xorg-xinit xorg-server xterm nano screen sudo iptables mesa-libgl dhclient dnsmasq darkhttpd openssh sshfs openssl openvpn gcc openvpn rtorrent powerdns postgresql" : null,
+ "sh -c 'repo-add /srv/http/archlinux/arch_offline/os/x86_64/arch_offline.db.tar.gz /srv/http/archlinux/arch_offline/os/x86_64/*.pkg.tar.xz'" : null
+ },
+ "Setup autostarts": {
+ "systemctl enable dhcpcd" : null,
+ "systemctl enable lighttpd2" : null
+ }
+ }
+}
diff --git a/deployments/default.json b/deployments/default.json
new file mode 100644
index 00000000..c2d34267
--- /dev/null
+++ b/deployments/default.json
@@ -0,0 +1,37 @@
+{
+ "args" : {
+ "password" : "<STDIN>",
+ "user" : "anton",
+ "_webbrowser" : "chromium",
+ "_window_manager" : "awesome",
+ "_keyboard_layout" : "sv-latin1"
+ },
+ "post" : {
+ "Install workstation packages": {
+ "pacman -Syy --noconfirm {_webbrowser} {_window_manager} openssh sshfs git dhclient ttf-freefont xorg-server xorg-xrandr xorg-xinit xterm nano wget pulseaudio pulseaudio-alsa pavucontrol smbclient cifs-utils xscreensaver" : null
+ },
+ "Enable autostarts": {
+ "systemctl enable dhcpcd" : null
+ },
+ "Setup desktop environment" : {
+ "sed -i 's/^twm &/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^xclock/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^xterm/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^exec xterm/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sh -c \"echo 'setxkbmap se' >> /etc/X11/xinit/xinitrc\"" : null,
+ "sh -c \"echo 'xscreensaver -no-splash &' >> /etc/X11/xinit/xinitrc\"" : null,
+ "sh -c \"echo 'exec {_window_manager}' >> /etc/X11/xinit/xinitrc\"" : {"pass-args" : true},
+ "sh -c \"echo 'KEYMAP={_keyboard_layout}\nFONT=lat9w-16' >> /etc/vconsole.conf\"" : {"pass-args" : true},
+ "sh -c \"sed -i 's/{ \\\"open terminal\\\", terminal/{ \\\"Chromium\\\", \\\"chromium\\\" },\n &1/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"sed -i 's/{ \\\"open terminal\\\", terminal/{ \\\"File handler\\\", \\\"nemo\\\" },\n &1/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"sed -i 's/^globalkeys = gears.table.join(/&\n awful.key({ modkey, }, \\\"l\\\", function() awful.spawn(\\\"xscreensaver-command -lock &\\\") end),\n/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"awk -i inplace -v RS='' '{gsub(/awful.key\\({ modkey,.*?}, \\\"Tab\\\",.*?\\\"client\\\"}\\),/, \\\"awful.key({ modkey, }, \\\"Tab\\\",\\\n function ()\\\n awful.client.focus.byidx(-1)\\\n if client.focus then\\\n client.focus:raise()\\\n end\\\n end),\\\n awful.key({ modkey, \\\"Shift\\\" }, \\\"Tab\\\",\\\n function ()\\\n awful.client.focus.byidx(1)\\\n if client.focus then\\\n client.focus.raise()\\\n end\\\n end),\\\"); print}' /etc/xdg/awesome/rc.lua\"" : null,
+ "gsettings set org.nemo.desktop show-desktop-icons false" : null,
+ "xdg-mime default nemo.desktop inode/directory application/x-gnome-saved-search" : null
+ },
+ "Setup users" : {
+ "useradd -m -G wheel -s /bin/bash anton" : null,
+ "sh -c \"echo {user}:{password} | chpasswd\"" : {"pass-args" : true}
+ }
+ }
+}
diff --git a/deployments/workstation.json b/deployments/workstation.json
new file mode 100644
index 00000000..50686193
--- /dev/null
+++ b/deployments/workstation.json
@@ -0,0 +1,35 @@
+{
+ "args" : {
+ "password" : "<STDIN>",
+ "_mediaplayer" : "lollypop gstreamer gst-plugins-good gnome-keyring",
+ "_webbrowser" : "chromium",
+ "_window_manager" : "awesome",
+ "_keyboard_layout" : "sv-latin1",
+ "_virtulization" : "qemu ovmf",
+ "post" : "don't reboot"
+ },
+ "post" : {
+ "Install workstation packages": {
+ "pacman -Syy --noconfirm openssh sshfs git {_webbrowser} {_mediaplayer} {_window_manager} {_virtulization} dhclient ttf-freefont xorg-server xorg-xrandr xorg-xinit xterm nano wget pulseaudio pulseaudio-alsa pavucontrol smbclient cifs-utils xscreensaver" : {"pass-args" : true}
+ },
+ "Setup virtulization" : {
+ "sh -c \"Description=\\\"Bridge for virtual machines\\\"\nInterface=br0\nConnection=bridge\nBindsToInterfaces=(eno1)\nIP=no\nExecUpPost=\\\"ip link set dev br0 address $(cat /sys/class/net/eno1/address); IP=dhcp; ip_set\\\"\nExecDownPre=\\\"IP=dhcp\\\"\n\n## Ignore (R)STP and immediately activate the bridge\nSkipForwardingDelay=yes\"" : null
+ },
+ "Setup desktop environment" : {
+ "sed -i 's/^twm &/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^xclock/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^xterm/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sed -i 's/^exec xterm/#&/' /etc/X11/xinit/xinitrc" : null,
+ "sh -c \"echo 'setxkbmap se' >> /etc/X11/xinit/xinitrc\"" : null,
+ "sh -c \"echo 'xscreensaver -no-splash &' >> /etc/X11/xinit/xinitrc\"" : null,
+ "sh -c \"echo 'exec {_window_manager}' >> /etc/X11/xinit/xinitrc\"" : {"pass-args" : true},
+ "sh -c \"echo 'KEYMAP={_keyboard_layout}\nFONT=lat9w-16' >> /etc/vconsole.conf\"" : {"pass-args" : true},
+ "sh -c \"sed -i 's/{ \\\"open terminal\\\", terminal/{ \\\"Chromium\\\", \\\"chromium\\\" },\n &1/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"sed -i 's/{ \\\"open terminal\\\", terminal/{ \\\"File handler\\\", \\\"nemo\\\" },\n &1/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"sed -i 's/^globalkeys = gears.table.join(/&\n awful.key({ modkey, }, \\\"l\\\", function() awful.spawn(\\\"xscreensaver-command -lock &\\\") end),\n/' /etc/xdg/awesome/rc.lua\"" : null,
+ "sh -c \"awk -i inplace -v RS='' '{gsub(/awful.key\\({ modkey,.*?}, \\\"Tab\\\",.*?\\\"client\\\"}\\),/, \\\"awful.key({ modkey, }, \\\"Tab\\\",\n function ()\n awful.client.focus.byidx(-1)\n if client.focus then\n client.focus:raise()\n end\n end),\n awful.key({ modkey, \\\"Shift\\\" }, \\\"Tab\\\",\n function ()\n awful.client.focus.byidx(1)\n if client.focus then\n client.focus.raise()\n end\n end),\\\"); print}' /etc/xdg/awesome/rc.lua\"" : null,
+ "gsettings set org.nemo.desktop show-desktop-icons false" : null,
+ "xdg-mime default nemo.desktop inode/directory application/x-gnome-saved-search" : null
+ }
+ }
+}
diff --git a/make_offline b/install_aur
index 225dec25..6452c428 100644
--- a/make_offline
+++ b/install_aur
@@ -1,17 +1,24 @@
#!/bin/bash
+# offline_mirror_path - is used to temporarily store build AUR packages
+# in order to "host" them to the build process.
+# The path will be on the build machine, not inside the build itself.
+
work_dir=$1
arch=$2
offline_mirror_path="/tmp/aur_offline"
-# A func to download, build ...
+# A func to download, build and host AUR packages to the ISO build process
build_aur () {
old_dir=`pwd`
package=$1
- # Prep with a build-user:
+ # Prep with a build-user (removed at the end):
+ # TODO: Check if already exists, if so, randomize name/don't remove at the end.
+ # TODO: Don't give permission to wheel, give it only to this user (easy, but needs debugging first)
useradd -m -G wheel builder
sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /etc/sudoers
+ # Extract the AUR package.
cd /tmp
rm -rf ${package} ${package}.tar.gz
wget "https://aur.archlinux.org/cgit/aur.git/snapshot/${package}.tar.gz"
@@ -24,18 +31,12 @@ build_aur () {
su - builder -c "(cd ${build_dir}; makepkg -s --noconfirm)" >/dev/null 2>&1
- echo " => Adding ${package} to local AUR mirror"
+ echo " => Adding ${package} to local AUR hosting directory ${offline_mirror_path}"
mkdir -p ${offline_mirror_path}
sh -c "cp *.xz ${offline_mirror_path}/"
sh -c "repo-add ${offline_mirror_path}/aur_offline.db.tar.gz ${offline_mirror_path}/*.xz"
- if [[ -z $(cat ${old_dir}/packages.both | grep ${package}) ]]; then
- # TODO: save a copy of ${old_dir}/packages.both ONCE, if it doesn't excist already.
- # This in order to revert our AUR changes which will affect a re-build.
- echo " => Adding ${package} to packages.both (from AUR)"
- echo "${package}" >> ${old_dir}/packages.both
- fi
- ## Long term storage inside the ISO? (if we want to install to disk, we need to pass this along)
+ ## Long term storage inside the ISO? (if we want to install from CD to disk or host it to others)
# sh -c "mv *.xz ${old_dir}/$2/$1.pkg.tar.xz"
cd ${old_dir}
@@ -48,8 +49,10 @@ build_aur () {
echo "Starting to sync upstream changes to offline mirror."
rm -rf /tmp/sync /tmp/local
-echo " => Building AUR (Adding packages to packages.both as we go along)"
-build_aur "lighttpd2-git"
+echo " => Building AUR packages (found in packages.aur)"
+for package in $(cat ${work_dir}/packages.aur); do
+ build_aur package
+done
if [[ -z $(cat ${work_dir}/pacman.conf | grep '\[aur_offline\]') ]]; then
echo " => Adding offline mirror to the chroot environment"