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"