mirror of
https://gitlab.alpinelinux.org/alpine/cloud/tiny-cloud.git
synced 2025-12-15 11:22:43 +03:00
move logic from init scripts to /lib/tiny-cloud/*
This commit is contained in:
parent
07f0e646e8
commit
b5af450a8e
40
README.md
40
README.md
@ -22,8 +22,8 @@ instance:
|
||||
* set the instance's hostname from instance metadata
|
||||
* install SSH keys from instance metadata to the cloud user account's
|
||||
`authorized_keys` file (the user must already exist)
|
||||
* save the instance user-data to a file and if it's a script, execute it at the
|
||||
end of the **default** runlevel
|
||||
* save the instance user-data to a file, and if it's a script, execute it at
|
||||
the end of the **default** runlevel
|
||||
|
||||
Optional features, which may not be universally necessary:
|
||||
* manage symlinks from NVMe block devices to `/dev/xvd` and `/dev/sd` devices
|
||||
@ -68,26 +68,26 @@ rc-update add tiny-cloud-final default
|
||||
|
||||
## Configuration
|
||||
|
||||
Tiny Cloud looks expects configuration to be found at
|
||||
[`/etc/conf.d/tiny-cloud`](etc/conf.d/tiny-cloud), which documents all
|
||||
tuneable parameters (and their defaults).
|
||||
By default, Tiny Cloud expects configuration at `/etc/conf.d/tiny-cloud`,
|
||||
although the location can be overridden by setting the `TINY_CLOUD_CONF`
|
||||
environment variable. The stock [`etc/conf.d/tiny-cloud`](
|
||||
etc/conf.d/tiny-cloud) file contains details of all tuneable settings.
|
||||
|
||||
However, because Tiny Cloud does not do auto-detection, you ***must*** set a
|
||||
value for `CLOUD` indicating which cloud provider which will be used when
|
||||
instantiating the image. Current valid values are `aws`, `azure`, `gcp`, and
|
||||
`oci`.
|
||||
*Because Tiny Cloud does not currently do auto-detection, you **MUST** set a
|
||||
configuration value for `CLOUD` indicating which cloud provider will be used.
|
||||
Current valid values are `aws`, `azure`, `gcp`, and `oci`.*
|
||||
|
||||
## Operation
|
||||
|
||||
The first time an instance boots -- either freshly instantiated from an image,
|
||||
or after installation on an existing instance -- Tiny Cloud sets up the
|
||||
or after installation on a pre-existing instance -- Tiny Cloud sets up the
|
||||
instance in three phases...
|
||||
|
||||
### Early Phase
|
||||
|
||||
The `tiny-cloud-early` init script does not depend on the cloud provider's
|
||||
Instance MetaData Service (IMDS), and does therefore does not have a dependency
|
||||
on networking. During this "early" phase, the root filesystem is expanded, and
|
||||
Instance MetaData Service (IMDS), and therefore does not have a dependency on
|
||||
networking. During this "early" phase, the root filesystem is expanded, and
|
||||
any necessary `mdev` rules for device hotplug are set up.
|
||||
|
||||
### Main Phase
|
||||
@ -99,16 +99,18 @@ data, and sets up instance's hostname and the cloud user's SSH keys before
|
||||
### Final Phase
|
||||
|
||||
`tiny-cloud-final` should be the very last init script to run in the
|
||||
**default** runlevel, and saves the instance's user data to
|
||||
`/var/lib/cloud/user-data`.
|
||||
**default** runlevel. By default, it saves the instance's user data to
|
||||
`/var/lib/cloud/user-data`, which is overrideable via the `TINY_CLOUD_VAR`
|
||||
andr `CLOUD_USERDATA` config settings.
|
||||
|
||||
If the user data is a script that starts with `#!` (aka "[shebang](
|
||||
https://en.wikipedia.org/wiki/Shebang_(Unix))"), it will be executed; its
|
||||
output (combined STDOUT and STDERR) is saved to `/var/log/cloud/user-data.log`
|
||||
and the exit code can be found in `/var/log/cloud/user-data.exit`.
|
||||
If the user data is a script starting with `#!/`, it will be executed; its
|
||||
output (combined STDOUT and STDERR) and exit code are saved to
|
||||
`/var/log/user-data.log` and `/var/log/user-data.exit`, respectively -- unless
|
||||
overriden with `TINY_CLOUD_LOGS` and `CLOUD_USERDATA` config settings.
|
||||
|
||||
If all went well, the very last thing `tiny-cloud-final` does is touch
|
||||
`/var/lib/cloud/.bootstrap-complete` into existence.
|
||||
a `.bootstrap-complete` file into existence in `/var/lib/cloud` or another
|
||||
directory specified by the `TINY_CLOUD_VAR` config setting.
|
||||
|
||||
### Further Reboots
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# tiny-cloud configuration
|
||||
# Tiny Cloud configuration
|
||||
|
||||
# REQUIRED: The instance's cloud provider (valid: aws, azure, gcp, oci)
|
||||
CLOUD=
|
||||
@ -6,5 +6,17 @@ CLOUD=
|
||||
# User account where instance SSH keys are installed
|
||||
#CLOUD_USER=alpine
|
||||
|
||||
# Number of seconds an AWS IMDS token is valid
|
||||
#IMDS_TOKEN_TTL=5
|
||||
# Filename of userdata file (in TINY_CLOUD_VAR directory)
|
||||
#CLOUD_USERDATA=user-data
|
||||
|
||||
# IMDS token validity, in seconds (AWS only)
|
||||
#IMDS_TOKEN_TTL=5
|
||||
|
||||
# Location of libraries
|
||||
#TINY_CLOUD_LIBS=/lib/tiny-cloud
|
||||
|
||||
# Location of var directory
|
||||
#TINY_CLOUD_VAR=/var/lib/cloud
|
||||
|
||||
# Location of log directory
|
||||
#TINY_CLOUD_LOGS=/var/log
|
||||
|
||||
@ -8,44 +8,18 @@ depend() {
|
||||
before sshd
|
||||
}
|
||||
|
||||
_update_hostname() {
|
||||
local fqdn=$(imds_hostname)
|
||||
local host="${fqdn%%\.*}"
|
||||
echo "$host" > /etc/hostname
|
||||
hostname -F /etc/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> /etc/hosts
|
||||
}
|
||||
|
||||
_set_ssh_keys() {
|
||||
local user="$1"
|
||||
local pwent=$(getent passwd "$user")
|
||||
local group=$(echo "$pwent" | cut -d: -f4)
|
||||
local ssh_dir="$(echo "$pwent" | cut -d: -f6)/.ssh"
|
||||
local keys_file="$ssh_dir/authorized_keys"
|
||||
|
||||
if [ ! -d "$ssh_dir" ]; then
|
||||
mkdir -p "$ssh_dir"
|
||||
chmod 700 "$ssh_dir"
|
||||
fi
|
||||
|
||||
touch "$keys_file"
|
||||
chmod 600 "$keys_file"
|
||||
chown -R "$user:$group" "$ssh_dir"
|
||||
imds_ssh_keys > "$keys_file"
|
||||
}
|
||||
|
||||
start() {
|
||||
[ -f "/var/lib/cloud/.bootstrap-complete" ] && return 0
|
||||
[ -d "/var/lib/cloud" ] || mkdir -p /var/lib/cloud
|
||||
source /lib/tiny-cloud/init-main
|
||||
|
||||
source /var/lib/tiny-cloud/imds
|
||||
CLOUD_USER="${CLOUD_USER:-alpine}"
|
||||
# TODO: background tiny-cloud network watcher?
|
||||
|
||||
ebegin "Setting Instance Hostname"; _update_hostname; eend $?
|
||||
is_bootstrapped && return 0
|
||||
|
||||
ebegin "Installing SSH Keys for $CLOUD_USER User"
|
||||
_set_ssh_keys "$CLOUD_USER"
|
||||
ebegin "Setting Instance Hostname"
|
||||
set_hostname
|
||||
eend $?
|
||||
|
||||
# TODO: background tiny-cloud-network watcher?
|
||||
ebegin "Installing SSH Keys for $CLOUD_USER User"
|
||||
set_ssh_keys "$CLOUD_USER"
|
||||
eend $?
|
||||
}
|
||||
@ -7,30 +7,14 @@ depend() {
|
||||
before mdev
|
||||
}
|
||||
|
||||
_expand_root_partition() {
|
||||
local mountpoint=$(busybox mountpoint -n / | cut -d' ' -f1)
|
||||
local volume=$(echo "$mountpoint" |
|
||||
sed -Ee "s/(nvme\d+n\d|(xv|s)d[a-z])p?\d?$/\1/"
|
||||
)
|
||||
|
||||
if [ "$mountpoint" != "$volume" ]; then
|
||||
partition=$(echo "$volume" | sed -Ee "s/.*(\d+)$/\2/")
|
||||
einfo "Expanding root partition to volume size..."
|
||||
echo ", +" | sfdisk -q --no-reread -N "$partition" "$volume"
|
||||
einfo "Updating kernel with new partition table..."
|
||||
partx -u "$volume"
|
||||
fi
|
||||
einfo "Resizing root filesystem..."
|
||||
resize2fs "$mountpoint"
|
||||
}
|
||||
|
||||
start() {
|
||||
[ -f "/var/lib/cloud/.bootstrap-complete" ] && return 0
|
||||
[ -d "/var/lib/cloud" ] || mkdir -p /var/lib/cloud
|
||||
source /lib/tiny-cloud/init-early
|
||||
|
||||
source /etc/conf.d/tiny-cloud # or use auto-sourced tiny-cloud-early?
|
||||
is_bootstrapped && return 0
|
||||
|
||||
ebegin "Expanding Root Partition"; _expand_root_partition; eend $?
|
||||
ebegin "Expanding Root Volume/Partition"
|
||||
expand_root
|
||||
eend $?
|
||||
|
||||
# TODO: _setup mdev things, if applicable
|
||||
}
|
||||
@ -8,30 +8,18 @@ depend() {
|
||||
provide cloud-final
|
||||
}
|
||||
|
||||
_save_userdata() {
|
||||
imds_userdata > "$USERDATA"
|
||||
}
|
||||
|
||||
_run_userdata() {
|
||||
local log="/var/log/user-data.log"
|
||||
local exit="/var/log/user-data.exit"
|
||||
|
||||
chmod +x "$USERDATA"
|
||||
{ "$USERDATA" 2>& 1; echo $? > "$exit"; } | tee "$log"
|
||||
|
||||
return $(cat "$exit")
|
||||
}
|
||||
|
||||
start() {
|
||||
[ -f "/var/lib/cloud/.bootstrap-complete" ] && return 0
|
||||
[ -d "/var/lib/cloud" ] || mkdir -p /var/lib/cloud
|
||||
source /lib/tiny-cloud/init-final
|
||||
|
||||
source /lib/tiny-cloud/imds
|
||||
is_bootstrapped && return 0
|
||||
|
||||
USERDATA="/var/lib/cloud/user-data"
|
||||
ebegin "Saving Instance UserData"
|
||||
save_userdata
|
||||
eend $?
|
||||
|
||||
ebegin "Saving Instance UserData"; _save_userdata; eend $?
|
||||
if head -n1 "$USERDATA" | grep -q '^#!/'; then
|
||||
ebegin "Executing UserData Script"; _run_userdata; eend $?
|
||||
if is_userdata_script; then
|
||||
ebegin "Executing UserData Script"
|
||||
run_userdata
|
||||
eend $?
|
||||
fi
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
# AWS Instance MetaData Service related variables and functions
|
||||
# AWS Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
|
||||
IMDS_HEADER="X-aws-ec2-metadata-token"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Azure metadata-related variables and functions
|
||||
# Azure Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
|
||||
IMDS_HEADER="Metadata"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Google Cloud metadata-related variables and functions
|
||||
# Google Cloud Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
|
||||
IMDS_HEADER="Metadata-Flavor"
|
||||
|
||||
@ -1,32 +1,33 @@
|
||||
# tiny-cloud Instance MetaData Service related functions and variables
|
||||
# Tiny Cloud - Instance MetaData Service functions and variables
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
CONF_DIR="/etc/conf.d"
|
||||
LIB_DIR="/lib/tiny-cloud"
|
||||
### configuration
|
||||
|
||||
### load configuration
|
||||
|
||||
[ -f "$CONF_DIR"/tiny-cloud ] && source "$CONF_DIR"/tiny-cloud
|
||||
|
||||
### configuration defaults
|
||||
|
||||
CLOUD="${CLOUD:-unknown}"
|
||||
CLOUD_LOGIN="${CLOUD_LOGIN:-alpine}"
|
||||
if [ ! -d "$LIB_DIR/$CLOUD" ]; then
|
||||
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
|
||||
exit 1
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
IMDS_HEADER=
|
||||
IMDS_QUERY=
|
||||
IMDS_URL=
|
||||
# defaults
|
||||
CLOUD="${CLOUD:-unknown}"
|
||||
|
||||
IMDS_HOSTNAME=
|
||||
IMDS_SSH_KEYS=
|
||||
IMDS_USERDATA=
|
||||
# these are always cloud-specific
|
||||
|
||||
### default/common functions
|
||||
unset \
|
||||
IMDS_HEADER \
|
||||
IMDS_QUERY \
|
||||
IMDS_URL \
|
||||
IMDS_HOSTNAME \
|
||||
IMDS_SSH_KEYS \
|
||||
IMDS_USERDATA
|
||||
|
||||
unset -f \
|
||||
_imds_token \
|
||||
_imds_header \
|
||||
2>/dev/null || true
|
||||
|
||||
# without error reporting or ending newline enforcement
|
||||
_imds() {
|
||||
wget --quiet --header "$(_imds_header)" --output-document - \
|
||||
"$IMDS_URL/$1/$IMDS_QUERY"
|
||||
@ -55,6 +56,11 @@ imds_ssh_keys() {
|
||||
imds "$IMDS_SSH_KEYS"
|
||||
}
|
||||
|
||||
# cloud-specific things (potentially overriding the above)
|
||||
### load cloud-specific things
|
||||
|
||||
[ -f "$LIB_DIR/$CLOUD/metadata" ] && source "$LIB_DIR/$CLOUD"/imds
|
||||
if [ ! -d "$TINY_CLOUD_LIBS/$CLOUD" ]; then
|
||||
echo "ERROR: Unknown Cloud '$CLOUD'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS/$CLOUD/imds"
|
||||
|
||||
15
lib/tiny-cloud/init-common
Normal file
15
lib/tiny-cloud/init-common
Normal file
@ -0,0 +1,15 @@
|
||||
# Tiny Cloud - Common Initialization
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
# set defaults
|
||||
CLOUD_USER=${CLOUD_USER:-alpine}
|
||||
CLOUD_USERDATA=${CLOUD_USERDATA:-user-data}
|
||||
TINY_CLOUD_LOGS=${TINY_CLOUD_LOGS:-/var/log}
|
||||
TINY_CLOUD_VAR=${TINY_CLOUD_VAR:-/var/lib/cloud}
|
||||
|
||||
# ensure existence of output directories
|
||||
[ ! -d "$TINY_CLOUD_VAR" ] && mkdir -p "$TINY_CLOUD_VAR"
|
||||
[ ! -d "$TINY_CLOUD_LOGS" ] && mkdir -p "$TINY_CLOUD_LOGS"
|
||||
|
||||
# is initial bootstrap already done?
|
||||
is_bootstrapped() { [ -f "$TINY_CLOUD_VAR"/.bootstrap-complete ]; }
|
||||
28
lib/tiny-cloud/init-early
Normal file
28
lib/tiny-cloud/init-early
Normal file
@ -0,0 +1,28 @@
|
||||
# Tiny Cloud - Early Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
|
||||
expand_root() {
|
||||
# explicitly use busybox, in case util-linux is also installed
|
||||
local mountpoint=$(busybox mountpoint -n / | cut -d' ' -f1)
|
||||
local volume=$(echo "$mountpoint" |
|
||||
sed -Ee "s/(nvme\d+n\d|(xv|s)d[a-z])p?\d?$/\1/"
|
||||
)
|
||||
|
||||
if [ "$mountpoint" != "$volume" ]; then
|
||||
partition=$(echo "$volume" | sed -Ee "s/.*(\d+)$/\2/")
|
||||
einfo "Expanding root partition to volume size..."
|
||||
echo ", +" | sfdisk -q --no-reread -N "$partition" "$volume"
|
||||
einfo "Updating kernel with new partition table..."
|
||||
partx -u "$volume"
|
||||
fi
|
||||
einfo "Resizing root filesystem..."
|
||||
resize2fs "$mountpoint"
|
||||
}
|
||||
30
lib/tiny-cloud/init-final
Normal file
30
lib/tiny-cloud/init-final
Normal file
@ -0,0 +1,30 @@
|
||||
# Tiny Cloud - Final Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
source "$TINY_CLOUD_LIBS"/imds
|
||||
|
||||
save_userdata() {
|
||||
imds_userdata > "$USERDATA"
|
||||
}
|
||||
|
||||
is_userdata_script() {
|
||||
head -n1 "$TINY_CLOUD_VAR/$CLOUD_USERSDATA" | grep -q '%#!/'
|
||||
}
|
||||
|
||||
run_userdata() {
|
||||
local log="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.log"
|
||||
local exit="$TINY_CLOUD_LOGS/$CLOUD_USERDATA.exit"
|
||||
local userdata="$TINY_CLOUD_VAR/$CLOUD_USERDATA"
|
||||
|
||||
chmod +x "$userdata"
|
||||
{ "$userdata" 2>& 1; echo $? > "$exit"; } | tee "$log"
|
||||
|
||||
return $(cat "$exit")
|
||||
}
|
||||
37
lib/tiny-cloud/init-main
Normal file
37
lib/tiny-cloud/init-main
Normal file
@ -0,0 +1,37 @@
|
||||
# Tiny Cloud - Main Phase Functions
|
||||
# vim:set ft=sh ts=4 noet:
|
||||
|
||||
if [ -z "$TINY_CLOUD_LIBS" ]; then
|
||||
TINY_CLOUD_CONF=${TINY_CLOUD_CONF:-/etc/conf.d/tiny-cloud}
|
||||
[ -f "$TINY_CLOUD_CONF" ] && source "$TINY_CLOUD_CONF"
|
||||
TINY_CLOUD_LIBS=${TINY_CLOUD_LIBS:-/lib/tiny-cloud}
|
||||
fi
|
||||
|
||||
source "$TINY_CLOUD_LIBS"/init-common
|
||||
source "$TINY_CLOUD_LIBS"/imds
|
||||
|
||||
set_hostname() {
|
||||
local fqdn=$(imds_hostname)
|
||||
local host="${fqdn%%\.*}"
|
||||
echo "$host" > /etc/hostname
|
||||
hostname -F /etc/hostname
|
||||
echo -e "127.0.1.1\t$fqdn $host" >> /etc/hosts
|
||||
}
|
||||
|
||||
set_ssh_keys() {
|
||||
local user="$CLOUD_USER"
|
||||
local pwent=$(getent passwd "$user")
|
||||
local group=$(echo "$pwent" | cut -d: -f4)
|
||||
local ssh_dir="$(echo "$pwent" | cut -d: -f6)/.ssh"
|
||||
local keys_file="$ssh_dir/authorized_keys"
|
||||
|
||||
if [ ! -d "$ssh_dir" ]; then
|
||||
mkdir -p "$ssh_dir"
|
||||
chmod 700 "$ssh_dir"
|
||||
fi
|
||||
|
||||
touch "$keys_file"
|
||||
chmod 600 "$keys_file"
|
||||
chown -R "$user:$group" "$ssh_dir"
|
||||
imds_ssh_keys > "$keys_file"
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
# OCI metadata-related variables and functions
|
||||
# OCI Instance MetaData Service variables and functions
|
||||
# vim:set ft=sh noet ts=4:
|
||||
|
||||
IMDS_HEADER="Authorization"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user