Compare commits

..

6 Commits

Author SHA1 Message Date
5282959b9b tweaking...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 20:13:51 +03:00
01d57aa88a added traefik iptables auto-update on boot...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 19:59:49 +03:00
685e7bfe14 added basic makefile -- still experimetal...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 19:42:59 +03:00
64347c9290 minor fix...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 19:30:09 +03:00
a084422584 more polish...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 19:27:52 +03:00
6279b1e6c2 refactoring...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2024-01-03 18:51:22 +03:00
4 changed files with 267 additions and 215 deletions

View File

@ -139,5 +139,183 @@ normpath(){
} }
#----------------------------------------------------------------------
#
# xread [-n] MSG VAR
#
xread(){
local non_empty=
if [[ $1 == '-n' ]] ; then
shift
local non_empty=1
fi
[ -z ${!2} ] \
&& eval 'read -ep "'$1'" -i "$DFL_'$2'" '${2}''
if [ -z $non_empty ] ; then
eval ''$2'=${'$2':=$DFL_'$2'}'
fi
[ $SCRIPTING ] \
&& echo "$2=${!2}"
}
#
# readVars
#
# Variables this handles:
# EMAIL
# DOMAIN
# ID
# CTHOSTNAME
# WAN_BRIDGE
# LAN_BRIDGE
# ADMIN_BRIDGE
# WAN_IP
# WAN_GATE
# LAN_IP
# LAN_GATE
# ADMIN_IP
# ADMIN_GATE
# ROOTPASS
# PCT_EXTRA
#
# Variables this sets:
# PASS
#
# Variables used:
# TMP_PASS_LEN
# ROOTPASS
#
readVars(){
xread -n "Email: " EMAIL
xread -n "Domain: " DOMAIN
xread "ID: " ID
xread "Hostname: " CTHOSTNAME
# bridge config...
xread "WAN bridge: vmbr" WAN_BRIDGE
xread "LAN bridge: vmbr" LAN_BRIDGE
xread "ADMIN bridge: vmbr" ADMIN_BRIDGE
# gateway...
# IPs can be:
# <empty>
# <IP>/<mask>
# dhcp
# Gateways can be:
# <empty>
# <IP>
xread "WAN ip: " WAN_IP
xread "WAN gateway: " WAN_GATE
xread "LAN ip: " LAN_IP
xread "LAN gateway: " LAN_GATE
xread "ADMIN ip: " ADMIN_IP
xread "ADMIN gateway: " ADMIN_GATE
# root password...
if [ -z $ROOTPASS ] ; then
read -sep "root password (Enter to skip): " PASS1
echo
if [ $PASS1 ] ; then
read -sep "retype root password: " PASS2
echo
if [[ $PASS1 != $PASS2 ]] ; then
echo "ERR: passwords do not match."
exit 1
fi
PASS=$PASS1
fi
else
PASS=$ROOTPASS
fi
# extra stuff...
xread "pct extra options: " PCT_EXTRA
}
#
# buildAssets [TEMPLATES [ASSETS]]
#
buildAssets(){
local TEMPLATE_DIR=$1
TEMPLATE_DIR=${TEMPLATE_DIR:=templates}
local ASSETS_DIR=$2
TEMPLATE_DIR=${ASSETS_DIR:=assets}
local TEMPLATES=($(find "$TEMPLATE_DIR" -type f))
for file in "${TEMPLATES[@]}" ; do
file=${file#${TEMPLATE_DIR}}
echo Generating: ${file}...
[ $DRY_RUN ] \
&& continue
# ensure the directory exists...
mkdir -p "$(dirname "${ASSETS_DIR}/${file}")"
cat "${TEMPLATE_DIR}/${file}" \
| sed \
-e 's/\${EMAIL}/'$EMAIL'/' \
-e 's/\${DOMAIN}/'$DOMAIN'/' \
-e 's/\${CTHOSTNAME}/'$CTHOSTNAME'/' \
-e 's/\${WAN_IP}/'${WAN_IP/\//\\/}'/' \
-e 's/\${WAN_GATE}/'$WAN_GATE'/' \
-e 's/\${LAN_IP}/'${LAN_IP/\//\\/}'/' \
-e 's/\${LAN_GATE}/'$LAN_GATE'/' \
-e 's/\${ADMIN_IP}/'${ADMIN_IP/\//\\/}'/' \
-e 's/\${ADMIN_GATE}/'$ADMIN_GATE'/' \
> "${ASSETS_DIR}/${file}"
done
}
#
# pctCreate ID TEMPLATE ARGS [PASS]
#
pctCreate(){
local TMP_PASS=$(cat /dev/urandom | base64 | head -c ${TMP_PASS_LEN:=32})
# NOTE: we are not setting the password here to avoid printing it to the terminal...
@ pct create $1 \
${2} \
${3} \
--password="$TMP_PASS" \
--start 1 \
|| exit 1
# set actual root password...
if [ "$4" ] ; then
echo "root:$4" \
| @ lxc-attach $1 chpasswd
fi
}
#
# pctCreate ID ARGS [PASS]
#
pctCreateAlpine(){
if [ $DRY_RUN ] ; then
local TEMPLATE=(/var/lib/vz/template/cache/alpine-3.18\*.tar.xz)
else
local TEMPLATE=($(ls /var/lib/vz/template/cache/alpine-3.18*.tar.xz))
fi
pctCreate $1 "${TEMPLATE[-1]}" "$2" "$3"
@ lxc-attach $1 apk update
@ lxc-attach $1 apk upgrade
}
#
# pctSet ID [ARGS [REBOOT]]
#
pctSet(){
[ "$2" ] \
&& @ pct set $1 \
${2}
[ "$3" ] \
&& @ pct reboot $1
}
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# vim:set ts=4 sw=4 nowrap : # vim:set ts=4 sw=4 nowrap :

22
Makefile Normal file
View File

@ -0,0 +1,22 @@
config.global: config.global.example
vim "+0r config.global.example" $<
config: config.global
gate: gate-traefik
$</make.sh
ns: ns
$</make.sh
all: config gate ns

View File

@ -1,11 +1,15 @@
#!/usr/bin/bash #!/usr/bin/bash
#---------------------------------------------------------------------- #----------------------------------------------------------------------
source ../.pct-helpers cd $(dirname $0)
PATH=$PATH:$(dirname "$(pwd)") PATH=$PATH:$(dirname "$(pwd)")
#----------------------------------------------------------------------
source ../.pct-helpers
#---------------------------------------------------------------------- #----------------------------------------------------------------------
[ -e ../config.global ] \ [ -e ../config.global ] \
@ -17,88 +21,31 @@ PATH=$PATH:$(dirname "$(pwd)")
#---------------------------------------------------------------------- #----------------------------------------------------------------------
TEMPLATE_DIR=${TEMPLATE_DIR:=templates} DFL_ID=${DFL_ID:=101}
ASSETS_DIR=${ASSETS_DIR:=assets}
# ROOTPASS=
TMP_PASS_LEN=${TMP_PASS_LEN:=32}
DFL_EMAIL=${DFL_EMAIL:=user@example.com}
DFL_DOMAIN=${DFL_DOMAIN:=example.com}
DFL_ID=${DFL_ID:=500}
DFL_CTHOSTNAME=${DFL_CTHOSTNAME:=gate} DFL_CTHOSTNAME=${DFL_CTHOSTNAME:=gate}
DFL_WAN_IP=${DFL_WAN_IP:=192.168.1.101/24} DFL_WAN_IP=${DFL_WAN_IP:=192.168.1.101/24}
DFL_WAN_GATE=${DFL_WAN_GATE:=192.168.1.252} DFL_WAN_GATE=${DFL_WAN_GATE:=192.168.1.252}
DFL_WAN_BRIDGE=${DFL_WAN_BRIDGE:=2} DFL_ADMIN_IP=${DFL_ADMIN_IP:=10.0.0.2/24}
DFL_LAN_BRIDGE=${DFL_LAN_BRIDGE:=0} ADMIN_GATE=-
DFL_ADMIN_BRIDGE=${DFL_ADMIN_BRIDGE:=1} DFL_LAN_IP=${DFL_LAN_IP:=10.1.1.2/24}
LAN_GATE=-
DFL_PCT_EXTRA=${DFL_PCT_EXTRA:=}
REBOOT=${REBOOT:=1} REBOOT=${REBOOT:=1}
readVars
#----------------------------------------------------------------------
[ -z $EMAIL ] \
&& read -ep "Email: " -i "$DFL_EMAIL" EMAIL
EMAIL=${EMAIL:=$DFL_EMAIL}
[ -z $DOMAIN ] \
&& read -ep "Domain: " -i "$DFL_DOMAIN" DOMAIN
DOMAIN=${DOMAIN:=$DFL_DOMAIN}
[ -z $ID ] \
&& read -ep "ID: " -i "$DFL_ID" ID
[ -z $CTHOSTNAME ] \
&& read -ep "Hostname: " -i "$DFL_CTHOSTNAME" CTHOSTNAME
# bridge config...
[ -z $WAN_BRIDGE ] \
&& read -ep "WAN bridge: vmbr" -i "$DFL_WAN_BRIDGE" WAN_BRIDGE
[ -z $LAN_BRIDGE ] \
&& read -ep "LAN bridge: vmbr" -i "$DFL_LAN_BRIDGE" LAN_BRIDGE
[ -z $ADMIN_BRIDGE ] \
&& read -ep "ADMIN bridge: vmbr" -i "$DFL_ADMIN_BRIDGE" ADMIN_BRIDGE
# wan...
[ -z $WAN_IP ] \
&& read -ep "WAN ip: " -i "$DFL_WAN_IP" WAN_IP
[ -z $WAN_GATE ] \
&& read -ep "WAN gateway: " -i "$DFL_WAN_GATE" WAN_GATE
# root password...
TMP_PASS=$(cat /dev/urandom | base64 | head -c ${TMP_PASS_LEN:=32})
if [ -z $ROOTPASS ] ; then
read -sep "root password (Enter to skip): " PASS1
echo
if [ $PASS1 ] ; then
read -sep "retype root password: " PASS2
echo
if [[ $PASS1 != $PASS2 ]] ; then
echo "ERR: passwords do not match."
exit 1
fi
PASS=$PASS1
fi
else
PASS=$ROOTPASS
fi
# extra stuff...
[ -z $PCT_EXTRA ] \
&& read -ep "pct extra options: " -i "$DFL_PCT_EXTRA" PCT_EXTRA
#---------------------------------------------------------------------- #----------------------------------------------------------------------
TEMPLATE=($(ls /var/lib/vz/template/cache/alpine-3.18*.tar.xz))
# XXX should we set the initial ip as 10.x.x.2/23, dhcp or empty???
# --net0 name=lan,bridge=vmbr${LAN_BRIDGE},firewall=1,ip=10.1.1.2/24,type=veth \
# --net1 name=admin,bridge=vmbr${ADMIN_BRIDGE},firewall=1,ip=10.0.0.2/24,type=veth \
OPTS_STAGE_1="\ OPTS_STAGE_1="\
--hostname $CTHOSTNAME \ --hostname $CTHOSTNAME \
--memory 128 \ --memory 128 \
--swap 128 \ --swap 128 \
--net0 name=wan,bridge=vmbr${WAN_BRIDGE},firewall=1${WAN_GATE:+,gw=${WAN_GATE}}${WAN_IP:+,ip=${WAN_IP}},type=veth \ --net0 name=wan,bridge=vmbr${WAN_BRIDGE},firewall=1${WAN_GATE:+,gw=${WAN_GATE}}${WAN_IP:+,ip=${WAN_IP}},type=veth \
--net1 name=admin,bridge=vmbr${ADMIN_BRIDGE},firewall=1,ip=10.0.0.2/24,type=veth \ --net1 name=admin,bridge=vmbr${ADMIN_BRIDGE},firewall=1${ADMIN_IP:+,ip=${ADMIN_IP}},type=veth \
--net2 name=lan,bridge=vmbr${LAN_BRIDGE},firewall=1,ip=10.1.1.2/24,type=veth \ --net2 name=lan,bridge=vmbr${LAN_BRIDGE},firewall=1${LAN_IP:+,ip=${LAN_IP}},type=veth \
--storage local-lvm \ --storage local-lvm \
--rootfs local-lvm:0.5 \ --rootfs local-lvm:0.5 \
--unprivileged 1 \ --unprivileged 1 \
@ -113,70 +60,36 @@ OPTS_STAGE_2="\
#---------------------------------------------------------------------- #----------------------------------------------------------------------
echo Building config... echo "# Building config..."
TEMPLATES=($(find "$TEMPLATE_DIR" -type f)) buildAssets "$TEMPLATE_DIR" "$ASSETS_DIR"
for file in "${TEMPLATES[@]}" ; do
file=${file#${TEMPLATE_DIR}}
echo Generating: ${file}...
# ensure the directory exists...
mkdir -p "$(dirname "${ASSETS_DIR}/${file}")"
cat "${TEMPLATE_DIR}/${file}" \
| sed \
-e 's/\${EMAIL}/'$EMAIL'/' \
-e 's/\${DOMAIN}/'$DOMAIN'/' \
-e 's/\${CTHOSTNAME}/'$CTHOSTNAME'/' \
-e 's/\${WAN_IP}/'${WAN_IP/\//\\/}'/' \
-e 's/\${WAN_GATE}/'$WAN_GATE'/' \
> "${ASSETS_DIR}/${file}"
done
echo "# Creating CT..."
pctCreateAlpine $ID "${OPTS_STAGE_1}" "$PASS"
#---------------------------------------------------------------------- echo "# Installing dependencies..."
echo Creating CT...
# NOTE: we are not setting the password here to avoid printing it to the terminal...
@ pct create $ID \
${TEMPLATE[-1]} \
${OPTS_STAGE_1} \
--password="$TMP_PASS" \
--start 1 \
|| exit 1
if [ $PASS ] ; then
echo Setting root password...
echo "root:$PASS" \
| @ lxc-attach $ID chpasswd
fi
echo Updating container...
@ lxc-attach $ID apk update
@ lxc-attach $ID apk upgrade
echo Installing dependencies...
@ lxc-attach $ID apk add bash bridge iptables traefik @ lxc-attach $ID apk add bash bridge iptables traefik
echo Copying assets... echo "# Copying assets..."
@ pct-push-r $ID ./assets / @ pct-push-r $ID ./assets /
echo Setup: traefik... echo "# Setup: traefik..."
@ lxc-attach $ID rc-update add traefik @ lxc-attach $ID rc-update add traefik
@ lxc-attach $ID rc-service traefik start @ lxc-attach $ID rc-service traefik start
echo Setup: iptables... echo "# Setup: iptables..."
@ lxc-attach $ID rc-update add iptables @ lxc-attach $ID rc-update add iptables
@ lxc-attach $ID bash /root/routing.sh @ lxc-attach $ID bash /root/routing.sh
@ lxc-attach $ID rc-service iptables save @ lxc-attach $ID rc-service iptables save
@ lxc-attach $ID rc-service iptables start @ lxc-attach $ID rc-service iptables start
echo "Post config..." echo "# Setup: iptables update script..."
[ "$OPTS_STAGE_2" ] \ @ lxc-attach $ID rc-update add local
&& @ pct set $ID \ @ lxc-attach $ID ln -s /root/routing.sh /etc/local.d/iptables-update.start
${OPTS_STAGE_2}
[ "$REBOOT" ] \ echo "# Post config..."
&& @ pct reboot $ID pctSet $ID "${OPTS_STAGE_2}" $REBOOT
echo Done. echo "# Done."

View File

@ -1,6 +1,12 @@
#!/usr/bin/bash #!/usr/bin/bash
#---------------------------------------------------------------------- #----------------------------------------------------------------------
cd $(dirname $0)
PATH=$PATH:$(dirname "$(pwd)")
#----------------------------------------------------------------------
source ../.pct-helpers source ../.pct-helpers
@ -15,130 +21,63 @@ source ../.pct-helpers
#---------------------------------------------------------------------- #----------------------------------------------------------------------
UPDATE_ON_LAN=1
TIMEOUT=5
TMP_PASS_LEN=32
TEMPLATE_DIR=templates
ASSETS_DIR=assets
# EMAIL=
# DOMAIN=
# ID=
# CTHOSTNAME=
# WAN_IP=
# WAN_GATE=
# ROOTPASS=
DFL_EMAIL=user@example.com
DFL_DOMAIN=example.com
DFL_ID=100 DFL_ID=100
DFL_CTHOSTNAME=ns DFL_CTHOSTNAME=ns
DFL_WAN_IP=192.168.1.101/24
DFL_WAN_GATE=192.168.1.252
TMP_PASS=$(cat /dev/urandom | base64 | head -c ${TMP_PASS_LEN:=32}) WAN_IP=-
WAN_GATE=-
DFL_ADMIN_IP=${DFL_ADMIN_IP:=10.0.0.1/24}
ADMIN_GATE=-
DFL_LAN_IP=${DFL_LAN_IP:=10.1.1.1/24}
DFL_LAN_GATE=${DFL_LAN_IP:=10.1.1.2/24}
REBOOT=${REBOOT:=1}
readVars
#---------------------------------------------------------------------- #----------------------------------------------------------------------
[ -z $EMAIL ] \ OPTS_STAGE_1="\
&& read -ep "Email: " -i "$DFL_EMAIL" EMAIL
EMAIL=${EMAIL:=$DFL_EMAIL}
[ -z $DOMAIN ] \
&& read -ep "Domain: " -i "$DFL_DOMAIN" DOMAIN
DOMAIN=${DOMAIN:=$DFL_DOMAIN}
[ -z $ID ] \
&& read -ep "ID: " -i "$DFL_ID" ID
[ -z $CTHOSTNAME ] \
&& read -ep "Hostname: " -i "$DFL_CTHOSTNAME" CTHOSTNAME
[ -z $WAN_IP ] \
&& read -ep "WAN ip (stub): " -i "$DFL_WAN_IP" WAN_IP
[ -z $WAN_GATE ] \
&& read -ep "WAN gateway (stub): " -i "$DFL_WAN_GATE" WAN_GATE
if [ -z $ROOTPASS ] ; then
read -sep "root password (Enter to skip): " PASS1
echo
if [ $PASS1 ] ; then
read -sep "retype root password: " PASS2
echo
if [[ $PASS1 != $PASS2 ]] ; then
echo "ERR: passwords do not match."
exit 1
fi
PASS=$PASS1
fi
else
PASS=$ROOTPASS
fi
#----------------------------------------------------------------------
echo Building config...
TEMPLATES=($(find "$TEMPLATE_DIR" -type f))
for file in "${TEMPLATES[@]}" ; do
file=${file#${TEMPLATE_DIR}}
echo Generating: ${file}...
cat "${TEMPLATE_DIR}/${file}" \
| sed \
-e 's/\${EMAIL}/'$EMAIL'/' \
-e 's/\${DOMAIN}/'$DOMAIN'/' \
-e 's/\${CTHOSTNAME}/'$CTHOSTNAME'/' \
-e 's/\${WAN_IP}/'${WAN_IP/\//\\/}'/' \
-e 's/\${WAN_GATE}/'$WAN_GATE'/' \
> "${ASSETS_DIR}/${file}"
done
#----------------------------------------------------------------------
echo Creating CT...
TEMPLATE=($(ls /var/lib/vz/template/cache/alpine-3.18*.tar.xz))
# XXX option to configure bridges...
# NOTE: we are not setting the password here to avoid printing it to the terminal...
@ pct create $ID \
${TEMPLATE[-1]} \
--hostname $CTHOSTNAME \ --hostname $CTHOSTNAME \
--memory 128 \ --memory 128 \
--swap 128 \ --swap 128 \
--net0 name=lan,bridge=vmbr0,firewall=1,ip=dhcp,type=veth \ --net0 name=lan,bridge=vmbr0,firewall=1${LAN_GATE:+,gw=$LAN_GATE}${LAN_IP:+,ip=$LAN_IP},type=veth \
--net1 name=admin,bridge=vmbr1,firewall=1,type=veth \ --net1 name=admin,bridge=vmbr1,firewall=1${ADMIN_IP:+,ip=$ADMIN_IP},type=veth \
--net2 name=wan,bridge=vmbr2,firewall=1${WAN_GATE:+,gw=${WAN_GATE}}${WAN_IP:+,ip=${WAN_IP}},type=veth \
--storage local-lvm \ --storage local-lvm \
--rootfs local-lvm:0.5 \ --rootfs local-lvm:0.5 \
--unprivileged 1 \ --unprivileged 1 \
--password="$TMP_PASS" \ ${PCT_EXTRA} \
--start 1 \ "
|| exit 1
# XXX ifdown admin lan interfaces fro bootstrap... OPTS_STAGE_2="\
--startup order=90,up=10 \
--onboot 1 \
"
echo Setting root password...
if [ $PASS ] ; then
echo "root:$PASS" \
| @ lxc-attach $ID chpasswd
fi
echo Updating container... #----------------------------------------------------------------------
@ lxc-attach $ID apk update
@ lxc-attach $ID apk upgrade
echo Installing dependencies... echo "# Building config..."
buildAssets "$TEMPLATE_DIR" "$ASSETS_DIR"
echo "# Creating CT..."
pctCreateAlpine $ID "${OPTS_STAGE_1}" "$PASS"
echo "# Installing dependencies..."
@ lxc-attach $ID apk add bash dnsmasq @ lxc-attach $ID apk add bash dnsmasq
echo Copying assets... echo "# Copying assets..."
@ pct-push-r $ID ./assets / @ pct-push-r $ID ./assets /
echo Setup: dnsmasq... echo "# Setup: dnsmasq..."
@ lxc-attach $ID rc-update add dnsmasq @ lxc-attach $ID rc-update add dnsmasq
@ lxc-attach $ID rc-service dnsmasq start @ lxc-attach $ID rc-service dnsmasq start
echo "# Post config..."
pctSet $ID "${OPTS_STAGE_2}" $REBOOT
echo "# Done."
echo Done.
#---------------------------------------------------------------------- #----------------------------------------------------------------------