arnaucube
arnaucube/configsPublic Self-hosted repository
configs/bin/box
bin/boxRaw
  1#!/usr/bin/env bash
  2#
  3# Launch LXC containers to work in there.
  4
  5# Needs: sudo snap install lxd
  6# initialize lxd: sudo lxd init --auto
  7
  8# NOTE: in case the container does not have internet:
  9# 1)
 10# sudo sysctl -w net.ipv4.ip_forward=1
 11#
 12# 2)
 13# # Force iptables to ACCEPT traffic from the LXD bridge 
 14# # Docker sets the global policy to DROP; we must explicitly allow lxdbr0
 15# sudo iptables -I FORWARD -i lxdbr0 -j ACCEPT
 16# sudo iptables -I FORWARD -o lxdbr0 -j ACCEPT
 17#
 18# 3)
 19# # allow LXD bridge through firewall:
 20# sudo ufw allow in on lxdbr0
 21# sudo ufw route allow in on lxdbr0
 22# sudo ufw route allow out on lxdbr0
 23#
 24# Note: when turning off and on the host machine, might need to set the iptables
 25# again: step 3).
 26
 27
 28set -e
 29
 30if [ -z "$1" ]; then
 31    echo "Error: no container name provided."
 32    echo "Usage: ./box.sh <container_name>"
 33    exit 1
 34fi
 35
 36CONTAINER_NAME="$1"
 37HOST_SHARE_DIR="/home/$USER/container_data/$CONTAINER_NAME"
 38CONTAINER_SHARE_DIR="/mnt/shared"
 39IMAGE="ubuntu:22.04"
 40
 41PROFILE_NAME=${2:-"default"} # if $2 is empty, use "default"
 42PROFILES_FILE="$HOME/bin/box_profiles.sh"
 43
 44# EXPOSE_PORTS="7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010"
 45EXPOSE_PORTS=""
 46
 47
 48if [ -z "$CONTAINER_NAME" ]; then
 49    echo "error: no container name provided."
 50    echo "Usage: ./box.sh <container_name> [profile_name]"
 51    exit 1
 52fi
 53
 54if [ ! -f "$PROFILES_FILE" ]; then
 55    echo "error: $PROFILES_FILE not found."
 56    exit 1
 57fi
 58
 59source "$PROFILES_FILE"
 60
 61if ! declare -f "profile_$PROFILE_NAME" > /dev/null; then
 62    echo "error: profile '$PROFILE_NAME' not found in $PROFILES_FILE."
 63    echo "Available profiles are:"
 64    grep -oP '(?<=profile_).*(?=\(\))' "$PROFILES_FILE"
 65    exit 1
 66fi
 67
 68echo "profile selected: [$PROFILE_NAME]"
 69echo "software to install: $SOFTWARE_LIST"
 70
 71mkdir -p "$HOST_SHARE_DIR"
 72
 73echo "launch LXD container: $CONTAINER_NAME..."
 74# security.nesting=true allows Docker to run inside this container
 75lxc launch "$IMAGE" "$CONTAINER_NAME" -c security.nesting=true
 76
 77sleep 2 # wait for filesystem
 78
 79echo "set dns"
 80HOST_UID=$(id -u)
 81# map Host User to Container Root
 82lxc config set "$CONTAINER_NAME" raw.idmap "both $HOST_UID 0"
 83# set dns to bypass host dns
 84lxc exec "$CONTAINER_NAME" -- rm -f /etc/resolv.conf
 85lxc exec "$CONTAINER_NAME" -- bash -c "echo 'nameserver 8.8.8.8' | tee /etc/resolv.conf"
 86
 87echo "restart container, sleep 2s"
 88lxc restart "$CONTAINER_NAME"
 89sleep 2
 90
 91echo "configure shared directory (between container & host)"
 92lxc config device add "$CONTAINER_NAME" project_storage disk \
 93    source="$HOST_SHARE_DIR" \
 94    path="$CONTAINER_SHARE_DIR"
 95
 96echo "configure port forwarding"
 97for PORT in $EXPOSE_PORTS; do
 98    lxc config device add "$CONTAINER_NAME" "proxy${PORT}" proxy \
 99        listen=tcp:0.0.0.0:${PORT} \
100        connect=tcp:127.0.0.1:${PORT}
101done
102
103echo "check internet"
104if ! lxc exec "$CONTAINER_NAME" -- ping -c 1 8.8.8.8 > /dev/null; then
105    echo "error: no internet access inside the container."
106    echo "note: check out the 'NOTE' at the top of the script for instructions."
107    # remove container, since failed the launch
108    lxc stop $CONTAINER_NAME
109    lxc delete $CONTAINER_NAME
110    exit 1
111fi
112
113echo "apt update & apt install"
114lxc exec "$CONTAINER_NAME" -- bash -c "
115    $(cat "$PROFILES_FILE")
116
117    export DEBIAN_FRONTEND=noninteractive
118    export NEEDRESTART_MODE=a # 'a' for automatic restart
119
120    apt-get update && apt-get upgrade -y
121
122    if declare -f profile_$PROFILE_NAME > /dev/null; then
123        profile_$PROFILE_NAME
124    else
125        echo 'error: profile function $PROFILE_NAME not found.'
126        exit 1
127    fi
128"
129
130echo "setup complete"
131echo "----------------------------------------------------"
132echo "Shared Directory (Host): $HOST_SHARE_DIR"
133echo "Shared Directory (Container): $CONTAINER_SHARE_DIR"
134echo "----------------------------------------------------"
135echo "To enter the container, run: lxc shell $CONTAINER_NAME"
136echo "To stop the container, run: lxc stop $CONTAINER_NAME"
137echo "To remove the container, run: lxc delete $CONTAINER_NAME"