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) (at the host machine)
 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 2).
 26
 27# Incus version:
 28#
 29# sudo incus admin init
 30#
 31# then download the ubuntu image:
 32# sudo incus launch images:ubuntu/24.04 test
 33#
 34# - create a managed network bridge:
 35# incus network create incusbr0 ipv4.address=auto ipv4.nat=true ipv6.address=none
 36# incus profile device set default eth0 network incusbr0
 37#
 38#
 39
 40set -e
 41
 42if [ -z "$1" ]; then
 43    echo "Error: no container name provided."
 44    echo "Usage: box <container_name> <profile_name(optional)>"
 45    exit 1
 46fi
 47
 48# Choose which container manager to use:
 49#MNGR="lxc"
 50MNGR="sudo incus"
 51
 52CONTAINER_NAME="$1"
 53HOST_SHARE_DIR="/home/$USER/container_data/$CONTAINER_NAME"
 54CONTAINER_SHARE_DIR="/mnt/shared"
 55IMAGE="images:ubuntu/24.04"
 56
 57PROFILE_NAME=${2:-"default"} # if $2 is empty, use "default"
 58PROFILES_FILE="$HOME/bin/box_profiles.sh"
 59
 60# EXPOSE_PORTS="7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010"
 61EXPOSE_PORTS=""
 62
 63
 64if [ -z "$CONTAINER_NAME" ]; then
 65    echo "error: no container name provided."
 66    echo "Usage: ./box.sh <container_name> [profile_name]"
 67    exit 1
 68fi
 69
 70if [ ! -f "$PROFILES_FILE" ]; then
 71    echo "error: $PROFILES_FILE not found."
 72    exit 1
 73fi
 74
 75source "$PROFILES_FILE"
 76
 77if ! declare -f "profile_$PROFILE_NAME" > /dev/null; then
 78    echo "error: profile '$PROFILE_NAME' not found in $PROFILES_FILE."
 79    echo "Available profiles are:"
 80    grep -oP '(?<=profile_).*(?=\(\))' "$PROFILES_FILE"
 81    exit 1
 82fi
 83
 84echo "profile selected: [$PROFILE_NAME]"
 85# echo "software to install: $SOFTWARE_LIST"
 86
 87mkdir -p "$HOST_SHARE_DIR"
 88
 89echo "launch LXD container: $CONTAINER_NAME..."
 90# security.nesting=true allows Docker to run inside this container
 91$MNGR launch "$IMAGE" "$CONTAINER_NAME" -c security.nesting=true
 92# $MNGR launch "$IMAGE" "$CONTAINER_NAME" -c security.nesting=true
 93
 94sleep 2 # wait for filesystem
 95
 96echo "set dns"
 97HOST_UID=$(id -u)
 98# map Host User to Container Root
 99# $MNGR config set "$CONTAINER_NAME" raw.idmap "both $HOST_UID 0"
100# set dns to bypass host dns
101#$MNGR exec "$CONTAINER_NAME" -- rm -f /etc/resolv.conf
102#$MNGR exec "$CONTAINER_NAME" -- bash -c "echo 'nameserver 8.8.8.8' | tee /etc/resolv.conf"
103
104echo "restart container"
105$MNGR restart "$CONTAINER_NAME"
106$MNGR exec "$CONTAINER_NAME" -- true
107
108echo "configure shared directory (between container & host)"
109$MNGR config device add "$CONTAINER_NAME" project_storage disk \
110    source="$HOST_SHARE_DIR" \
111    path="$CONTAINER_SHARE_DIR"
112
113echo "configure port forwarding"
114for PORT in $EXPOSE_PORTS; do
115    $MNGR config device add "$CONTAINER_NAME" "proxy${PORT}" proxy \
116        listen=tcp:0.0.0.0:${PORT} \
117        connect=tcp:127.0.0.1:${PORT}
118done
119
120
121$MNGR config device set $CONTAINER_NAME project_storage shift true
122
123echo "check internet"
124if ! $MNGR exec "$CONTAINER_NAME" -- ping -c 1 8.8.8.8 > /dev/null; then
125    echo "error: no internet access inside the container."
126    echo "note: check out the 'NOTE' at the top of the script for instructions."
127    # remove container, since failed the launch
128    $MNGR stop $CONTAINER_NAME
129    $MNGR delete $CONTAINER_NAME
130    exit 1
131fi
132
133echo "apt update & apt install"
134$MNGR exec "$CONTAINER_NAME" -- bash -c "
135    $(cat "$PROFILES_FILE")
136
137    export DEBIAN_FRONTEND=noninteractive
138    export NEEDRESTART_MODE=a # 'a' for automatic restart
139
140    apt-get update && apt-get upgrade -y
141
142    if declare -f profile_$PROFILE_NAME > /dev/null; then
143        profile_$PROFILE_NAME
144    else
145        echo 'error: profile function $PROFILE_NAME not found.'
146        exit 1
147    fi
148"
149
150echo "setup complete"
151echo "----------------------------------------------------"
152echo "Shared Directory (Host): $HOST_SHARE_DIR"
153echo "Shared Directory (Container): $CONTAINER_SHARE_DIR"
154echo "----------------------------------------------------"
155echo "To enter the container, run: $MNGR shell $CONTAINER_NAME"
156echo "To stop the container, run: $MNGR stop $CONTAINER_NAME"
157echo "To remove the container, run: $MNGR delete $CONTAINER_NAME"