├── .gitignore ├── templates └── hostname.tpl ├── .gitattributes ├── files └── etc │ ├── inittab │ ├── board.d │ ├── 90-set_hostname │ └── 99-default_network │ └── init.d │ └── container_init ├── LICENSE ├── README └── scripts └── build_rootfs_cs.sh /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /templates/hostname.tpl: -------------------------------------------------------------------------------- 1 | {{ container.name }} 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /files/etc/inittab: -------------------------------------------------------------------------------- 1 | ::sysinit:/etc/init.d/rcS S boot 2 | ::shutdown:/etc/init.d/rcS K shutdown 3 | console::askfirst:/usr/libexec/login.sh 4 | -------------------------------------------------------------------------------- /files/etc/board.d/90-set_hostname: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | . /lib/functions/uci-defaults.sh 5 | 6 | board_config_update 7 | 8 | json_is_a system object && exit 0 9 | 10 | ucidef_set_hostname "$(uname -n)" 11 | 12 | board_config_flush 13 | 14 | exit 0 15 | -------------------------------------------------------------------------------- /files/etc/board.d/99-default_network: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) 2013-2015 OpenWrt.org 4 | # 5 | 6 | . /lib/functions/uci-defaults.sh 7 | 8 | board_config_update 9 | 10 | json_is_a network object && exit 0 11 | 12 | ucidef_set_interface_lan 'eth0' dhcp 13 | [ -d /sys/class/net/eth1 ] && ucidef_set_interface_wan 'eth1' 14 | 15 | board_config_flush 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /files/etc/init.d/container_init: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | # Copyright (C) 2018 Mikael Magnusson 3 | 4 | START=15 5 | 6 | boot() { 7 | # Only execute for lxc containers 8 | if [ "$container" != "lxc" ]; then 9 | exit 0 10 | fi 11 | local has_kmod="$(grep "/lib/modules/[0-9].*" /usr/lib/opkg/info/kernel.list /lib/apk/packages/kernel.list 2>/dev/null | head -1)" 12 | if [ ! -e /lib/modules/"$(uname -r)" ] && [ -n "$has_kmod" ]; then 13 | local modulesdir="$(basename "$(dirname "$has_kmod")")" 14 | ln -s "$modulesdir" /lib/modules/"$(uname -r)" 15 | fi 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mikael Magnusson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | lxd-openwrt-simplified 2 | =========== 3 | 4 | Scripts for building LXD/LXC images from OpenWrt rootfs tarballs. 5 | 6 | This is a simplified version of https://github.com/mikma/lxd-openwrt. 7 | 8 | This version assumes the user has already got an OpenWrt 22.03 or later rootfs tarball containing ALL essential packages, e.g. by buildroot or by image builder. 9 | 10 | What it will do: 11 | 12 | 1. unpack the tarball provided by the user. 13 | 14 | 2. build metadata and inject container-specific files/settings. 15 | 16 | 3. repack the tarball according to lxc/lxd requirements. 17 | 18 | Requirements 19 | ------------ 20 | 21 | It's recommended you use Debian or Ubuntu on the build system. 22 | * fakeroot is needed. Or user can config the script to use sudo. 23 | 24 | Configuration 25 | ------------- 26 | 27 | Refer to the top of build_cust.sh. 28 | And users may have to monitor the entropy available, as this script will disable the urngd service of the OpenWrt in favor of EGD on host, with the assumption that the OpenWrt instance shares entropy with the host. 29 | 30 | Usage 31 | ----- 32 | 33 | ./build_cust.sh 34 | 35 | Example 36 | ------- 37 | 38 | ./build_cust.sh openwrt-snapshot-r13592-x86-64-generic-rootfs.tar.gz plain 39 | 40 | You may be also interested in my wrapper scripts for running OpenWrt as lxc containers in Proxmox VE: https://github.com/DazzyWalkman/oplxc4pve 41 | -------------------------------------------------------------------------------- /scripts/build_rootfs_cs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | usage() { 4 | echo "Usage: $0 [-d|--disable-services ] [-o|--output ][-f|--files ] [-m|--metadata ] " 5 | exit 1 6 | } 7 | dst_file=/dev/stdout 8 | files= 9 | services= 10 | metadata= 11 | metadata_dir= 12 | temp=$(getopt -o "d:o:f:m:" -l "disable-services:,output:,files:,metadata:,help" -- "$@") 13 | eval set -- "$temp" 14 | while true; do 15 | case "$1" in 16 | -d | --disable-services) 17 | services="$2" 18 | shift 2 19 | ;; 20 | -o | --output) 21 | dst_file="$2" 22 | shift 2 23 | ;; 24 | -f | --files) 25 | files="$2" 26 | shift 2 27 | ;; 28 | -m | --metadata) 29 | metadata=$(basename "$2") 30 | metadata_dir=$(dirname "$2") 31 | shift 2 32 | ;; 33 | --help) 34 | usage 35 | ;; 36 | --) 37 | shift 38 | break 39 | ;; 40 | esac 41 | done 42 | if [ $# -ne 1 ]; then 43 | usage 44 | fi 45 | src_tar=$1 46 | dir=$(mktemp -d) 47 | if [ ! -d "$dir" ]; then 48 | echo "Failed to make temp dir. Abort." 49 | exit 1 50 | fi 51 | files_dir=files/ 52 | instroot="$dir"/rootfs 53 | unpack() { 54 | mkdir -p "$instroot" 55 | (cd "$instroot" && tar -xz) <"$src_tar" 56 | } 57 | pack() { 58 | echo Pack rootfs 59 | if [ -n "$metadata" ]; then 60 | local TARGET_DIR="$dir" 61 | else 62 | local TARGET_DIR="$dir"/rootfs 63 | fi 64 | tar -cp --sort=name -C "$TARGET_DIR" . | gzip -9n >"$dst_file" 65 | } 66 | disable_root_and_jail() { 67 | sed -i -e 's/^root::/root:*:/' "$instroot"/etc/shadow 68 | #FIXME 69 | #Disable process isolation for dnsmasq 70 | if [ -x "$instroot"/etc/init.d/dnsmasq ]; then 71 | sed -i -e '/procd_add_jail/s/^/#/' "$instroot"/etc/init.d/dnsmasq 72 | fi 73 | } 74 | add_file() { 75 | file=$1 76 | src_dir=$2 77 | dst_dir=$3 78 | src=$src_dir/$file 79 | dst=$dst_dir/$file 80 | if [ -d "$src" ]; then 81 | if [ ! -d "$dst" ]; then 82 | mkdir -p "$dst" 83 | fi 84 | elif [ -f "$src" ]; then 85 | cp "$src" "$dst" 86 | foo=$(dirname "$file") 87 | if [ "$foo" = "./etc/init.d" ]; then 88 | echo Enabling "$file" 89 | set +e 90 | env IPKG_INSTROOT="$instroot" sh "$instroot"/etc/rc.common "$dst" enable 91 | set -e 92 | fi 93 | fi 94 | } 95 | add_files() { 96 | src_dir=$1 97 | dst_dir=$2 98 | for f in $(cd "$src_dir" && find .); do 99 | add_file "$f" "$src_dir" "$dst_dir" 100 | done 101 | } 102 | disable_services() { 103 | local services="$1" 104 | for service in $services; do 105 | local init_script="$instroot"/etc/init.d/"$service" 106 | if [ -x "$init_script" ]; then 107 | echo Disabling "$service" 108 | env IPKG_INSTROOT="$instroot" sh "$instroot"/etc/rc.common "$init_script" disable 109 | else 110 | echo "$service" not found. Skip. 111 | fi 112 | done 113 | } 114 | clean_up() { 115 | rm -rf "$dir" 116 | } 117 | unpack 118 | disable_root_and_jail 119 | if [ -n "$metadata" ]; then 120 | add_file "$metadata" "$metadata_dir" "$dir" 121 | fi 122 | add_files templates/ "$dir"/templates/ 123 | disable_services "$services" 124 | add_files $files_dir "$instroot" 125 | if [ -n "$files" ]; then 126 | add_files "$files" "$instroot" 127 | fi 128 | pack 129 | clean_up 130 | --------------------------------------------------------------------------------