diff options
author | Jake Buchholz <tomalok@gmail.com> | 2019-04-29 22:22:13 -0700 |
---|---|---|
committer | Jake Buchholz <tomalok@gmail.com> | 2019-04-29 22:22:13 -0700 |
commit | c8b443e75148a97c926239f2a734a3fcd72b8646 (patch) | |
tree | 05aaf32db315193955260c2eb9caa243767c16c4 | |
parent | 9dc3539850ba4eaf4dedd3ad66be94ec28faa9b0 (diff) | |
download | alpine-ec2-ami-c8b443e75148a97c926239f2a734a3fcd72b8646.tar.bz2 alpine-ec2-ami-c8b443e75148a97c926239f2a734a3fcd72b8646.tar.xz alpine-ec2-ami-c8b443e75148a97c926239f2a734a3fcd72b8646.zip |
sort out bootloader stuff
* packer.conf
+ don't need to pass bootloader
+ pass kernel_mods/kernel_opts
+ use_env_var_file to get around problems with ENV var contents (new execute_command, too)
* profiles/base/1
+ add kernel_modules/options
* scripts/resolve-profile.py.in
+ fold()
- strips quotes from complex keys
- include separator char at beginning of fmt
- different dicts use different separators
+ svcs dict -> scalar
- make vars clearer
- ' ' separator between levels
* setup-ami.sh
+ no longer need to 'tr' REPOS, PKGS, SVCS
+ detect bootloader to use
- when 'grub-efi' is bootloader, partition target device w/small EFI partition, format vfat, install_grub_efi() untested yet
+ merge setup_extlinux into install_extlinux
-rw-r--r-- | packer.conf | 6 | ||||
-rw-r--r-- | profiles/base/1 | 14 | ||||
-rw-r--r-- | scripts/resolve-profile.py.in | 37 | ||||
-rwxr-xr-x | scripts/setup-ami.sh | 135 |
4 files changed, 131 insertions, 61 deletions
diff --git a/packer.conf b/packer.conf index ecd5b81..513f093 100644 --- a/packer.conf +++ b/packer.conf | |||
@@ -71,12 +71,14 @@ provisioners = [ | |||
71 | "APK_TOOLS_SHA256={{user `apk_tools_sha256`}}" | 71 | "APK_TOOLS_SHA256={{user `apk_tools_sha256`}}" |
72 | "ALPINE_KEYS={{user `alpine_keys`}}" | 72 | "ALPINE_KEYS={{user `alpine_keys`}}" |
73 | "ALPINE_KEYS_SHA256={{user `alpine_keys_sha256`}}" | 73 | "ALPINE_KEYS_SHA256={{user `alpine_keys_sha256`}}" |
74 | "BOOTLOADER={{user `bootloader`}}" | ||
75 | "REPOS={{user `repos`}}" | 74 | "REPOS={{user `repos`}}" |
76 | "PKGS={{user `pkgs`}}" | 75 | "PKGS={{user `pkgs`}}" |
77 | "SVCS={{user `svcs`}}" | 76 | "SVCS={{user `svcs`}}" |
77 | "KERNEL_MODS={{user `kernel_modules`}}" | ||
78 | "KERNEL_OPTS={{user `kernel_options`}}" | ||
78 | ] | 79 | ] |
79 | execute_command = "sudo sh -c '{{ .Vars }} {{ .Path }}'" | 80 | use_env_var_file = "true" |
81 | execute_command = "sudo sh -c '. {{.EnvVarFile}} && {{.Path}}'" | ||
80 | } | 82 | } |
81 | ] | 83 | ] |
82 | 84 | ||
diff --git a/profiles/base/1 b/profiles/base/1 index a4c8ab1..3bda7ed 100644 --- a/profiles/base/1 +++ b/profiles/base/1 | |||
@@ -41,7 +41,6 @@ apk_tools = null | |||
41 | apk_tools_sha256 = null | 41 | apk_tools_sha256 = null |
42 | alpine_keys = null | 42 | alpine_keys = null |
43 | alpine_keys_sha256 = null | 43 | alpine_keys_sha256 = null |
44 | bootloader = null | ||
45 | repos {} | 44 | repos {} |
46 | pkgs { | 45 | pkgs { |
47 | linux-virt = true | 46 | linux-virt = true |
@@ -55,12 +54,10 @@ pkgs { | |||
55 | tzdata = true | 54 | tzdata = true |
56 | } | 55 | } |
57 | svcs { | 56 | svcs { |
58 | # sysinit | ||
59 | devfs = "sysinit" | 57 | devfs = "sysinit" |
60 | dmesg = "sysinit" | 58 | dmesg = "sysinit" |
61 | hwdrivers = "sysinit" | 59 | hwdrivers = "sysinit" |
62 | mdev = "sysinit" | 60 | mdev = "sysinit" |
63 | # boot | ||
64 | acpid = "boot" | 61 | acpid = "boot" |
65 | bootmisc = "boot" | 62 | bootmisc = "boot" |
66 | haveged = "boot" | 63 | haveged = "boot" |
@@ -70,13 +67,20 @@ svcs { | |||
70 | swap = "boot" | 67 | swap = "boot" |
71 | sysctl = "boot" | 68 | sysctl = "boot" |
72 | syslog = "boot" | 69 | syslog = "boot" |
73 | # default | ||
74 | chronyd = "default" | 70 | chronyd = "default" |
75 | networking = "default" | 71 | networking = "default" |
76 | sshd = "default" | 72 | sshd = "default" |
77 | tiny-ec2-bootstrap = "default" | 73 | tiny-ec2-bootstrap = "default" |
78 | # shutdown | ||
79 | killprocs = "shutdown" | 74 | killprocs = "shutdown" |
80 | mount-ro = "shutdown" | 75 | mount-ro = "shutdown" |
81 | savecache = "shutdown" | 76 | savecache = "shutdown" |
82 | } | 77 | } |
78 | kernel_modules { | ||
79 | "sd-mod" = true | ||
80 | "usb-storage" = true | ||
81 | "ext4" = true | ||
82 | } | ||
83 | kernel_options { | ||
84 | "console=ttyS0" = true | ||
85 | "console=tty0" = true | ||
86 | } | ||
diff --git a/scripts/resolve-profile.py.in b/scripts/resolve-profile.py.in index 67f9d24..050da00 100644 --- a/scripts/resolve-profile.py.in +++ b/scripts/resolve-profile.py.in | |||
@@ -22,20 +22,23 @@ os.makedirs(profile_dir) | |||
22 | 22 | ||
23 | # func to fold dict down to scalar | 23 | # func to fold dict down to scalar |
24 | def fold(dict, fmt): | 24 | def fold(dict, fmt): |
25 | a = [] | 25 | s = '' |
26 | for k, v in dict.items(): | 26 | for k, v in dict.items(): |
27 | k = k.strip('"') # complex keys may be in quotes | ||
27 | if v == True: | 28 | if v == True: |
28 | a.append(k) | 29 | s += fmt[0] + k |
29 | elif not (v == None or v == False): | 30 | elif not (v == None or v == False): |
30 | a.append(fmt.format(k, v)) | 31 | s += fmt.format(k, v) |
31 | return ','.join(str(x) for x in a) | 32 | return s[1:] |
32 | 33 | ||
33 | # fold these dicts vars down to scalar, based on item values | 34 | # fold these dicts vars down to scalar, based on item values |
34 | fold_dicts = { | 35 | fold_dicts = { |
35 | 'ami_access': '{0}', | 36 | 'ami_access': ',{0}', |
36 | 'ami_regions': '{0}', | 37 | 'ami_regions': ',{0}', |
37 | 'repos': '@{1} {0}', | 38 | 'repos': "\n@{1} {0}", |
38 | 'pkgs': '{0}@{1}' | 39 | 'pkgs': ' {0}@{1}', |
40 | 'kernel_modules': ',{0}', | ||
41 | 'kernel_options': ' {0}' | ||
39 | } | 42 | } |
40 | 43 | ||
41 | # parse/resolve HOCON profile config, we need just the 'builds' portion | 44 | # parse/resolve HOCON profile config, we need just the 'builds' portion |
@@ -62,17 +65,17 @@ for bk, b in builds.items(): | |||
62 | b[dk] = fold(b[dk], fmt) | 65 | b[dk] = fold(b[dk], fmt) |
63 | 66 | ||
64 | # fold 'svcs' dict to scalar | 67 | # fold 'svcs' dict to scalar |
65 | svcs = {} | 68 | lvls = {} |
66 | for svc, v in b['svcs'].items(): | 69 | for svc, lvl in b['svcs'].items(): |
67 | if v == True: | 70 | if lvl == True: |
68 | # service in default runlevel | 71 | # service in default runlevel |
69 | svcs['default'].append(svc) | 72 | lvls['default'].append(svc) |
70 | elif not (v == None or v == False): | 73 | elif not (lvl == None or lvl == False): |
71 | # service in specified runlevel (skip svc when false/null) | 74 | # service in specified runlevel (skip svc when false/null) |
72 | if v not in svcs.keys(): | 75 | if lvl not in lvls.keys(): |
73 | svcs[v] = [] | 76 | lvls[lvl] = [] |
74 | svcs[v].append(svc) | 77 | lvls[lvl].append(svc) |
75 | b['svcs'] = ':'.join(str(l) + '=' + ','.join(str(s) for s in ss) for l, ss in svcs.items()) | 78 | b['svcs'] = ' '.join(str(lvl) + '=' + ','.join(str(svc) for svc in svcs) for lvl, svcs in lvls.items()) |
76 | 79 | ||
77 | # write build def json file | 80 | # write build def json file |
78 | with open(vars_file, 'w') as out: | 81 | with open(vars_file, 'w') as out: |
diff --git a/scripts/setup-ami.sh b/scripts/setup-ami.sh index b79768c..72157a5 100755 --- a/scripts/setup-ami.sh +++ b/scripts/setup-ami.sh | |||
@@ -3,6 +3,9 @@ | |||
3 | 3 | ||
4 | set -eu | 4 | set -eu |
5 | 5 | ||
6 | # what bootloader should we use? | ||
7 | [ -d "/sys/firmware/efi" ] && BOOTLOADER=grub-efi || BOOTLOADER=syslinux | ||
8 | |||
6 | die() { | 9 | die() { |
7 | printf '\033[1;31mERROR:\033[0m %s\n' "$@" >&2 # bold red | 10 | printf '\033[1;31mERROR:\033[0m %s\n' "$@" >&2 # bold red |
8 | exit 1 | 11 | exit 1 |
@@ -55,21 +58,55 @@ fetch_apk_tools() { | |||
55 | find "$store" -name apk | 58 | find "$store" -name apk |
56 | } | 59 | } |
57 | 60 | ||
61 | # mostly from Alpine's /sbin/setup-disk | ||
62 | setup_partitions() { | ||
63 | # TODO: do we really need to waste 1M? | ||
64 | local diskdev="$1" start=1M line= | ||
65 | shift | ||
66 | |||
67 | # create new partitions | ||
68 | ( | ||
69 | for line in "$@"; do | ||
70 | case "$line" in | ||
71 | 0M*) ;; | ||
72 | *) echo "$start,$line"; start= ;; | ||
73 | esac | ||
74 | done | ||
75 | ) | sfdisk --quiet --label $DISKLABEL $diskdev | ||
76 | |||
77 | # create device nodes if not exist | ||
78 | mdev -s | ||
79 | } | ||
80 | |||
58 | make_filesystem() { | 81 | make_filesystem() { |
59 | local device="$1" # target device path | 82 | local device="$1" # target device path |
60 | local target="$2" # mount target | 83 | local root_dev="$1" # root partition |
84 | local target="$2" # mount target | ||
85 | local efi_dev= # EFI partition | ||
86 | |||
87 | if [ "$BOOTLOADER" = 'grub-efi' ]; then | ||
88 | # create a small EFI partition (remainder for root), and format it | ||
89 | setup_partitions "$device" '5M,EF' ',L' | ||
90 | efi_dev="${device}1" | ||
91 | root_dev="${device}2" | ||
92 | mkfs.vfat -n EFI "${device}1" | ||
93 | fi | ||
61 | 94 | ||
62 | mkfs.ext4 -O ^64bit "$device" | 95 | mkfs.ext4 -O ^64bit -L / "$root_dev" |
63 | e2label "$device" / | 96 | mount "$root_dev" "$target" |
64 | mount "$device" "$target" | 97 | |
98 | if [ "$BOOTLOADER" = 'grub-efi' ]; then | ||
99 | mkdir -p "$target"/boot/efi | ||
100 | mount -t vfat "$efi_dev" "$target"/boot/efi | ||
101 | fi | ||
102 | # TODO? return "$root_dev" | ||
65 | } | 103 | } |
66 | 104 | ||
67 | setup_repositories() { | 105 | setup_repositories() { |
68 | local target="$1" # target directory | 106 | local target="$1" # target directory |
69 | local repos="$2" # repositories | ||
70 | 107 | ||
71 | mkdir -p "$target"/etc/apk/keys | 108 | mkdir -p "$target"/etc/apk/keys |
72 | echo "$repos" > "$target"/etc/apk/repositories | 109 | echo "$REPOS" > "$target"/etc/apk/repositories |
73 | } | 110 | } |
74 | 111 | ||
75 | fetch_keys() { | 112 | fetch_keys() { |
@@ -107,9 +144,8 @@ setup_chroot() { | |||
107 | 144 | ||
108 | install_core_packages() { | 145 | install_core_packages() { |
109 | local target="$1" # target directory | 146 | local target="$1" # target directory |
110 | local pkgs="$2" # packages, space separated | ||
111 | 147 | ||
112 | chroot "$target" apk --no-cache add $pkgs | 148 | chroot "$target" apk --no-cache add $PKGS |
113 | 149 | ||
114 | chroot "$target" apk --no-cache add --no-scripts $BOOTLOADER | 150 | chroot "$target" apk --no-cache add --no-scripts $BOOTLOADER |
115 | 151 | ||
@@ -131,26 +167,28 @@ setup_mdev() { | |||
131 | sed -n -i -e '/# fallback/r /tmp/nvme-ebs-mdev.conf' -e 1x -e '2,${x;p}' -e '${x;p}' "$target"/etc/mdev.conf | 167 | sed -n -i -e '/# fallback/r /tmp/nvme-ebs-mdev.conf' -e 1x -e '2,${x;p}' -e '${x;p}' "$target"/etc/mdev.conf |
132 | } | 168 | } |
133 | 169 | ||
134 | # TODO: use alpine-conf setup-*? (based on $BOOTLOADER) | ||
135 | create_initfs() { | 170 | create_initfs() { |
136 | local target="$1" | 171 | local target="$1" |
137 | 172 | ||
138 | # TODO: other useful mkinitfs stuff? | ||
139 | |||
140 | # Create ENA feature for mkinitfs | ||
141 | echo "kernel/drivers/net/ethernet/amazon" > \ | ||
142 | "$target"/etc/mkinitfs/features.d/ena.modules | ||
143 | |||
144 | # Enable ENA and NVME features these don't hurt for any instance and are | 173 | # Enable ENA and NVME features these don't hurt for any instance and are |
145 | # hard requirements of the 5 series and i3 series of instances | 174 | # hard requirements of the 5 series and i3 series of instances |
175 | # TODO: profile-ize? | ||
146 | sed -Ei 's/^features="([^"]+)"/features="\1 nvme ena"/' \ | 176 | sed -Ei 's/^features="([^"]+)"/features="\1 nvme ena"/' \ |
147 | "$target"/etc/mkinitfs/mkinitfs.conf | 177 | "$target"/etc/mkinitfs/mkinitfs.conf |
148 | 178 | ||
149 | chroot "$target" /sbin/mkinitfs $(basename $(find "$target"/lib/modules/* -maxdepth 0)) | 179 | chroot "$target" /sbin/mkinitfs $(basename $(find "$target"/lib/modules/* -maxdepth 0)) |
150 | } | 180 | } |
151 | 181 | ||
152 | # TODO: this is for syslinux only, there's likely a grub equivalence | 182 | install_bootloader() { |
153 | setup_extlinux() { | 183 | local target="$1" |
184 | case "$BOOTLOADER" in | ||
185 | syslinux) install_extlinux "$target" ;; | ||
186 | grub-efi) install_grub_efi "$target" ;; | ||
187 | *) die "unknown bootloader '$BOOTLOADER'" ;; | ||
188 | esac | ||
189 | } | ||
190 | |||
191 | install_extlinux() { | ||
154 | local target="$1" | 192 | local target="$1" |
155 | 193 | ||
156 | # Must use disk labels instead of UUID or devices paths so that this works | 194 | # Must use disk labels instead of UUID or devices paths so that this works |
@@ -159,26 +197,51 @@ setup_extlinux() { | |||
159 | # | 197 | # |
160 | # Enable ext4 because the root device is formatted ext4 | 198 | # Enable ext4 because the root device is formatted ext4 |
161 | # | 199 | # |
162 | # Shorten timeout because EC2 has no way to interact with instance console | 200 | # Shorten timeout (1/10s) as EC2 has no way to interact with instance console |
163 | # | 201 | # |
164 | # ttyS0 is the target for EC2s "Get System Log" feature whereas tty0 is the | 202 | # ttyS0 is the target for EC2s "Get System Log" feature whereas tty0 is the |
165 | # target for EC2s "Get Instance Screenshot" feature. Enabling the serial | 203 | # target for EC2s "Get Instance Screenshot" feature. Enabling the serial |
166 | # port early in extlinux gives the most complete output in the system log. | 204 | # port early in extlinux gives the most complete output in the system log. |
167 | sed -Ei -e "s|^[# ]*(root)=.*|\1=LABEL=/|" \ | 205 | sed -Ei -e "s|^[# ]*(root)=.*|\1=LABEL=/|" \ |
168 | -e "s|^[# ]*(default_kernel_opts)=.*|\1=\"console=ttyS0 console=tty0\"|" \ | 206 | -e "s|^[# ]*(default_kernel_opts)=.*|\1=\"$KERNEL_OPTS\"|" \ |
169 | -e "s|^[# ]*(serial_port)=.*|\1=ttyS0|" \ | 207 | -e "s|^[# ]*(serial_port)=.*|\1=ttyS0|" \ |
170 | -e "s|^[# ]*(modules)=.*|\1=sd-mod,usb-storage,ext4|" \ | 208 | -e "s|^[# ]*(modules)=.*|\1=$KERNEL_MODS|" \ |
171 | -e "s|^[# ]*(default)=.*|\1=virt|" \ | 209 | -e "s|^[# ]*(default)=.*|\1=virt|" \ |
172 | -e "s|^[# ]*(timeout)=.*|\1=1|" \ | 210 | -e "s|^[# ]*(timeout)=.*|\1=1|" \ |
173 | "$target"/etc/update-extlinux.conf | 211 | "$target"/etc/update-extlinux.conf |
212 | |||
213 | chroot "$target" /sbin/extlinux --install /boot | ||
214 | chroot "$target" /sbin/update-extlinux --warn-only | ||
174 | } | 215 | } |
175 | 216 | ||
176 | # TODO: this is for syslinux only, there's likely a grub equivalence | 217 | install_grub_efi() { |
177 | install_extlinux() { | ||
178 | local target="$1" | 218 | local target="$1" |
179 | 219 | ||
180 | chroot "$target" /sbin/extlinux --install /boot | 220 | case "$ARCH" in |
181 | chroot "$target" /sbin/update-extlinux --warn-only | 221 | x86_64) grub_target=x86_64-efi ; fwa=x64 ;; |
222 | aarch64) grub_target=arm64-efi ; fwa=aa64 ;; | ||
223 | *) die "ARCH=$ARCH is currently unsupported" ;; | ||
224 | esac | ||
225 | |||
226 | # TODO: this should be set up when we mkfs/mount | ||
227 | #mkdir -p "$target"/boot/efi | ||
228 | |||
229 | # disable nvram so grub doesn't call efibootmgr | ||
230 | chroot "$target" /sbin/grub-install --target=$grub_target --efi-directory=/boot/efi \ | ||
231 | --bootloader-id=alpine --boot-directory=/boot --no-nvram | ||
232 | |||
233 | # fallback mode | ||
234 | install -D "$target"/boot/efi/EFI/alpine/grub$fwa.efi "$target"/boot/efi/EFI/boot/$fwa.efi | ||
235 | |||
236 | # add cmdline linux defaults to /etc/default/grub | ||
237 | echo "GRUB_CMDLINE_LINUX_DEFAULT=\"modules=$KERNEL_MODS $KERNEL_OPTS\"" >> "$target"/etc/default/grub | ||
238 | |||
239 | # eliminate grub pause | ||
240 | sed -ie 's/^GRUB_TIMEOUT=.$/GRUB_TIMEOUT=0/' "$target"/etc/default/grub | ||
241 | |||
242 | # generate/install new config | ||
243 | [ -e "$target"/boot/grub/grub.cfg ] && cp "$target"/boot/grub/grub.cfg "$target"/boot/grub/grub.cfg.backup | ||
244 | chroot "$target" grub-mkconfig -o /boot/grub/grub.cfg | ||
182 | } | 245 | } |
183 | 246 | ||
184 | setup_fstab() { | 247 | setup_fstab() { |
@@ -188,6 +251,11 @@ setup_fstab() { | |||
188 | # <fs> <mountpoint> <type> <opts> <dump/pass> | 251 | # <fs> <mountpoint> <type> <opts> <dump/pass> |
189 | LABEL=/ / ext4 defaults,noatime 1 1 | 252 | LABEL=/ / ext4 defaults,noatime 1 1 |
190 | EOF | 253 | EOF |
254 | |||
255 | # if we're using grub-efi bootloader, add extra line for EFI partition | ||
256 | if [ "$BOOTLOADER" = 'grub-efi' ]; then | ||
257 | echo "LABEL=EFI /boot/efi vfat defaults,noatime,uid=0,gid=0,umask=077 0 0" >> "$target"/etc/fstab | ||
258 | fi | ||
191 | } | 259 | } |
192 | 260 | ||
193 | setup_networking() { | 261 | setup_networking() { |
@@ -204,9 +272,8 @@ EOF | |||
204 | 272 | ||
205 | enable_services() { | 273 | enable_services() { |
206 | local target="$1" | 274 | local target="$1" |
207 | local svcs="$2" | ||
208 | 275 | ||
209 | local lvl_svcs; for lvl_svcs in $svcs; do | 276 | local lvl_svcs; for lvl_svcs in $SVCS; do |
210 | rc_add "$target" $(echo "$lvl_svcs" | tr =, ' ') | 277 | rc_add "$target" $(echo "$lvl_svcs" | tr =, ' ') |
211 | done | 278 | done |
212 | } | 279 | } |
@@ -267,10 +334,6 @@ cleanup() { | |||
267 | } | 334 | } |
268 | 335 | ||
269 | main() { | 336 | main() { |
270 | local repos=$(echo "$REPOS" | tr , "\n") | ||
271 | local pkgs=$(echo "$PKGS" | tr , ' ') | ||
272 | local svcs=$(echo "$SVCS" | tr : ' ') | ||
273 | |||
274 | local device="/dev/xvdf" | 337 | local device="/dev/xvdf" |
275 | local target="/mnt/target" | 338 | local target="/mnt/target" |
276 | 339 | ||
@@ -285,7 +348,7 @@ main() { | |||
285 | make_filesystem "$device" "$target" | 348 | make_filesystem "$device" "$target" |
286 | 349 | ||
287 | einfo "Configuring Alpine repositories" | 350 | einfo "Configuring Alpine repositories" |
288 | setup_repositories "$target" "$repos" | 351 | setup_repositories "$target" |
289 | 352 | ||
290 | einfo "Fetching Alpine signing keys" | 353 | einfo "Fetching Alpine signing keys" |
291 | fetch_keys "$target" | 354 | fetch_keys "$target" |
@@ -296,19 +359,17 @@ main() { | |||
296 | setup_chroot "$target" | 359 | setup_chroot "$target" |
297 | 360 | ||
298 | einfo "Installing core packages" | 361 | einfo "Installing core packages" |
299 | install_core_packages "$target" "$pkgs" | 362 | install_core_packages "$target" |
300 | 363 | ||
301 | # TODO: syslinux vs grub, maybe use setup-* scripts? | ||
302 | einfo "Configuring and enabling boot loader" | 364 | einfo "Configuring and enabling boot loader" |
303 | create_initfs "$target" | 365 | create_initfs "$target" |
304 | setup_extlinux "$target" | 366 | install_bootloader "$target" |
305 | install_extlinux "$target" | ||
306 | 367 | ||
307 | einfo "Configuring system" | 368 | einfo "Configuring system" |
308 | setup_mdev "$target" | 369 | setup_mdev "$target" |
309 | setup_fstab "$target" | 370 | setup_fstab "$target" |
310 | setup_networking "$target" | 371 | setup_networking "$target" |
311 | enable_services "$target" "$svcs" | 372 | enable_services "$target" |
312 | create_alpine_user "$target" | 373 | create_alpine_user "$target" |
313 | configure_ntp "$target" | 374 | configure_ntp "$target" |
314 | 375 | ||