├── NEWS ├── README ├── AUTHORS ├── config ├── ubuntu.lucid.conf.in ├── alpine.userns.conf.in ├── centos.userns.conf.in ├── debian.userns.conf.in ├── devuan.userns.conf.in ├── fedora.userns.conf.in ├── gentoo.userns.conf.in ├── kali.userns.conf.in ├── oracle.userns.conf.in ├── plamo.userns.conf.in ├── sabayon.userns.conf.in ├── archlinux.userns.conf.in ├── opensuse.userns.conf.in ├── slackware.userns.conf.in ├── sparclinux.userns.conf.in ├── ubuntu-cloud.lucid.conf.in ├── ubuntu-cloud.userns.conf.in ├── ubuntu-cloud.common.conf.in ├── plamo.common.conf.in ├── voidlinux.userns.conf.in ├── ubuntu.userns.conf.in ├── alpine.common.conf.in ├── gentoo.common.conf.in ├── centos.common.conf.in ├── oracle.common.conf.in ├── sparclinux.common.conf.in ├── kali.common.conf.in ├── Makefile.am ├── debian.common.conf.in ├── devuan.common.conf.in ├── fedora.common.conf.in ├── opensuse.common.conf.in ├── archlinux.common.conf.in ├── voidlinux.common.conf.in ├── openwrt.common.conf.in ├── ubuntu.common.conf.in ├── slackware.common.conf.in ├── sabayon.common.conf.in ├── gentoo.moresecure.conf.in └── acinclude.m4 ├── Makefile.am ├── templates ├── Makefile.am ├── lxc-voidlinux.in ├── lxc-sshd.in ├── lxc-cirros.in ├── lxc-archlinux.in ├── lxc-ubuntu-cloud.in ├── lxc-openmandriva.in ├── lxc-pld.in ├── lxc-plamo.in ├── lxc-altlinux.in ├── lxc-sabayon.in └── lxc-alpine.in ├── MAINTAINERS ├── .github └── workflows │ └── commits.yml ├── autogen.sh ├── CONTRIBUTING ├── configure.ac └── INSTALL /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | IBM Corporation. 2 | -------------------------------------------------------------------------------- /config/ubuntu.lucid.conf.in: -------------------------------------------------------------------------------- 1 | # Ubuntu 10.04 LTS doesn't have /dev/lxc/ 2 | lxc.tty.dir = 3 | -------------------------------------------------------------------------------- /config/alpine.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config. 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/centos.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/debian.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/devuan.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/fedora.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/gentoo.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/kali.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/oracle.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/plamo.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/sabayon.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/archlinux.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/opensuse.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/slackware.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/sparclinux.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | -------------------------------------------------------------------------------- /config/ubuntu-cloud.lucid.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the main Ubuntu lucid config 2 | lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf 3 | -------------------------------------------------------------------------------- /config/ubuntu-cloud.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the main Ubuntu userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf 3 | -------------------------------------------------------------------------------- /config/ubuntu-cloud.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the main Ubuntu config 2 | lxc.include = @LXCTEMPLATECONFIG@/ubuntu.common.conf 3 | 4 | lxc.hook.clone = @LXCHOOKDIR@/ubuntu-cloud-prep 5 | -------------------------------------------------------------------------------- /config/plamo.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/ 5 | lxc.tty.dir = 6 | 7 | # Extra cgroup device access 8 | ## rtc 9 | lxc.cgroup.devices.allow = c 254:0 rm 10 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am 2 | 3 | ACLOCAL_AMFLAGS = -I config 4 | 5 | LIBTOOL_DEPS = @LIBTOOL_DEPS@ 6 | SUBDIRS = config templates 7 | DIST_SUBDIRS = config templates 8 | EXTRA_DIST = \ 9 | autogen.sh \ 10 | CONTRIBUTING \ 11 | MAINTAINERS 12 | 13 | ChangeLog:: 14 | @touch ChangeLog 15 | -------------------------------------------------------------------------------- /config/voidlinux.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | 4 | # Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd 5 | lxc.environment=VIRTUALIZATION=lxc 6 | 7 | # Set the halt/stop signals 8 | lxc.signal.halt=SIGCONT 9 | -------------------------------------------------------------------------------- /config/ubuntu.userns.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global userns config 2 | lxc.include = @LXCTEMPLATECONFIG@/userns.conf 3 | 4 | # Extra fstab entries as mountall can't mount those by itself 5 | lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0 6 | lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0 7 | -------------------------------------------------------------------------------- /templates/Makefile.am: -------------------------------------------------------------------------------- 1 | templatesdir=@LXCTEMPLATEDIR@ 2 | 3 | templates_SCRIPTS = \ 4 | lxc-alpine \ 5 | lxc-altlinux \ 6 | lxc-anolis \ 7 | lxc-archlinux \ 8 | lxc-centos \ 9 | lxc-cirros \ 10 | lxc-debian \ 11 | lxc-devuan \ 12 | lxc-fedora \ 13 | lxc-fedora-legacy \ 14 | lxc-gentoo \ 15 | lxc-kali \ 16 | lxc-openeuler \ 17 | lxc-openmandriva \ 18 | lxc-opensuse \ 19 | lxc-oracle \ 20 | lxc-plamo \ 21 | lxc-pld \ 22 | lxc-slackware \ 23 | lxc-sshd \ 24 | lxc-ubuntu \ 25 | lxc-ubuntu-cloud \ 26 | lxc-sparclinux \ 27 | lxc-voidlinux \ 28 | lxc-sabayon 29 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | Before submitting your patches, check they are signed-off-by 2 | conforming with the DCO contained in the ./CONTRIBUTING file. 3 | 4 | Maintainer 5 | ---------- 6 | 7 | Committers : Serge Hallyn, Stéphane Graber, Dwight Engen and Christian Brauner 8 | Mail patches to : lxc-devel@lists.linuxcontainers.org 9 | Send pull requests at : https://github.com/lxc/lxc 10 | Mailing lists : lxc-devel@lists.linuxcontainers.org, lxc-users@lists.linuxcontainers.org 11 | Web page : https://linuxcontainers.org/lxc 12 | GIT location : git://github.com/lxc/lxc 13 | -------------------------------------------------------------------------------- /config/alpine.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config. 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/. 5 | lxc.tty.dir = 6 | 7 | # Drop another (potentially) harmful capabilities. 8 | lxc.cap.drop = audit_write 9 | lxc.cap.drop = ipc_owner 10 | lxc.cap.drop = mknod 11 | lxc.cap.drop = sys_nice 12 | lxc.cap.drop = sys_pacct 13 | lxc.cap.drop = sys_rawio 14 | lxc.cap.drop = sys_resource 15 | lxc.cap.drop = sys_tty_config 16 | lxc.cap.drop = syslog 17 | lxc.cap.drop = wake_alarm 18 | 19 | # Mount /run as tmpfs. 20 | lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0 21 | 22 | # Mount /dev/shm as tmpfs; needed for building python and possibly other packages. 23 | lxc.mount.entry=shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0 24 | -------------------------------------------------------------------------------- /config/gentoo.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Gentoo common default configuration 5 | # This is the most feature-full container configuration 6 | # But security is not the goal. 7 | # Looking for more security, see gentoo.moresecure.conf 8 | 9 | # Doesn't support consoles in /dev/lxc/ 10 | lxc.tty.dir = 11 | 12 | # Extra cgroup device access 13 | ## rtc 14 | lxc.cgroup.devices.allow = c 254:0 rm 15 | ## tun 16 | lxc.cgroup.devices.allow = c 10:200 rwm 17 | ## hpet 18 | lxc.cgroup.devices.allow = c 10:228 rwm 19 | ## kvm 20 | lxc.cgroup.devices.allow = c 10:232 rwm 21 | ## To use loop devices, copy the following line to the container's 22 | ## configuration file (uncommented). 23 | #lxc.cgroup.devices.allow = b 7:* rwm 24 | 25 | # /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328) 26 | # and possibly other packages. 27 | lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir 28 | -------------------------------------------------------------------------------- /config/centos.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Capabilities 5 | # Uncomment these if you don't run anything that needs the capability, and 6 | # would like the container to run with less privilege. 7 | # 8 | # Dropping sys_admin disables container root from doing a lot of things 9 | # that could be bad like re-mounting lxc fstab entries rw for example, 10 | # but also disables some useful things like being able to nfs mount, and 11 | # things that are already namespaced with ns_capable() kernel checks, like 12 | # hostname(1). 13 | # lxc.cap.drop = sys_admin 14 | # lxc.cap.drop = net_raw # breaks dhcp/ping 15 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 16 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 17 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 18 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 19 | # lxc.cap.drop = audit_write 20 | lxc.cap.drop = sys_nice sys_pacct sys_rawio 21 | -------------------------------------------------------------------------------- /config/oracle.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Capabilities 5 | # Uncomment these if you don't run anything that needs the capability, and 6 | # would like the container to run with less privilege. 7 | # 8 | # Dropping sys_admin disables container root from doing a lot of things 9 | # that could be bad like re-mounting lxc fstab entries rw for example, 10 | # but also disables some useful things like being able to nfs mount, and 11 | # things that are already namespaced with ns_capable() kernel checks, like 12 | # hostname(1). 13 | # lxc.cap.drop = sys_admin 14 | # lxc.cap.drop = net_raw # breaks dhcp/ping 15 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 16 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 17 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 18 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 19 | # lxc.cap.drop = audit_write 20 | lxc.cap.drop = sys_nice sys_pacct sys_rawio 21 | -------------------------------------------------------------------------------- /config/sparclinux.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Capabilities 5 | # Uncomment these if you don't run anything that needs the capability, and 6 | # would like the container to run with less privilege. 7 | # 8 | # Dropping sys_admin disables container root from doing a lot of things 9 | # that could be bad like re-mounting lxc fstab entries rw for example, 10 | # but also disables some useful things like being able to nfs mount, and 11 | # things that are already namespaced with ns_capable() kernel checks, like 12 | # hostname(1). 13 | # lxc.cap.drop = sys_admin 14 | # lxc.cap.drop = net_raw # breaks dhcp/ping 15 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 16 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 17 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 18 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 19 | # lxc.cap.drop = audit_write 20 | lxc.cap.drop = sys_nice sys_pacct sys_rawio 21 | -------------------------------------------------------------------------------- /.github/workflows/commits.yml: -------------------------------------------------------------------------------- 1 | name: Commits 2 | on: 3 | - pull_request 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | dco-check: 10 | permissions: 11 | pull-requests: read # for tim-actions/get-pr-commits to get list of commits from the PR 12 | name: Signed-off-by (DCO) 13 | runs-on: ubuntu-20.04 14 | steps: 15 | - name: Get PR Commits 16 | id: 'get-pr-commits' 17 | uses: tim-actions/get-pr-commits@master 18 | with: 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | 21 | - name: Check that all commits are signed-off 22 | uses: tim-actions/dco@master 23 | with: 24 | commits: ${{ steps.get-pr-commits.outputs.commits }} 25 | 26 | target-branch: 27 | permissions: 28 | contents: none 29 | name: Branch target 30 | runs-on: ubuntu-20.04 31 | steps: 32 | - name: Check branch target 33 | env: 34 | TARGET: ${{ github.event.pull_request.base.ref }} 35 | run: | 36 | set -x 37 | [ "${TARGET}" = "main" ] && exit 0 38 | 39 | echo "Invalid branch target: ${TARGET}" 40 | exit 1 41 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # lxc: linux Container library 4 | # 5 | # (C) Copyright IBM Corp. 2007, 2008 6 | # 7 | # Authors: 8 | # Daniel Lezcano 9 | # 10 | # This library is free software; you can redistribute it and/or 11 | # modify it under the terms of the GNU Lesser General Public 12 | # License as published by the Free Software Foundation; either 13 | # version 2.1 of the License, or (at your option) any later version. 14 | # 15 | # This library is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | # Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public 21 | # License along with this library; if not, write to the Free Software 22 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 | 24 | set -x 25 | 26 | test -d autom4te.cache && rm -rf autom4te.cache 27 | aclocal -I config || exit 1 28 | autoconf || exit 1 29 | automake --add-missing --copy || exit 1 30 | -------------------------------------------------------------------------------- /config/kali.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/ 5 | lxc.tty.dir = 6 | 7 | # When using LXC with apparmor, the container will be confined by default. 8 | # If you wish for it to instead run unconfined, copy the following line 9 | # (uncommented) to the container's configuration file. 10 | #lxc.apparmor.profile = unconfined 11 | 12 | # If you wish to allow mounting block filesystems, then use the following 13 | # line instead, and make sure to grant access to the block device and/or loop 14 | # devices below in lxc.cgroup.devices.allow. 15 | #lxc.apparmor.profile = lxc-container-default-with-mounting 16 | 17 | # Extra cgroup device access 18 | ## rtc 19 | lxc.cgroup.devices.allow = c 254:0 rm 20 | ## tun 21 | lxc.cgroup.devices.allow = c 10:200 rwm 22 | ## hpet 23 | lxc.cgroup.devices.allow = c 10:228 rwm 24 | ## kvm 25 | lxc.cgroup.devices.allow = c 10:232 rwm 26 | ## To use loop devices, copy the following line to the container's 27 | ## configuration file (uncommented). 28 | #lxc.cgroup.devices.allow = b 7:* rwm 29 | -------------------------------------------------------------------------------- /config/Makefile.am: -------------------------------------------------------------------------------- 1 | templatesconfigdir=@LXCTEMPLATECONFIG@ 2 | 3 | templatesconfig_DATA = \ 4 | alpine.common.conf \ 5 | alpine.userns.conf \ 6 | archlinux.common.conf \ 7 | archlinux.userns.conf \ 8 | centos.common.conf \ 9 | centos.userns.conf \ 10 | debian.common.conf \ 11 | debian.userns.conf \ 12 | devuan.common.conf \ 13 | devuan.userns.conf \ 14 | fedora.common.conf \ 15 | fedora.userns.conf \ 16 | gentoo.common.conf \ 17 | gentoo.moresecure.conf \ 18 | gentoo.userns.conf \ 19 | kali.common.conf \ 20 | kali.userns.conf \ 21 | opensuse.common.conf \ 22 | opensuse.userns.conf \ 23 | oracle.common.conf \ 24 | oracle.userns.conf \ 25 | plamo.common.conf \ 26 | plamo.userns.conf \ 27 | slackware.common.conf \ 28 | slackware.userns.conf \ 29 | ubuntu-cloud.common.conf \ 30 | ubuntu-cloud.lucid.conf \ 31 | ubuntu-cloud.userns.conf \ 32 | ubuntu.common.conf \ 33 | ubuntu.lucid.conf \ 34 | ubuntu.userns.conf \ 35 | openwrt.common.conf \ 36 | sparclinux.common.conf \ 37 | sparclinux.userns.conf \ 38 | voidlinux.common.conf \ 39 | voidlinux.userns.conf \ 40 | sabayon.common.conf \ 41 | sabayon.userns.conf 42 | -------------------------------------------------------------------------------- /config/debian.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/ 5 | lxc.tty.dir = 6 | 7 | # When using LXC with apparmor, the container will be confined by default. 8 | # If you wish for it to instead run unconfined, copy the following line 9 | # (uncommented) to the container's configuration file. 10 | #lxc.apparmor.profile = unconfined 11 | 12 | # If you wish to allow mounting block filesystems, then use the following 13 | # line instead, and make sure to grant access to the block device and/or loop 14 | # devices below in lxc.cgroup.devices.allow. 15 | #lxc.apparmor.profile = lxc-container-default-with-mounting 16 | 17 | # Extra cgroup device access 18 | ## rtc 19 | lxc.cgroup.devices.allow = c 254:0 rm 20 | ## tun 21 | lxc.cgroup.devices.allow = c 10:200 rwm 22 | ## hpet 23 | lxc.cgroup.devices.allow = c 10:228 rwm 24 | ## kvm 25 | lxc.cgroup.devices.allow = c 10:232 rwm 26 | ## To use loop devices, copy the following line to the container's 27 | ## configuration file (uncommented). 28 | #lxc.cgroup.devices.allow = b 7:* rwm 29 | -------------------------------------------------------------------------------- /config/devuan.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/ 5 | lxc.tty.dir = 6 | 7 | # When using LXC with apparmor, the container will be confined by default. 8 | # If you wish for it to instead run unconfined, copy the following line 9 | # (uncommented) to the container's configuration file. 10 | #lxc.apparmor.profile = unconfined 11 | 12 | # If you wish to allow mounting block filesystems, then use the following 13 | # line instead, and make sure to grant access to the block device and/or loop 14 | # devices below in lxc.cgroup.devices.allow. 15 | #lxc.apparmor.profile = lxc-container-default-with-mounting 16 | 17 | # Extra cgroup device access 18 | ## rtc 19 | lxc.cgroup.devices.allow = c 254:0 rm 20 | ## tun 21 | lxc.cgroup.devices.allow = c 10:200 rwm 22 | ## hpet 23 | lxc.cgroup.devices.allow = c 10:228 rwm 24 | ## kvm 25 | lxc.cgroup.devices.allow = c 10:232 rwm 26 | ## To use loop devices, copy the following line to the container's 27 | ## configuration file (uncommented). 28 | #lxc.cgroup.devices.allow = b 7:* rwm 29 | -------------------------------------------------------------------------------- /config/fedora.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Capabilities 5 | # Uncomment these if you don't run anything that needs the capability, and 6 | # would like the container to run with less privilege. 7 | # 8 | # Dropping sys_admin disables container root from doing a lot of things 9 | # that could be bad like re-mounting lxc fstab entries rw for example, 10 | # but also disables some useful things like being able to nfs mount, and 11 | # things that are already namespaced with ns_capable() kernel checks, like 12 | # hostname(1). 13 | # lxc.cap.drop = sys_admin 14 | # lxc.cap.drop = net_raw # breaks dhcp/ping 15 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 16 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 17 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 18 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 19 | # lxc.cap.drop = audit_write 20 | # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd 21 | lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio 22 | -------------------------------------------------------------------------------- /config/opensuse.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Capabilities 5 | # Uncomment these if you don't run anything that needs the capability, and 6 | # would like the container to run with less privilege. 7 | # 8 | # Dropping sys_admin disables container root from doing a lot of things 9 | # that could be bad like re-mounting lxc fstab entries rw for example, 10 | # but also disables some useful things like being able to nfs mount, and 11 | # things that are already namespaced with ns_capable() kernel checks, like 12 | # hostname(1). 13 | # lxc.cap.drop = sys_admin 14 | # lxc.cap.drop = net_raw # breaks dhcp/ping 15 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 16 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 17 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 18 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 19 | # lxc.cap.drop = audit_write 20 | # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd 21 | # lxc.cap.drop = setfcap 22 | lxc.cap.drop = sys_nice sys_pacct sys_rawio 23 | -------------------------------------------------------------------------------- /config/archlinux.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Allow for 6 tty devices by default 5 | lxc.tty.max = 6 6 | 7 | # Set the halt/stop signals 8 | lxc.signal.halt=SIGRTMIN+4 9 | 10 | # Uncomment to disable creating tty devices subdirectory in /dev 11 | # lxc.tty.dir = 12 | 13 | # Capabilities 14 | # Uncomment these if you don't run anything that needs the capability, and 15 | # would like the container to run with less privilege. 16 | # 17 | # Dropping sys_admin disables container root from doing a lot of things 18 | # that could be bad like re-mounting lxc fstab entries rw for example, 19 | # but also disables some useful things like being able to nfs mount, and 20 | # things that are already namespaced with ns_capable() kernel checks, like 21 | # hostname(1). 22 | # lxc.cap.drop = sys_admin 23 | # lxc.cap.drop = net_raw # breaks dhcp/ping 24 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 25 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 26 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 27 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 28 | # lxc.cap.drop = audit_write 29 | # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd 30 | # 31 | lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio 32 | -------------------------------------------------------------------------------- /config/voidlinux.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Allow for 6 tty devices by default 5 | lxc.tty.max = 6 6 | 7 | # Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd 8 | lxc.environment=VIRTUALIZATION=lxc 9 | 10 | # Set the halt/stop signals 11 | lxc.signal.halt=SIGCONT 12 | 13 | 14 | # Uncomment to disable creating tty devices subdirectory in /dev 15 | # lxc.tty.dir = 16 | 17 | # Capabilities 18 | # Uncomment these if you don't run anything that needs the capability, and 19 | # would like the container to run with less privilege. 20 | # 21 | # Dropping sys_admin disables container root from doing a lot of things 22 | # that could be bad like re-mounting lxc fstab entries rw for example, 23 | # but also disables some useful things like being able to nfs mount, and 24 | # things that are already namespaced with ns_capable() kernel checks, like 25 | # hostname(1). 26 | # lxc.cap.drop = sys_admin 27 | # lxc.cap.drop = net_raw # breaks dhcp/ping 28 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 29 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 30 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 31 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 32 | # lxc.cap.drop = audit_write 33 | # lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd 34 | # 35 | lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio 36 | -------------------------------------------------------------------------------- /config/openwrt.common.conf.in: -------------------------------------------------------------------------------- 1 | # Default console settings 2 | lxc.tty.dir = lxc 3 | lxc.tty.max = 4 4 | lxc.pty.max = 1024 5 | 6 | # Default capabilities 7 | lxc.cap.drop = mac_admin 8 | lxc.cap.drop = mac_override 9 | lxc.cap.drop = sys_admin 10 | lxc.cap.drop = sys_module 11 | lxc.cap.drop = sys_nice 12 | lxc.cap.drop = sys_pacct 13 | lxc.cap.drop = sys_ptrace 14 | lxc.cap.drop = sys_rawio 15 | lxc.cap.drop = sys_resource 16 | lxc.cap.drop = sys_time 17 | lxc.cap.drop = sys_tty_config 18 | lxc.cap.drop = syslog 19 | lxc.cap.drop = wake_alarm 20 | 21 | # Default cgroups - all denied except those whitelisted 22 | lxc.cgroup.devices.deny = a 23 | ## /dev/null and zero 24 | lxc.cgroup.devices.allow = c 1:3 rwm 25 | lxc.cgroup.devices.allow = c 1:5 rwm 26 | ## consoles 27 | lxc.cgroup.devices.allow = c 5:0 rwm 28 | lxc.cgroup.devices.allow = c 5:1 rwm 29 | ## /dev/{,u}random 30 | lxc.cgroup.devices.allow = c 1:8 rwm 31 | lxc.cgroup.devices.allow = c 1:9 rwm 32 | ## /dev/pts/* 33 | lxc.cgroup.devices.allow = c 5:2 rwm 34 | lxc.cgroup.devices.allow = c 136:* rwm 35 | ## rtc 36 | lxc.cgroup.devices.allow = c 254:0 rm 37 | ## tun 38 | lxc.cgroup.devices.allow = c 10:200 rwm 39 | ## dev/tty0 40 | lxc.cgroup.devices.allow = c 4:0 rwm 41 | ## dev/tty1 42 | lxc.cgroup.devices.allow = c 4:1 rwm 43 | 44 | ## To use loop devices, copy the following line to the container's 45 | ## configuration file (uncommented). 46 | #lxc.cgroup.devices.allow = b 7:* rwm 47 | 48 | # Blacklist some syscalls which are not safe in privileged 49 | # containers 50 | lxc.seccomp.profile = /usr/share/lxc/config/common.seccomp 51 | -------------------------------------------------------------------------------- /config/ubuntu.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Default mount entries 5 | lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0 6 | lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0 7 | lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0 8 | lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0 9 | 10 | # When using LXC with apparmor, the container will be confined by default. 11 | # If you wish for it to instead run unconfined, copy the following line 12 | # (uncommented) to the container's configuration file. 13 | #lxc.apparmor.profile = unconfined 14 | 15 | # Uncomment the following line to autodetect squid-deb-proxy configuration on the 16 | # host and forward it to the guest at start time. 17 | #lxc.hook.pre-start = /usr/share/lxc/hooks/squid-deb-proxy-client 18 | 19 | # If you wish to allow mounting block filesystems, then use the following 20 | # line instead, and make sure to grant access to the block device and/or loop 21 | # devices below in lxc.cgroup.devices.allow. 22 | #lxc.apparmor.profile = lxc-container-default-with-mounting 23 | 24 | # Extra cgroup device access 25 | ## rtc 26 | lxc.cgroup.devices.allow = c 254:0 rm 27 | ## tun 28 | lxc.cgroup.devices.allow = c 10:200 rwm 29 | ## hpet 30 | lxc.cgroup.devices.allow = c 10:228 rwm 31 | ## kvm 32 | lxc.cgroup.devices.allow = c 10:232 rwm 33 | ## To use loop devices, copy the following line to the container's 34 | ## configuration file (uncommented). 35 | #lxc.cgroup.devices.allow = b 7:* rwm 36 | -------------------------------------------------------------------------------- /config/slackware.common.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Doesn't support consoles in /dev/lxc/ 5 | lxc.tty.dir = 6 | 7 | # Extra cgroup device access 8 | ## rtc 9 | lxc.cgroup.devices.allow = c 254:0 rm 10 | ## tun 11 | lxc.cgroup.devices.allow = c 10:200 rwm 12 | ## hpet 13 | lxc.cgroup.devices.allow = c 10:228 rwm 14 | ## kvm 15 | lxc.cgroup.devices.allow = c 10:232 rwm 16 | ## To use loop devices, copy the following line to the container's 17 | ## configuration file (uncommented). 18 | #lxc.cgroup.devices.allow = b 7:* rwm 19 | 20 | # mount /dev/shm as tmpfs 21 | lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir 22 | 23 | # Capabilities 24 | # Uncomment these if you don't run anything that needs the capability, and 25 | # would like the container to run with less privilege. 26 | # Note that some are already dropped in common.conf. 27 | # 28 | # Dropping sys_admin disables container root from doing a lot of things 29 | # that could be bad like re-mounting lxc fstab entries rw for example, 30 | # but also disables some useful things like being able to nfs mount, and 31 | # things that are already namespaced with ns_capable() kernel checks, like 32 | # hostname(1). 33 | # 34 | # Some of these don't apply in Slackware but are here for future reference. 35 | # 36 | # lxc.cap.drop = sys_admin # breaks systemd 37 | # lxc.cap.drop = net_raw # breaks dhcp/ping 38 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 39 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 40 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 41 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 42 | # lxc.cap.drop = audit_write 43 | # lxc.cap.drop = setpcap # breaks journald 44 | # lxc.cap.drop = sys_resource # breaks systemd 45 | # 46 | lxc.cap.drop = mknod setfcap setpcap 47 | -------------------------------------------------------------------------------- /config/sabayon.common.conf.in: -------------------------------------------------------------------------------- 1 | # Default configuration for Sabayon containers 2 | 3 | # Setup the default mounts 4 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed 5 | 6 | # Allow for 1024 pseudo terminals 7 | lxc.pty.max = 1024 8 | 9 | # Setup 1 tty devices for lxc-console command 10 | lxc.tty.max = 1 11 | 12 | # Needed for systemd distro 13 | lxc.autodev = 1 14 | 15 | # Doesn't support consoles in /dev/lxc/ 16 | lxc.tty.dir = 17 | 18 | # CGroup whitelist 19 | lxc.cgroup.devices.deny = a 20 | 21 | ## Allow any mknod (but not reading/writing the node) 22 | #lxc.cgroup.devices.allow = c *:* m 23 | #lxc.cgroup.devices.allow = b *:* m 24 | 25 | ## Allow specific devices 26 | ### /dev/null 27 | lxc.cgroup.devices.allow = c 1:3 rwm 28 | ### /dev/zero 29 | lxc.cgroup.devices.allow = c 1:5 rwm 30 | ### /dev/full 31 | lxc.cgroup.devices.allow = c 1:7 rwm 32 | ### /dev/random 33 | lxc.cgroup.devices.allow = c 1:8 rwm 34 | ### /dev/urandom 35 | lxc.cgroup.devices.allow = c 1:9 rwm 36 | ### /dev/pts/* 37 | #lxc.cgroup.devices.allow = c 136:* rwm 38 | ### /dev/tty 39 | #lxc.cgroup.devices.allow = c 5:0 rwm 40 | ### /dev/console 41 | #lxc.cgroup.devices.allow = c 5:1 rwm 42 | ### /dev/ptmx 43 | #lxc.cgroup.devices.allow = c 5:2 rwm 44 | ### fuse 45 | #lxc.cgroup.devices.allow = c 10:229 rwm 46 | ## To use loop devices, copy the following line to the container's 47 | ## configuration file (uncommented). 48 | #lxc.cgroup.devices.allow = b 7:* rwm 49 | ## rtc 50 | #lxc.cgroup.devices.allow = c 254:0 rm 51 | ## tun 52 | #lxc.cgroup.devices.allow = c 10:200 rwm 53 | ## hpet 54 | #lxc.cgroup.devices.allow = c 10:228 rwm 55 | ## kvm 56 | #lxc.cgroup.devices.allow = c 10:232 rwm 57 | ## /dev/mem 58 | #lxc.cgroup.devices.allow = c 1:1 rwm 59 | 60 | # If something doesn't work, try to comment this out. 61 | # Dropping sys_admin disables container root from doing a lot of things 62 | # that could be bad like re-mounting lxc fstab entries rw for example, 63 | # but also disables some useful things like being able to nfs mount, and 64 | # things that are already namespaced with ns_capable() kernel checks, like 65 | # hostname(1). 66 | lxc.cap.drop = sys_time sys_module sys_rawio mac_admin mac_override 67 | #lxc.cap.drop = sys_admin 68 | 69 | 70 | # /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328) 71 | # and possibly other packages. 72 | lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir 73 | 74 | # Blacklist some syscalls which are not safe in privileged 75 | # containers 76 | lxc.seccomp.profile = @LXCTEMPLATECONFIG@/common.seccomp 77 | 78 | # Customize lxc options through common directory 79 | lxc.include = @LXCTEMPLATECONFIG@/common.conf.d/ 80 | -------------------------------------------------------------------------------- /config/gentoo.moresecure.conf.in: -------------------------------------------------------------------------------- 1 | # This derives from the global common config 2 | lxc.include = @LXCTEMPLATECONFIG@/common.conf 3 | 4 | # Gentoo security oriented default configuration 5 | # This is a more security oriented container configuration 6 | # "More" because this is far from fully secure 7 | # Looking for more working features and you trust your 8 | # Container user ? see gentoo.common.conf 9 | 10 | # do not mount sysfs, see http://blog.bofh.it/debian/id_413 11 | lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid,create=dir 0 0 12 | lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,create=dir 0 0 13 | lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 14 | 15 | # Capabilities 16 | # Uncomment these if you don't run anything that needs the capability, and 17 | # would like the container to run with less privilege. 18 | # 19 | # Dropping sys_admin disables container root from doing a lot of things 20 | # that could be bad like re-mounting lxc fstab entries rw for example, 21 | # but also disables some useful things like being able to nfs mount, and 22 | # things that are already namespaced with ns_capable() kernel checks, like 23 | # hostname(1). 24 | # lxc.cap.drop = sys_admin # breaks systemd 25 | # lxc.cap.drop = net_raw # breaks dhcp/ping 26 | # lxc.cap.drop = setgid # breaks login (initgroups/setgroups) 27 | # lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd) 28 | # lxc.cap.drop = setuid # breaks sshd,nfs statd 29 | # lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed) 30 | # lxc.cap.drop = audit_write 31 | # lxc.cap.drop = setpcap # breaks journald 32 | # lxc.cap.drop = sys_resource # breaks systemd 33 | # lxc.cap.drop = sys_boot # breaks sysvinit 34 | lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog 35 | 36 | # WARNING: the security vulnerability reported for 'cap_net_admin' at 37 | # http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html 38 | # via JIT spraying (the BPF JIT module disabled on most systems was used 39 | # in the example, but others are suggested vulnerable) meant that users 40 | # with root in a container, that capability and kernel module may escape 41 | # the container. ALWAYS be extremely careful granting any process root 42 | # within a container, use a minimal configuration at all levels - 43 | # including the kernel - and multiple layers of security on any system 44 | # where security is a priority. note that not only LXC but PAX (and 45 | # others?) were vulnerable to this issue. 46 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Contributing to this project 2 | ---------------------------- 3 | 4 | This project accepts contributions. In order to contribute, you should 5 | pay attention to a few things: 6 | 7 | 1 - your code must follow the coding style rules 8 | 2 - the format of the submission must Github pull requests 9 | 3 - your work must be signed 10 | 11 | 12 | Coding Style: 13 | ------------- 14 | 15 | The coding style follows the Linux kernel coding style. 16 | 17 | The coding style is defined in the 'CodingStyle' file, available in 18 | the directory 'Documentation' of the Linux kernel source tree. 19 | 20 | It can be accessed online too: 21 | 22 | https://www.kernel.org/doc/html/v4.10/process/coding-style.html 23 | 24 | Submitting Modifications: 25 | ------------------------- 26 | 27 | The contributions must be Github pull requests. 28 | 29 | Licensing for new files: 30 | ------------------------ 31 | 32 | LXC is made of files shipped under a few different licenses. 33 | 34 | Anything that ends up being part of the LXC library needs to be released 35 | under LGPLv2.1+ or a license compatible with it (though the latter will 36 | only be accepted for cases where the code originated elsewhere and was 37 | imported into LXC). 38 | 39 | Language bindings for the libraries need to be released under LGPLv2.1+. 40 | 41 | Anything else (non-libaries) needs to be Free Software and needs to be 42 | allowed to link with LGPLv2.1+ code (if needed). LXC upstream prefers 43 | LGPLv2.1+ or GPLv2 for those. 44 | 45 | When introducing a new file into the project, please make sure it has a 46 | copyright header making clear under which license it's being released 47 | and if it doesn't match the criteria described above, please explain 48 | your decision on the lxc-devel mailing-list when submitting your patch. 49 | 50 | Developer Certificate of Origin: 51 | -------------------------------- 52 | 53 | To improve tracking of contributions to this project we will use a 54 | process modeled on the modified DCO 1.1 and use a "sign-off" procedure. 55 | 56 | The sign-off is a simple line at the end of the explanation for the 57 | patch, which certifies that you wrote it or otherwise have the right 58 | to pass it on as an open-source patch. The rules are pretty simple: 59 | if you can certify the below: 60 | 61 | By making a contribution to this project, I certify that: 62 | 63 | (a) The contribution was created in whole or in part by me and I have 64 | the right to submit it under the open source license indicated in 65 | the file; or 66 | 67 | (b) The contribution is based upon previous work that, to the best of 68 | my knowledge, is covered under an appropriate open source License 69 | and I have the right under that license to submit that work with 70 | modifications, whether created in whole or in part by me, under 71 | the same open source license (unless I am permitted to submit 72 | under a different license), as indicated in the file; or 73 | 74 | (c) The contribution was provided directly to me by some other person 75 | who certified (a), (b) or (c) and I have not modified it. 76 | 77 | (d) The contribution is made free of any other party's intellectual 78 | property claims or rights. 79 | 80 | (e) I understand and agree that this project and the contribution are 81 | public and that a record of the contribution (including all 82 | personal information I submit with it, including my sign-off) is 83 | maintained indefinitely and may be redistributed consistent with 84 | this project or the open source license(s) involved. 85 | 86 | 87 | then you just add a line saying 88 | 89 | Signed-off-by: Random J Developer 90 | 91 | You can do it by using option -s or --signoff when you commit 92 | 93 | git commit --signoff ... 94 | 95 | using your real name (sorry, no pseudonyms or anonymous contributions.) 96 | 97 | In addition we support the following DCOs which maintainers can use to indicate 98 | that a patch is acceptable: 99 | 100 | Acked-by: Random J Developer 101 | Reviewed-by: Random J Developer 102 | 103 | If you are contributing as a group who is implementing a feature together such 104 | that it cannot be reasonably attributed to a single developer please use: 105 | 106 | Co-developed-by: Random J Developer 1 107 | Co-developed-by: Random J Developer 2 108 | -------------------------------------------------------------------------------- /config/acinclude.m4: -------------------------------------------------------------------------------- 1 | dnl as-ac-expand.m4 0.2.0 2 | dnl autostars m4 macro for expanding directories using configure's prefix 3 | dnl thomas@apestaart.org 4 | dnl 5 | 6 | dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) 7 | dnl example 8 | dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) 9 | dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local 10 | 11 | AC_DEFUN([AS_AC_EXPAND], 12 | [ 13 | EXP_VAR=[$1] 14 | FROM_VAR=[$2] 15 | 16 | dnl first expand prefix and exec_prefix if necessary 17 | prefix_save=$prefix 18 | exec_prefix_save=$exec_prefix 19 | 20 | dnl if no prefix given, then use /usr/local, the default prefix 21 | if test "x$prefix" = "xNONE"; then 22 | prefix="$ac_default_prefix" 23 | fi 24 | dnl if no exec_prefix given, then use prefix 25 | if test "x$exec_prefix" = "xNONE"; then 26 | exec_prefix=$prefix 27 | fi 28 | 29 | full_var="$FROM_VAR" 30 | dnl loop until it doesn't change anymore 31 | while true; do 32 | new_full_var="`eval echo $full_var`" 33 | if test "x$new_full_var" = "x$full_var"; then break; fi 34 | full_var=$new_full_var 35 | done 36 | 37 | dnl clean up 38 | full_var=$new_full_var 39 | AC_SUBST([$1], "$full_var") 40 | 41 | dnl restore prefix and exec_prefix 42 | prefix=$prefix_save 43 | exec_prefix=$exec_prefix_save 44 | ]) 45 | 46 | dnl Available from the GNU Autoconf Macro Archive at: 47 | dnl http://www.gnu.org/software/ac-archive/htmldoc/ax_compare_version.html 48 | AC_DEFUN([AX_COMPARE_VERSION], [ 49 | # Used to indicate true or false condition 50 | ax_compare_version=false 51 | # Convert the two version strings to be compared into a format that 52 | # allows a simple string comparison. The end result is that a version 53 | # string of the form 1.12.5-r617 will be converted to the form 54 | # 0001001200050617. In other words, each number is zero padded to four 55 | # digits, and non digits are removed. 56 | AS_VAR_PUSHDEF([A],[ax_compare_version_A]) 57 | A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 58 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 59 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 60 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 61 | -e 's/[[^0-9]]//g'` 62 | 63 | AS_VAR_PUSHDEF([B],[ax_compare_version_B]) 64 | B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 65 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 66 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 67 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 68 | -e 's/[[^0-9]]//g'` 69 | 70 | dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary 71 | dnl # then the first line is used to determine if the condition is true. 72 | dnl # The sed right after the echo is to remove any indented white space. 73 | m4_case(m4_tolower($2), 74 | [lt],[ 75 | ax_compare_version=`echo "x$A 76 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` 77 | ], 78 | [gt],[ 79 | ax_compare_version=`echo "x$A 80 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` 81 | ], 82 | [le],[ 83 | ax_compare_version=`echo "x$A 84 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` 85 | ], 86 | [ge],[ 87 | ax_compare_version=`echo "x$A 88 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` 89 | ],[ 90 | dnl Split the operator from the subversion count if present. 91 | m4_bmatch(m4_substr($2,2), 92 | [0],[ 93 | # A count of zero means use the length of the shorter version. 94 | # Determine the number of characters in A and B. 95 | ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'` 96 | ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'` 97 | 98 | # Set A to no more than B's length and B to no more than A's length. 99 | A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` 100 | B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` 101 | ], 102 | [[0-9]+],[ 103 | # A count greater than zero means use only that many subversions 104 | A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 105 | B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 106 | ], 107 | [.+],[ 108 | AC_WARNING( 109 | [illegal OP numeric parameter: $2]) 110 | ],[]) 111 | 112 | # Pad zeros at end of numbers to make same length. 113 | ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" 114 | B="$B`echo $A | sed 's/./0/g'`" 115 | A="$ax_compare_version_tmp_A" 116 | 117 | # Check for equality or inequality as necessary. 118 | m4_case(m4_tolower(m4_substr($2,0,2)), 119 | [eq],[ 120 | test "x$A" = "x$B" && ax_compare_version=true 121 | ], 122 | [ne],[ 123 | test "x$A" != "x$B" && ax_compare_version=true 124 | ],[ 125 | AC_WARNING([illegal OP parameter: $2]) 126 | ]) 127 | ]) 128 | 129 | AS_VAR_POPDEF([A])dnl 130 | AS_VAR_POPDEF([B])dnl 131 | 132 | dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. 133 | if test "$ax_compare_version" = "true" ; then 134 | m4_ifvaln([$4],[$4],[:])dnl 135 | m4_ifvaln([$5],[else $5])dnl 136 | fi 137 | ]) dnl AX_COMPARE_VERSION 138 | -------------------------------------------------------------------------------- /templates/lxc-voidlinux.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # template script for generating Void Linux container for LXC 5 | # 6 | 7 | # 8 | # lxc: linux Container library 9 | 10 | # Authors: 11 | # Gregor Reitzenstein 12 | 13 | # Based on lxc-archlinux template by: 14 | # Alexander Vladimirov 15 | # John Lane 16 | 17 | # This library is free software; you can redistribute it and/or 18 | # modify it under the terms of the GNU Lesser General Public 19 | # License as published by the Free Software Foundation; either 20 | # version 2.1 of the License, or (at your option) any later version. 21 | 22 | # This library is distributed in the hope that it will be useful, 23 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 | # Lesser General Public License for more details. 26 | 27 | # You should have received a copy of the GNU Lesser General Public 28 | # License along with this library; if not, write to the Free Software 29 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 30 | 31 | # Utility functions 32 | 33 | # Check if array $2 contains item $1 34 | containsElement() { 35 | local e 36 | for e in "${@:2}"; do [[ "$1" == "$e" ]] && return 0; done 37 | return 1 38 | } 39 | 40 | # split comma-separated string into an array 41 | # ${1} - string to split 42 | # ${2} - separator (default is ",") 43 | # ${result} - result value on success 44 | split_string() { 45 | local ifs=${IFS} 46 | IFS="${2:-,}" 47 | read -ra result < <(echo "${1}") 48 | IFS=${ifs} 49 | return 0 50 | } 51 | 52 | # Make sure the usual locations are in PATH 53 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 54 | 55 | # defaults 56 | default_path="/var/lib/lxc" 57 | default_path="@LXCPATH@" 58 | shared_config="@LXCTEMPLATECONFIG@/voidlinux.common.conf" 59 | userns_config="@LXCTEMPLATECONFIG@/voidlinux.userns.conf" 60 | 61 | pkg_blacklist=("linux>=0" "e2fsprogs>=0" "btrfs-progs>=0" "xfsprogs>=0" "f2fs-tools>=0" "dosfstools>=0") 62 | base_packages=() 63 | for pkg in $(xbps-query -Mv --repository="https://repo-default.voidlinux.org/current/" -x base-system); do 64 | containsElement "$pkg" "${pkg_blacklist[@]}" || base_packages+=($pkg) 65 | done 66 | declare -a additional_packages 67 | 68 | copy_configuration() { 69 | mkdir -p "${config_path}" 70 | local config="${config_path}/config" 71 | echo "lxc.uts.name = ${name}" >> "${config}" 72 | grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \ 73 | || echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}" 74 | 75 | # Detect if were in a UserNS and include the right config 76 | if [ -z "${LXC_MAPPED_GID+x}" ] || [ -z "${LXC_MAPPED_UID+x}" ]; then 77 | echo "lxc.include = ${userns_config}" >> "${config}" 78 | else 79 | echo "lxc.include = ${shared_config}" >> "${config}" 80 | fi 81 | 82 | if [ $? -ne 0 ]; then 83 | echo "Failed to configure container" 84 | return 1 85 | fi 86 | return 0 87 | } 88 | 89 | install_void() { 90 | if ! yes | xbps-install -Sy -R https://repo-default.voidlinux.org/current -r "${rootfs_path}" "${base_packages[@]}" 91 | then 92 | echo "Failed to install container packages" 93 | return 1 94 | fi 95 | } 96 | 97 | usage() { 98 | cat < [-p|--path=] [-a|--arch=] 101 | [-r|--root_password=] [-P|--packages=] [-h|--help] 102 | 103 | Mandatory args: 104 | -n,--name container name, used to as an identifier for that container from now on 105 | Optional args: 106 | -p,--path path to where the container rootfs will be created (${default_path}) 107 | --rootfs path for actual container rootfs, (${default_path}/rootfs) 108 | -P,--packages preinstall additional packages, comma-separated list 109 | -c,--config use specified pacman config when installing container packages 110 | -a,--arch use specified architecture instead of host's architecture 111 | -r,--root_password set container root password 112 | -h,--help print this help 113 | EOF 114 | return 0 115 | } 116 | 117 | options=$(getopt -o hp:P:n:c:r: -l help,rootfs:,path:,packages:,name:,config:,root_password:,mapped-uid:,mapped-gid: -- "${@}") 118 | if [ ${?} -ne 0 ]; then 119 | usage "$(basename "${0}")" 120 | exit 1 121 | fi 122 | eval set -- "${options}" 123 | 124 | while true 125 | do 126 | case "${1}" in 127 | -h|--help) usage "${0}" && exit 0;; 128 | -p|--path) path=${2}; shift 2;; 129 | -n|--name) name=${2}; shift 2;; 130 | -c|--config) config_path=${2}; shift 2;; 131 | --rootfs) rootfs_path=${2}; shift 2;; 132 | -P|--packages) additional_packages=${2}; shift 2;; 133 | -r|--root_password) root_passwd=${2}; shift 2;; 134 | --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; 135 | --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; 136 | --) shift 1; break ;; 137 | *) break ;; 138 | esac 139 | done 140 | 141 | if [ -z "${name}" ]; then 142 | echo "missing required 'name' parameter" 143 | exit 1 144 | fi 145 | 146 | type xbps-install >/dev/null 2>&1 147 | if [ ${?} -ne 0 ]; then 148 | echo "'xbps-install' command is missing." 149 | fi 150 | type xbps-query >/dev/null 2>&1 151 | if [ ${?} -ne 0 ]; then 152 | echo "'xbps-query' command is missing." 153 | fi 154 | 155 | if [ -z "${rootfs_path}" ]; then 156 | rootfs_path="${path}/rootfs" 157 | fi 158 | config_path="${path}" 159 | 160 | revert() { 161 | echo "Interrupted, cleaning up" 162 | lxc-destroy -n "${name}" 163 | rm -rf "${path:?}/${name}" 164 | rm -rf "${default_path:?}/${name}" 165 | exit 1 166 | } 167 | trap revert SIGHUP SIGINT SIGTERM 168 | 169 | copy_configuration 170 | if [ $? -ne 0 ]; then 171 | echo "Failed to write configuration file" 172 | rm -rf "${config_path}" 173 | exit 1 174 | fi 175 | 176 | if [ ${#additional_packages[@]} -gt 0 ]; then 177 | split_string "${additional_packages}" 178 | base_packages+=(${result[@]}) 179 | fi 180 | 181 | mkdir -p "${rootfs_path}" 182 | install_void 183 | if [ ${?} -ne 0 ]; then 184 | echo "Failed to install Void Linux" 185 | rm -rf "${config_path}" "${path}" 186 | exit 1 187 | fi 188 | 189 | 190 | 191 | if [ -n "${root_passwd}" ]; then 192 | echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd 193 | fi 194 | 195 | cat << EOF 196 | Void Linux Container ${name} has been successfully created. The configuration is 197 | stored in ${config_path}/config. Please refer to https://docs.voidlinux.org for 198 | information regarding Void Linux. 199 | EOF 200 | -------------------------------------------------------------------------------- /templates/lxc-sshd.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # lxc: linux Container library 5 | 6 | # Authors: 7 | # Daniel Lezcano 8 | 9 | # This library is free software; you can redistribute it and/or 10 | # modify it under the terms of the GNU Lesser General Public 11 | # License as published by the Free Software Foundation; either 12 | # version 2.1 of the License, or (at your option) any later version. 13 | 14 | # This library is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | # Lesser General Public License for more details. 18 | 19 | # You should have received a copy of the GNU Lesser General Public 20 | # License along with this library; if not, write to the Free Software 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | 23 | # Detect use under userns (unsupported) 24 | for arg in "$@"; do 25 | [ "$arg" = "--" ] && break 26 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 27 | echo "This template can't be used for unprivileged containers." 1>&2 28 | echo "You may want to try the \"download\" template instead." 1>&2 29 | exit 1 30 | fi 31 | done 32 | 33 | # Make sure the usual locations are in PATH 34 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 35 | 36 | install_sshd() 37 | { 38 | rootfs=$1 39 | 40 | tree="\ 41 | $rootfs/var/empty/sshd \ 42 | $rootfs/var/lib/empty/sshd \ 43 | $rootfs/etc/init.d \ 44 | $rootfs/etc/rc.d \ 45 | $rootfs/etc/ssh \ 46 | $rootfs/etc/sysconfig/network-scripts \ 47 | $rootfs/dev/shm \ 48 | $rootfs/run/sshd \ 49 | $rootfs/proc \ 50 | $rootfs/sys \ 51 | $rootfs/bin \ 52 | $rootfs/sbin \ 53 | $rootfs/usr \ 54 | $rootfs/tmp \ 55 | $rootfs/home \ 56 | $rootfs/root \ 57 | $rootfs/lib \ 58 | $rootfs/lib64" 59 | 60 | mkdir -p $tree 61 | if [ $? -ne 0 ]; then 62 | return 1 63 | fi 64 | 65 | ln -s /run $rootfs/var/run 66 | if [ $? -ne 0 ]; then 67 | return 1 68 | fi 69 | 70 | return 0 71 | } 72 | 73 | configure_sshd() 74 | { 75 | rootfs=$1 76 | 77 | cat < $rootfs/etc/passwd 78 | root:x:0:0:root:/root:/bin/bash 79 | sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 80 | EOF 81 | 82 | cat < $rootfs/etc/group 83 | root:x:0:root 84 | sshd:x:74: 85 | EOF 86 | 87 | ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key 88 | ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key 89 | 90 | # by default setup root password with no password 91 | cat < $rootfs/etc/ssh/sshd_config 92 | Port 22 93 | Protocol 2 94 | HostKey /etc/ssh/ssh_host_rsa_key 95 | HostKey /etc/ssh/ssh_host_dsa_key 96 | UsePrivilegeSeparation yes 97 | SyslogFacility AUTH 98 | LogLevel INFO 99 | LoginGraceTime 120 100 | PermitRootLogin yes 101 | StrictModes yes 102 | PubkeyAuthentication yes 103 | IgnoreRhosts yes 104 | HostbasedAuthentication no 105 | PermitEmptyPasswords yes 106 | ChallengeResponseAuthentication no 107 | EOF 108 | 109 | if [ -n "$auth_key" -a -f "$auth_key" ]; then 110 | u_path="/root/.ssh" 111 | root_u_path="$rootfs/$u_path" 112 | mkdir -p $root_u_path 113 | cp $auth_key "$root_u_path/authorized_keys" 114 | chown -R 0:0 "$rootfs/$u_path" 115 | chmod 700 "$rootfs/$u_path" 116 | echo "Inserted SSH public key from $auth_key into $rootfs/$u_path" 117 | fi 118 | 119 | return 0 120 | } 121 | 122 | copy_configuration() 123 | { 124 | path=$1 125 | rootfs=$2 126 | name=$3 127 | 128 | init_path=$(realpath --relative-to=/ $(readlink -f /sbin/init)) 129 | 130 | grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config 131 | cat <> $path/config 132 | lxc.uts.name = $name 133 | lxc.pty.max = 1024 134 | lxc.cap.drop = sys_module mac_admin mac_override sys_time 135 | 136 | # When using LXC with apparmor, uncomment the next line to run unconfined: 137 | #lxc.apparmor.profile = unconfined 138 | 139 | lxc.autodev = 1 140 | 141 | lxc.mount.entry = /lib lib none ro,bind 0 0 142 | lxc.mount.entry = /bin bin none ro,bind 0 0 143 | lxc.mount.entry = /usr usr none ro,bind 0 0 144 | lxc.mount.entry = /sbin sbin none ro,bind 0 0 145 | lxc.mount.entry = tmpfs run/sshd tmpfs mode=0644 0 0 146 | lxc.mount.entry = @LXCTEMPLATEDIR@/lxc-sshd $init_path none ro,bind 0 0 147 | lxc.mount.entry = /etc/init.d etc/init.d none ro,bind 0 0 148 | 149 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed 150 | EOF 151 | 152 | # Oracle Linux and Fedora need the following two bind mounted 153 | if [ -d /etc/sysconfig/network-scripts ]; then 154 | cat <> $path/config 155 | lxc.mount.entry = /etc/sysconfig/network-scripts etc/sysconfig/network-scripts none ro,bind 0 0 156 | EOF 157 | fi 158 | 159 | if [ -d /etc/rc.d ]; then 160 | cat <> $path/config 161 | lxc.mount.entry = /etc/rc.d etc/rc.d none ro,bind 0 0 162 | EOF 163 | fi 164 | 165 | # if no .ipv4 section in config, then have the container run dhcp 166 | grep -q "^lxc.net.0.ipv4.address" $path/config || touch $rootfs/run-dhcp 167 | 168 | if [ "$(uname -m)" = "x86_64" ]; then 169 | cat <> $path/config 170 | lxc.mount.entry = /lib64 lib64 none ro,bind 0 0 171 | EOF 172 | fi 173 | } 174 | 175 | usage() 176 | { 177 | cat < [--rootfs=] 179 | EOF 180 | return 0 181 | } 182 | 183 | check_for_cmd() 184 | { 185 | cmd_path=`type $1` 186 | if [ $? -ne 0 ]; then 187 | echo "The command '$1' $cmd_path is not accessible on the system" 188 | exit 1 189 | fi 190 | # we use cut instead of awk because awk is alternatives symlink on ubuntu 191 | # and /etc/alternatives isn't bind mounted 192 | cmd_path=`echo $cmd_path |cut -d ' ' -f 3` 193 | } 194 | 195 | options=$(getopt -o hp:n:S: -l help,rootfs:,path:,name:,auth-key: -- "$@") 196 | if [ $? -ne 0 ]; then 197 | usage $(basename $0) 198 | exit 1 199 | fi 200 | eval set -- "$options" 201 | 202 | while true 203 | do 204 | case "$1" in 205 | -h|--help) usage $0 && exit 0;; 206 | -p|--path) path=$2; shift 2;; 207 | --rootfs) rootfs=$2; shift 2;; 208 | -n|--name) name=$2; shift 2;; 209 | -S|--auth-key) auth_key=$2; shift 2;; 210 | --) shift 1; break ;; 211 | *) break ;; 212 | esac 213 | done 214 | 215 | if [ "$(id -u)" != "0" ]; then 216 | echo "This script should be run as 'root'" 217 | exit 1 218 | fi 219 | 220 | if [ $0 = "/sbin/init" ]; then 221 | 222 | PATH="$PATH:/bin:/sbin:/usr/sbin" 223 | check_for_cmd @SBINDIR@/init.lxc 224 | check_for_cmd sshd 225 | sshd_path=$cmd_path 226 | 227 | # run dhcp? 228 | if [ -f /run-dhcp ]; then 229 | check_for_cmd dhclient 230 | check_for_cmd ifconfig 231 | touch /etc/fstab 232 | rm -f /dhclient.conf 233 | cat > /dhclient.conf << EOF 234 | send host-name = gethostname(); 235 | EOF 236 | ifconfig eth0 up 237 | dhclient eth0 -cf /dhclient.conf 238 | echo "Container IP address:" 239 | ifconfig eth0 |grep inet 240 | fi 241 | 242 | exec @SBINDIR@/init.lxc --name $name -- $sshd_path 243 | exit 1 244 | fi 245 | 246 | if [ -z "$path" ]; then 247 | echo "'path' parameter is required" 248 | exit 1 249 | fi 250 | 251 | # detect rootfs 252 | config="$path/config" 253 | if [ -z "$rootfs" ]; then 254 | if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then 255 | rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) 256 | else 257 | rootfs=$path/rootfs 258 | fi 259 | fi 260 | 261 | install_sshd $rootfs 262 | if [ $? -ne 0 ]; then 263 | echo "failed to install sshd's rootfs" 264 | exit 1 265 | fi 266 | 267 | configure_sshd $rootfs 268 | if [ $? -ne 0 ]; then 269 | echo "failed to configure sshd template" 270 | exit 1 271 | fi 272 | 273 | copy_configuration $path $rootfs $name 274 | if [ $? -ne 0 ]; then 275 | echo "failed to write configuration file" 276 | exit 1 277 | fi 278 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_INIT([lxc-templates], [3.0.4]) 5 | AM_INIT_AUTOMAKE 6 | 7 | # We need pkg-config 8 | PKG_PROG_PKG_CONFIG 9 | 10 | AC_CONFIG_SRCDIR([configure.ac]) 11 | # AC_CONFIG_AUX_DIR([config]) 12 | # AC_CONFIG_HEADERS([src/config.h]) 13 | # AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability subdir-objects]) 14 | AC_CANONICAL_HOST 15 | # AM_PROG_CC_C_O 16 | AC_GNU_SOURCE 17 | 18 | # Detect the distribution. This is used for the default configuration and 19 | # for some distro-specific build options. 20 | AC_MSG_CHECKING([host distribution]) 21 | AC_ARG_WITH(distro, AS_HELP_STRING([--with-distro=DISTRO], [Specify the Linux distribution to target: One of redhat, oracle, centos, fedora, suse, gentoo, debian, devuan, arch, slackware, plamo, paldo, openmandriva, pardus, sparclinux, altlinux.])) 22 | if type lsb_release >/dev/null 2>&1 && test "z$with_distro" = "z"; then 23 | with_distro=`lsb_release -is` 24 | fi 25 | if test "z$with_distro" = "z"; then 26 | AC_CHECK_FILE(/etc/redhat-release,with_distro="redhat") 27 | AC_CHECK_FILE(/etc/oracle-release,with_distro="oracle") 28 | AC_CHECK_FILE(/etc/sparclinux-release,with_distro="sparclinux") 29 | AC_CHECK_FILE(/etc/centos-release,with_distro="centos") 30 | AC_CHECK_FILE(/etc/fedora-release,with_distro="fedora") 31 | AC_CHECK_FILE(/etc/SuSE-release,with_distro="suse") 32 | AC_CHECK_FILE(/etc/gentoo-release,with_distro="gentoo") 33 | AC_CHECK_FILE(/etc/debian_version,with_distro="debian") 34 | AC_CHECK_FILE(/etc/arch-release,with_distro="arch") 35 | AC_CHECK_FILE(/etc/slackware-version,with_distro="slackware") 36 | AC_CHECK_FILE(/etc/plamo-version,with_distro="plamo") 37 | AC_CHECK_FILE(/etc/frugalware-release,with_distro="frugalware") 38 | AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva") 39 | AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva") 40 | AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus") 41 | AC_CHECK_FILE(/etc/altlinux-release,with_distro="altlinux") 42 | AC_CHECK_FILE(/etc/pld-release,with_distro="pld") 43 | fi 44 | with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'` 45 | 46 | if test "z$with_distro" = "zforsparc"; then 47 | with_distro="sparclinux" 48 | fi 49 | 50 | if test "z$with_distro" = "z"; then 51 | with_distro="unknown" 52 | fi 53 | case $with_distro in 54 | ubuntu|raspbian) 55 | distrosysconf="$sysconfdir/default" 56 | ;; 57 | redhat|centos|fedora|oracle|oracleserver|sparclinux|altlinux|suse|opensuse*|plamo|pld) 58 | distrosysconf="$sysconfdir/sysconfig" 59 | ;; 60 | *) 61 | distrosysconf="$sysconfdir/default" 62 | ;; 63 | esac 64 | AC_MSG_RESULT([$with_distro]) 65 | AM_CONDITIONAL([HAVE_DEBIAN], [test x"$with_distro" = "xdebian" -o x"$with_distro" = "xubuntu" -o x"$with_distro" = "xraspbian"]) 66 | AM_CONDITIONAL([DISTRO_UBUNTU], [test "x$with_distro" = "xubuntu"]) 67 | 68 | AC_CONFIG_LINKS([config/etc/default.conf:config/etc/${distroconf}]) 69 | 70 | # Not in older autoconf versions 71 | # AS_VAR_COPY(DEST, SOURCE) 72 | # ------------------------- 73 | # Set the polymorphic shell variable DEST to the contents of the polymorphic 74 | # shell variable SOURCE. 75 | m4_ifdef([AS_VAR_COPY], [], 76 | [AC_DEFUN([AS_VAR_COPY], 77 | [AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])]) 78 | ]) 79 | 80 | dnl PKG_CHECK_VAR was introduced with pkg-config 0.28 81 | m4_ifdef([PKG_CHECK_VAR], [], 82 | [AC_DEFUN([PKG_CHECK_VAR], 83 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 84 | AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl 85 | _PKG_CONFIG([$1], [variable="][$3]["], [$2]) 86 | AS_VAR_COPY([$1], [pkg_cv_][$1]) 87 | AS_VAR_IF([$1], [""], [$5], [$4])dnl 88 | ])# PKG_CHECK_VAR 89 | ]) 90 | 91 | # Allow overriding the default runtime dir (/run) 92 | AC_ARG_WITH([runtime-path], 93 | [AC_HELP_STRING( 94 | [--with-runtime-path=dir], 95 | [runtime directory (default: /run)] 96 | )], [], [with_runtime_path=['/run']]) 97 | 98 | # LXC container path, where the containers are actually stored 99 | # This is overridden by an entry in the file called LXCCONF 100 | # (i.e. /etc/lxc/lxc.conf) 101 | AC_ARG_WITH([config-path], 102 | [AC_HELP_STRING( 103 | [--with-config-path=dir], 104 | [lxc configuration repository path] 105 | )], [], [with_config_path=['${localstatedir}/lib/lxc']]) 106 | 107 | # The path of the global lxc configuration file. 108 | AC_ARG_WITH([global-conf], 109 | [AC_HELP_STRING( 110 | [--with-global-conf=dir], 111 | [global lxc configuration file] 112 | )], [], [with_global_conf=['${sysconfdir}/lxc/lxc.conf']]) 113 | 114 | # Rootfs path, where the container mount structure is assembled 115 | AC_ARG_WITH([rootfs-path], 116 | [AC_HELP_STRING( 117 | [--with-rootfs-path=dir], 118 | [lxc rootfs mount point] 119 | )], [], [with_rootfs_path=['${libdir}/lxc/rootfs']]) 120 | 121 | # Expand some useful variables 122 | AS_AC_EXPAND(PREFIX, "$prefix") 123 | AS_AC_EXPAND(LIBDIR, "$libdir") 124 | AS_AC_EXPAND(BINDIR, "$bindir") 125 | AS_AC_EXPAND(SBINDIR, "$sbindir") 126 | AS_AC_EXPAND(LIBEXECDIR, "$libexecdir") 127 | AS_AC_EXPAND(INCLUDEDIR, "$includedir") 128 | AS_AC_EXPAND(SYSCONFDIR, "$sysconfdir") 129 | AS_AC_EXPAND(LXC_DEFAULT_CONFIG, "$sysconfdir/lxc/default.conf") 130 | AS_AC_EXPAND(DATADIR, "$datadir") 131 | AS_AC_EXPAND(LOCALSTATEDIR, "$localstatedir") 132 | AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date --utc --date=@${SOURCE_DATE_EPOCH:-$(date +%s)} '+%Y-%m-%d')") 133 | AS_AC_EXPAND(LXCPATH, "$with_config_path") 134 | AS_AC_EXPAND(LXC_GLOBAL_CONF, "$with_global_conf") 135 | AS_AC_EXPAND(LXC_USERNIC_CONF, "$with_usernic_conf") 136 | AS_AC_EXPAND(LXC_USERNIC_DB, "$with_usernic_db") 137 | AS_AC_EXPAND(LXC_DISTRO_SYSCONF, "$distrosysconf") 138 | AS_AC_EXPAND(LXCROOTFSMOUNT, "$with_rootfs_path") 139 | AS_AC_EXPAND(LXCTEMPLATEDIR, "$datadir/lxc/templates") 140 | AS_AC_EXPAND(LXCTEMPLATECONFIG, "$datadir/lxc/config") 141 | AS_AC_EXPAND(LXCHOOKDIR, "$datadir/lxc/hooks") 142 | AS_AC_EXPAND(LXCBINHOOKDIR, "$libexecdir/lxc/hooks") 143 | AS_AC_EXPAND(LXCINITDIR, "$libexecdir") 144 | AS_AC_EXPAND(RUNTIME_PATH, "$with_runtime_path") 145 | 146 | # Check for some standard binaries 147 | AC_PROG_SED 148 | 149 | # Files requiring some variable expansion 150 | AC_CONFIG_FILES([ 151 | Makefile 152 | 153 | config/Makefile 154 | config/alpine.common.conf 155 | config/alpine.userns.conf 156 | config/archlinux.common.conf 157 | config/archlinux.userns.conf 158 | config/centos.common.conf 159 | config/centos.userns.conf 160 | config/debian.common.conf 161 | config/debian.userns.conf 162 | config/devuan.common.conf 163 | config/devuan.userns.conf 164 | config/fedora.common.conf 165 | config/fedora.userns.conf 166 | config/gentoo.common.conf 167 | config/gentoo.moresecure.conf 168 | config/gentoo.userns.conf 169 | config/kali.common.conf 170 | config/kali.userns.conf 171 | config/opensuse.common.conf 172 | config/opensuse.userns.conf 173 | config/oracle.common.conf 174 | config/oracle.userns.conf 175 | config/plamo.common.conf 176 | config/plamo.userns.conf 177 | config/slackware.common.conf 178 | config/slackware.userns.conf 179 | config/ubuntu-cloud.common.conf 180 | config/ubuntu-cloud.lucid.conf 181 | config/ubuntu-cloud.userns.conf 182 | config/ubuntu.common.conf 183 | config/ubuntu.lucid.conf 184 | config/ubuntu.userns.conf 185 | config/openwrt.common.conf 186 | config/sparclinux.common.conf 187 | config/sparclinux.userns.conf 188 | config/voidlinux.common.conf 189 | config/voidlinux.userns.conf 190 | config/sabayon.common.conf 191 | config/sabayon.userns.conf 192 | 193 | templates/Makefile 194 | templates/lxc-alpine 195 | templates/lxc-altlinux 196 | templates/lxc-anolis 197 | templates/lxc-archlinux 198 | templates/lxc-centos 199 | templates/lxc-cirros 200 | templates/lxc-debian 201 | templates/lxc-devuan 202 | templates/lxc-fedora 203 | templates/lxc-fedora-legacy 204 | templates/lxc-gentoo 205 | templates/lxc-kali 206 | templates/lxc-openeuler 207 | templates/lxc-openmandriva 208 | templates/lxc-opensuse 209 | templates/lxc-oracle 210 | templates/lxc-plamo 211 | templates/lxc-pld 212 | templates/lxc-slackware 213 | templates/lxc-sshd 214 | templates/lxc-ubuntu 215 | templates/lxc-ubuntu-cloud 216 | templates/lxc-sparclinux 217 | templates/lxc-voidlinux 218 | templates/lxc-sabayon 219 | ], 220 | if test "${ac_file##templates/lxc-}" != "${ac_file}"; then chmod +x $ac_file; fi 221 | ) 222 | AC_CONFIG_COMMANDS([default],[[]],[[]]) 223 | AC_OUTPUT 224 | 225 | # Configuration overview 226 | cat << EOF 227 | 228 | ---------------------------- 229 | Environment: 230 | - distribution: $with_distro 231 | EOF 232 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 5 | 2006 Free Software Foundation, Inc. 6 | 7 | This file is free documentation; the Free Software Foundation gives 8 | unlimited permission to copy, distribute and modify it. 9 | 10 | Basic Installation 11 | ================== 12 | 13 | Briefly, the shell commands `./autogen.sh; ./configure; make; make install' 14 | should configure, build, and install this package. The following 15 | more-detailed instructions are generic; see the `README' file for 16 | instructions specific to this package. 17 | 18 | The `configure' shell script attempts to guess correct values for 19 | various system-dependent variables used during compilation. It uses 20 | those values to create a `Makefile' in each directory of the package. 21 | It may also create one or more `.h' files containing system-dependent 22 | definitions. Finally, it creates a shell script `config.status' that 23 | you can run in the future to recreate the current configuration, and a 24 | file `config.log' containing compiler output (useful mainly for 25 | debugging `configure'). 26 | 27 | It can also use an optional file (typically called `config.cache' 28 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 29 | the results of its tests to speed up reconfiguring. Caching is 30 | disabled by default to prevent problems with accidental use of stale 31 | cache files. 32 | 33 | If you need to do unusual things to compile the package, please try 34 | to figure out how `configure' could check whether to do them, and mail 35 | diffs or instructions to the address given in the `README' so they can 36 | be considered for the next release. If you are using the cache, and at 37 | some point `config.cache' contains results you don't want to keep, you 38 | may remove or edit it. 39 | 40 | The file `configure.ac' (or `configure.in') is used to create 41 | `configure' by a program called `autoconf'. You need `configure.ac' if 42 | you want to change it or regenerate `configure' using a newer version 43 | of `autoconf'. 44 | 45 | The simplest way to compile this package is: 46 | 47 | 0. If the sources are not coming from a package maintainer and the 48 | 'configure' file does not exist, you should run './autogen.sh' in 49 | the directory containing the package's source code in order to 50 | generate the 'configure' file from the 'configure.ac' file. 51 | 52 | 1. `cd' to the directory containing the package's source code and type 53 | `./configure' to configure the package for your system. 54 | 55 | Running `configure' might take a while. While running, it prints 56 | some messages telling which features it is checking for. 57 | 58 | 2. Type `make' to compile the package. 59 | 60 | 3. Optionally, type `make check' to run any self-tests that come with 61 | the package. 62 | 63 | 4. Type `make install' to install the programs and any data files and 64 | documentation. 65 | 66 | 5. You can remove the program binaries and object files from the 67 | source code directory by typing `make clean'. To also remove the 68 | files that `configure' created (so you can compile the package for 69 | a different kind of computer), type `make distclean'. There is 70 | also a `make maintainer-clean' target, but that is intended mainly 71 | for the package's developers. If you use it, you may have to get 72 | all sorts of other programs in order to regenerate files that came 73 | with the distribution. 74 | 75 | Compilers and Options 76 | ===================== 77 | 78 | Some systems require unusual options for compilation or linking that the 79 | `configure' script does not know about. Run `./configure --help' for 80 | details on some of the pertinent environment variables. 81 | 82 | You can give `configure' initial values for configuration parameters 83 | by setting variables in the command line or in the environment. Here 84 | is an example: 85 | 86 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 87 | 88 | *Note Defining Variables::, for more details. 89 | 90 | Compiling For Multiple Architectures 91 | ==================================== 92 | 93 | You can compile the package for more than one kind of computer at the 94 | same time, by placing the object files for each architecture in their 95 | own directory. To do this, you can use GNU `make'. `cd' to the 96 | directory where you want the object files and executables to go and run 97 | the `configure' script. `configure' automatically checks for the 98 | source code in the directory that `configure' is in and in `..'. 99 | 100 | With a non-GNU `make', it is safer to compile the package for one 101 | architecture at a time in the source code directory. After you have 102 | installed the package for one architecture, use `make distclean' before 103 | reconfiguring for another architecture. 104 | 105 | Installation Names 106 | ================== 107 | 108 | By default, `make install' installs the package's commands under 109 | `/usr/local/bin', include files under `/usr/local/include', etc. You 110 | can specify an installation prefix other than `/usr/local' by giving 111 | `configure' the option `--prefix=PREFIX'. 112 | 113 | You can specify separate installation prefixes for 114 | architecture-specific files and architecture-independent files. If you 115 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 116 | PREFIX as the prefix for installing programs and libraries. 117 | Documentation and other data files still use the regular prefix. 118 | 119 | In addition, if you use an unusual directory layout you can give 120 | options like `--bindir=DIR' to specify different values for particular 121 | kinds of files. Run `configure --help' for a list of the directories 122 | you can set and what kinds of files go in them. 123 | 124 | If the package supports it, you can cause programs to be installed 125 | with an extra prefix or suffix on their names by giving `configure' the 126 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 127 | 128 | Optional Features 129 | ================= 130 | 131 | Some packages pay attention to `--enable-FEATURE' options to 132 | `configure', where FEATURE indicates an optional part of the package. 133 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 134 | is something like `gnu-as' or `x' (for the X Window System). The 135 | `README' should mention any `--enable-' and `--with-' options that the 136 | package recognizes. 137 | 138 | For packages that use the X Window System, `configure' can usually 139 | find the X include and library files automatically, but if it doesn't, 140 | you can use the `configure' options `--x-includes=DIR' and 141 | `--x-libraries=DIR' to specify their locations. 142 | 143 | Specifying the System Type 144 | ========================== 145 | 146 | There may be some features `configure' cannot figure out automatically, 147 | but needs to determine by the type of machine the package will run on. 148 | Usually, assuming the package is built to be run on the _same_ 149 | architectures, `configure' can figure that out, but if it prints a 150 | message saying it cannot guess the machine type, give it the 151 | `--build=TYPE' option. TYPE can either be a short name for the system 152 | type, such as `sun4', or a canonical name which has the form: 153 | 154 | CPU-COMPANY-SYSTEM 155 | 156 | where SYSTEM can have one of these forms: 157 | 158 | OS KERNEL-OS 159 | 160 | See the file `config.sub' for the possible values of each field. If 161 | `config.sub' isn't included in this package, then this package doesn't 162 | need to know the machine type. 163 | 164 | If you are _building_ compiler tools for cross-compiling, you should 165 | use the option `--target=TYPE' to select the type of system they will 166 | produce code for. 167 | 168 | If you want to _use_ a cross compiler, that generates code for a 169 | platform different from the build platform, you should specify the 170 | "host" platform (i.e., that on which the generated programs will 171 | eventually be run) with `--host=TYPE'. 172 | 173 | Sharing Defaults 174 | ================ 175 | 176 | If you want to set default values for `configure' scripts to share, you 177 | can create a site shell script called `config.site' that gives default 178 | values for variables like `CC', `cache_file', and `prefix'. 179 | `configure' looks for `PREFIX/share/config.site' if it exists, then 180 | `PREFIX/etc/config.site' if it exists. Or, you can set the 181 | `CONFIG_SITE' environment variable to the location of the site script. 182 | A warning: not all `configure' scripts look for a site script. 183 | 184 | Defining Variables 185 | ================== 186 | 187 | Variables not defined in a site shell script can be set in the 188 | environment passed to `configure'. However, some packages may run 189 | configure again during the build, and the customized values of these 190 | variables may be lost. In order to avoid this problem, you should set 191 | them in the `configure' command line, using `VAR=value'. For example: 192 | 193 | ./configure CC=/usr/local2/bin/gcc 194 | 195 | causes the specified `gcc' to be used as the C compiler (unless it is 196 | overridden in the site shell script). 197 | 198 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 199 | an Autoconf bug. Until the bug is fixed you can use this workaround: 200 | 201 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 202 | 203 | `configure' Invocation 204 | ====================== 205 | 206 | `configure' recognizes the following options to control how it operates. 207 | 208 | `--help' 209 | `-h' 210 | Print a summary of the options to `configure', and exit. 211 | 212 | `--version' 213 | `-V' 214 | Print the version of Autoconf used to generate the `configure' 215 | script, and exit. 216 | 217 | `--cache-file=FILE' 218 | Enable the cache: use and save the results of the tests in FILE, 219 | traditionally `config.cache'. FILE defaults to `/dev/null' to 220 | disable caching. 221 | 222 | `--config-cache' 223 | `-C' 224 | Alias for `--cache-file=config.cache'. 225 | 226 | `--quiet' 227 | `--silent' 228 | `-q' 229 | Do not print messages saying which checks are being made. To 230 | suppress all normal output, redirect it to `/dev/null' (any error 231 | messages will still be shown). 232 | 233 | `--srcdir=DIR' 234 | Look for the package's source code in directory DIR. Usually 235 | `configure' can determine that directory automatically. 236 | 237 | `configure' also accepts some other, not widely useful, options. Run 238 | `configure --help' for more details. 239 | 240 | -------------------------------------------------------------------------------- /templates/lxc-cirros.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # template script for generating ubuntu container for LXC 4 | # 5 | # This script consolidates and extends the existing lxc ubuntu scripts 6 | # 7 | 8 | # Copyright © 2013 Canonical Ltd. 9 | # Author: Scott Moser 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License version 2, as 13 | # published by the Free Software Foundation. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License along 21 | # with this program; if not, write to the Free Software Foundation, Inc., 22 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | 24 | # Detect use under userns (unsupported) 25 | # Make sure the usual locations are in PATH 26 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 27 | 28 | VERBOSITY=0 29 | DOWNLOAD_URL="http://download.cirros-cloud.net/" 30 | 31 | UNAME_M=$(uname -m) 32 | ARCHES=( i386 x86_64 amd64 arm ) 33 | STREAMS=( released devel ) 34 | SOURCES=( nocloud none ) 35 | BUILD="standard" 36 | LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" 37 | 38 | LXC_MAPPED_GID= 39 | LXC_MAPPED_UID= 40 | 41 | DEF_VERSION="released" 42 | DEF_SOURCE="nocloud" 43 | case "${UNAME_M}" in 44 | i?86) DEF_ARCH="i386";; 45 | x86_64) DEF_ARCH="x86_64";; 46 | arm*) DEF_ARCH="arm";; 47 | *) DEF_ARCH="i386";; 48 | esac 49 | 50 | am_in_userns() { 51 | [ -e /proc/self/uid_map ] || { echo no; return; } 52 | [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; } 53 | line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map) 54 | [ "$line" = "0 0 4294967295" ] && { echo no; return; } 55 | echo yes 56 | } 57 | 58 | in_userns=0 59 | [ $(am_in_userns) = "yes" ] && in_userns=1 60 | 61 | # Allow the cache base to be set by environment variable 62 | if [ $(id -u) -eq 0 ]; then 63 | CACHE_D=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc/cirros"} 64 | else 65 | CACHE_D=${LXC_CACHE_PATH:-"$HOME/.cache/lxc/cirros"} 66 | fi 67 | 68 | error() { echo "$@" 1>&2; } 69 | inargs() { 70 | local needle="$1" x="" 71 | shift 72 | for x in "$@"; do 73 | [ "$needle" = "$x" ] && return 0 74 | done 75 | return 1 76 | } 77 | 78 | Usage() { 79 | cat <&2; [ $# -eq 0 ] || error "$@"; return 1; } 98 | 99 | debug() { 100 | local level=${1}; shift; 101 | [ "${level}" -gt "${VERBOSITY}" ] && return 102 | error "${@}" 103 | } 104 | jsondict() { 105 | local k="" v="" ret="{" 106 | for arg in "$@"; do 107 | k="${arg%%=*}" 108 | v="${arg#*=}" 109 | ret="${ret} \"${k}\": \"$v\"," 110 | done 111 | ret="${ret%,} }" 112 | echo "$ret" 113 | } 114 | 115 | copy_configuration() 116 | { 117 | local path=$1 rootfs=$2 name=$3 arch=$4 release=$5 118 | cat >> "$path/config" <> $path/config 165 | fi 166 | 167 | } 168 | 169 | insert_ds_nocloud() { 170 | local root_d="$1" authkey="$2" udfile="$3" 171 | local sdir="$root_d/var/lib/cloud/seed/nocloud" 172 | 173 | mkdir -p "$sdir" || 174 | { error "failed to make datasource dir $sdir"; return 1; } 175 | rm -f "$sdir/meta-data" "$sdir/user-data" || 176 | { error "failed to clean old data from $sdir"; return 1; } 177 | 178 | iid="iid-local01" 179 | jsondict "instance-id=$iid" \ 180 | ${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" || 181 | { error "failed to write metadata to $sdir/meta-data"; return 1; } 182 | 183 | if [ -n "$udfile" ]; then 184 | cat "$udfile" > "$sdir/user-data" || 185 | { error "failed to write user-data to $sdir"; return 1; } 186 | else 187 | rm -f "$sdir/user-data" 188 | fi 189 | } 190 | 191 | insert_ds() { 192 | local dstype="$1" root_d="$2" authkey="$3" udfile="$4" 193 | case "$dstype" in 194 | nocloud) insert_ds_nocloud "$root_d" "$authkey" "$udfile" 195 | esac 196 | } 197 | 198 | extract_rootfs() { 199 | local tarball="$1" rootfs_d="$2" 200 | mkdir -p "${rootfs_d}" || 201 | { error "failed to make rootfs dir ${rootfs_d}"; return 1; } 202 | 203 | if [ $in_userns -eq 1 ]; then 204 | tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" || 205 | { error "failed to populate ${rootfs_d}"; return 1; } 206 | else 207 | tar -C "${rootfs_d}" -Sxzf "${tarball}" || 208 | { error "failed to populate ${rootfs_d}"; return 1; } 209 | fi 210 | return 0 211 | } 212 | 213 | download_tarball() { 214 | local arch="$1" ver="$2" cached="$3" baseurl="$4" 215 | local out="" outd="" file="" dlpath="" 216 | file="cirros-$ver-$arch-lxc.tar.gz" 217 | dlpath="$ver/$file" 218 | outd="${cached}/${dlpath%/*}" 219 | if [ -f "$cached/$dlpath" ]; then 220 | _RET="$cached/$dlpath" 221 | return 0 222 | fi 223 | 224 | mkdir -p "${outd}" || 225 | { error "failed to create ${outd}"; return 1; } 226 | 227 | debug 1 "downloading ${baseurl%/}/$dlpath" to "${cached}/$dlpath" 228 | wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" && 229 | mv "$cached/$dlpath.$$" "$cached/$dlpath" || { 230 | rm -f "$cached/$dlpath.$$"; 231 | error "failed to download $dlpath"; 232 | return 1; 233 | } 234 | _RET="$cached/$dlpath" 235 | } 236 | 237 | create_main() { 238 | local short_opts="a:hn:p:S:uvV" 239 | local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:" 240 | local getopt_out="" 241 | getopt_out=$(getopt --name "${0##*/}" \ 242 | --options "${short_opts}" --long "${long_opts}" -- "$@") && 243 | eval set -- "${getopt_out}" || 244 | { bad_Usage; return; } 245 | 246 | local arch="${DEF_ARCH}" dsource="${DEF_SOURCE}" version="${DEF_VERSION}" 247 | local authkey_f="" authkeys="" userdata_f="" path="" tarball="" 248 | local cur="" next="" 249 | local rootfs_d="" 250 | 251 | while [ $# -ne 0 ]; do 252 | cur=$1; next=$2; 253 | case "$cur" in 254 | -a|--arch) arch="$next"; shift;; 255 | -h|--help) Usage ; return 0;; 256 | -n|--name) name="$next"; shift;; 257 | -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));; 258 | -S|--auth-key) authkey_f="$next"; shift;; 259 | -p|--path) path=$next; shift;; 260 | -v|--version) version=$next; shift;; 261 | -u|--userdata) userdata_f="$next"; shift;; 262 | --tarball) tarball="$next"; shift;; 263 | --source) dsource="$next"; shift;; 264 | --rootfs) rootfs_d="$next"; shift;; 265 | --mapped-uid) LXC_MAPPED_UID=$next; shift;; 266 | --mapped-gid) LXC_MAPPED_GID=$next; shift;; 267 | --) shift; break;; 268 | esac 269 | shift; 270 | done 271 | 272 | [ -n "$rootfs_d" ] || rootfs_d="$path/rootfs" 273 | [ $# -eq 0 ] || { bad_Usage "unexpected arguments: $*"; return; } 274 | [ -n "$path" ] || { error "'path' parameter is required"; return 1; } 275 | 276 | if [ "$(id -u)" != "0" ]; then 277 | { error "must be run as root"; return 1; } 278 | fi 279 | 280 | case "$arch" in 281 | i?86) arch="i386";; 282 | amd64) arch="x86_64";; 283 | esac 284 | 285 | inargs "$arch" "${ARCHES[@]}" || 286 | { error "bad arch '$arch'. allowed: ${ARCHES[*]}"; return 1; } 287 | 288 | inargs "$dsource" "${SOURCES[@]}" || 289 | { error "bad source '$dsource'. allowed: ${SOURCES[*]}"; return 1; } 290 | 291 | if [ "$dsource" = "none" ] && [ -n "$userdata_f" -o -n "$authkey_f" ]; then 292 | error "userdata and authkey are incompatible with --source=none"; 293 | return 1; 294 | fi 295 | 296 | if [ -n "$authkey_f" ]; then 297 | if [ ! -f "$authkey_f" ]; then 298 | error "--auth-key=${authkey_f} must reference a file" 299 | return 1 300 | fi 301 | authkeys=$(cat "$authkey_f") || 302 | { error "failed to read ${authkey_f}"; return 1; } 303 | fi 304 | 305 | if [ -n "$userdata_f" -a ! -f "${userdata_f}" ]; then 306 | error "${userdata_f}: --userdata arg not a file" 307 | return 1 308 | fi 309 | 310 | if [ -z "$tarball" ]; then 311 | if inargs "$version" "${STREAMS[@]}"; then 312 | out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") || 313 | { error "failed to convert 'version=$version'"; return 1; } 314 | version="$out" 315 | fi 316 | download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" || 317 | return 318 | tarball="$_RET" 319 | fi 320 | 321 | extract_rootfs "${tarball}" "${rootfs_d}" || return 322 | 323 | if [ "$version" = "0.3.2~pre1" ]; then 324 | debug 1 "fixing console for lxc and '$version'" 325 | sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \ 326 | "$rootfs_d/etc/inittab" || 327 | { error "failed to fix console entry for $version"; return 1; } 328 | fi 329 | 330 | if [ "$dsource" != "none" ]; then 331 | insert_ds "$dsource" "$path/rootfs" "$authkeys" "$userdata_f" || { 332 | error "failed to insert userdata to $path/rootfs" 333 | return 1 334 | } 335 | fi 336 | 337 | copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release" 338 | return 339 | } 340 | 341 | create_main "$@" 342 | 343 | # vi: ts=4 expandtab 344 | -------------------------------------------------------------------------------- /templates/lxc-archlinux.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # template script for generating Arch Linux container for LXC 5 | # 6 | 7 | # 8 | # lxc: linux Container library 9 | 10 | # Authors: 11 | # Alexander Vladimirov 12 | # John Lane 13 | 14 | # This library is free software; you can redistribute it and/or 15 | # modify it under the terms of the GNU Lesser General Public 16 | # License as published by the Free Software Foundation; either 17 | # version 2.1 of the License, or (at your option) any later version. 18 | 19 | # This library is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | # Lesser General Public License for more details. 23 | 24 | # You should have received a copy of the GNU Lesser General Public 25 | # License along with this library; if not, write to the Free Software 26 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | # Detect use under userns (unsupported) 29 | for arg in "$@"; do 30 | [ "$arg" = "--" ] && break 31 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 32 | echo "This template can't be used for unprivileged containers." 1>&2 33 | echo "You may want to try the \"download\" template instead." 1>&2 34 | exit 1 35 | fi 36 | done 37 | 38 | # Make sure the usual locations are in PATH 39 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 40 | 41 | # defaults 42 | arch=$(uname -m) 43 | default_path="@LXCPATH@" 44 | default_locale="en_US.UTF-8" 45 | pacman_config="/etc/pacman.conf" 46 | common_config="@LXCTEMPLATECONFIG@/common.conf" 47 | shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf" 48 | 49 | # by default, install 'base' except the kernel 50 | pkg_blacklist="linux" 51 | base_packages=("systemd-sysvcompat") 52 | for pkg in $(pacman -Sqg base); do 53 | [ "${pkg_blacklist#*$pkg}" = "$pkg_blacklist" ] && base_packages+=($pkg) 54 | done 55 | declare -a additional_packages 56 | 57 | # split comma-separated string into an array 58 | # ${1} - string to split 59 | # ${2} - separator (default is ",") 60 | # ${result} - result value on success 61 | split_string() { 62 | local ifs=${IFS} 63 | IFS="${2:-,}" 64 | read -a result < <(echo "${1}") 65 | IFS=${ifs} 66 | return 0 67 | } 68 | 69 | [ -f /etc/arch-release ] && is_arch=true 70 | 71 | # Arch-specific preconfiguration for container 72 | configure_arch() { 73 | # on ArchLinux, read defaults from host systemd configuration 74 | if [ "${is_arch}" ]; then 75 | cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/" 76 | else 77 | echo "LANG=${default_locale}" > "${rootfs_path}/etc/locale.conf" 78 | if [ -e "${rootfs_path}/etc/locale.gen" ]; then 79 | sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen" 80 | if [ ! "${default_locale}" = "en_US.UTF-8" ]; then 81 | echo "${default_locale} ${default_locale##*.}" >> \ 82 | "${rootfs_path}/etc/locale.gen" 83 | fi 84 | fi 85 | fi 86 | 87 | # hostname and nameservers 88 | echo "${name}" > "${rootfs_path}/etc/hostname" 89 | 90 | # network configuration 91 | cat > "${rootfs_path}/etc/systemd/network/eth0.network" << EOF 92 | [Match] 93 | Name=eth0 94 | 95 | [Network] 96 | DHCP=ipv4 97 | EOF 98 | 99 | # chroot and configure system 100 | arch-chroot "${rootfs_path}" /bin/bash -s << EOF 101 | mkdir /run/lock 102 | locale-gen 103 | # set default boot target 104 | ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target 105 | # override getty@.service for container ttys 106 | sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ 107 | -e 's/After=dev-%i.device/After=/' \ 108 | < /lib/systemd/system/getty\@.service \ 109 | > /etc/systemd/system/getty\@.service 110 | # fix systemd-sysctl service 111 | sed -e 's/^ConditionPathIsReadWrite=\/proc\/sys\/$/ConditionPathIsReadWrite=\/proc\/sys\/net\//' \ 112 | -e 's/^ExecStart=\/usr\/lib\/systemd\/systemd-sysctl$/ExecStart=\/usr\/lib\/systemd\/systemd-sysctl --prefix net/' \ 113 | -i /usr/lib/systemd/system/systemd-sysctl.service 114 | # initialize pacman keyring 115 | pacman-key --init 116 | pacman-key --populate archlinux 117 | 118 | # enable networkd 119 | systemctl enable systemd-networkd 120 | systemctl enable systemd-resolved 121 | ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf 122 | EOF 123 | # enable getty on active ttys 124 | local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.max" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") 125 | local devttydir=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.dir" | head -n1 | cut -d= -f2 | tr -d "[:blank:]") 126 | local devtty="" 127 | # bind getty instances to /dev//tty* if lxc.tty.dir is set 128 | [ -n "${devttydir}" ] && devtty="${devttydir}-" 129 | if [ ${nttys:-0} -gt 1 ]; then 130 | ( cd "${rootfs_path}/etc/systemd/system/getty.target.wants" 131 | for i in $(seq 1 $nttys); do ln -sf "../getty@.service" "getty@${devtty}tty${i}.service"; done ) 132 | fi 133 | # update securetty to allow console login if devttydir is set 134 | if [ -n "${devttydir}" ]; then 135 | for i in $(seq 1 ${nttys:-1}); do 136 | echo "${devttydir}/tty${i}" >> "${rootfs_path}/etc/securetty" 137 | done 138 | fi 139 | [ -n "${devttydir}" ] && echo "${devttydir}/console" >> "${rootfs_path}/etc/securetty" 140 | # Arch default configuration allows only tty1-6 for login 141 | [ ${nttys:-0} -gt 6 ] && echo \ 142 | "You may want to modify container's /etc/securetty \ 143 | file to allow root logins on tty7 and higher" 144 | return 0 145 | } 146 | 147 | # write container configuration files 148 | copy_configuration() { 149 | mkdir -p "${config_path}" 150 | local config="${config_path}/config" 151 | echo "lxc.uts.name = ${name}" >> "${config}" 152 | grep -q "^lxc.arch" "${config}" 2>/dev/null \ 153 | || echo "lxc.arch = ${arch}" >> "${config}" 154 | grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \ 155 | || echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}" 156 | [ -e "${shared_config}" ] \ 157 | && echo "lxc.include = ${shared_config}" >> "${config}" 158 | if [ $? -ne 0 ]; then 159 | echo "Failed to configure container" 160 | return 1 161 | fi 162 | return 0 163 | } 164 | 165 | # install packages within container chroot 166 | install_arch() { 167 | [ "${arch}" != "$(uname -m)" ] && different_arch=true 168 | 169 | if [ "${different_arch}" = "true" ]; then 170 | container_pacman_config=$(mktemp) 171 | container_mirrorlist=$(mktemp) 172 | sed -e "s:Architecture =.*:Architecture = ${arch}:g" \ 173 | -e "s:/etc/pacman.d/mirrorlist:${container_mirrorlist}:g" \ 174 | "${pacman_config}" > "${container_pacman_config}" 175 | sed -e "s:\(x86_64\|\$arch\):${arch}:g" \ 176 | /etc/pacman.d/mirrorlist > "${container_mirrorlist}" 177 | 178 | pacman_config="${container_pacman_config}" 179 | fi 180 | 181 | if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \ 182 | ${base_packages[@]}; then 183 | echo "Failed to install container packages" 184 | return 1 185 | fi 186 | 187 | if [ "${different_arch}" = "true" ]; then 188 | sed -i -e "s:Architecture =.*:Architecture = ${arch}:g" \ 189 | "${rootfs_path}"/etc/pacman.conf 190 | cp "${container_mirrorlist}" "${rootfs_path}"/etc/pacman.d/mirrorlist 191 | rm "${container_pacman_config}" "${container_mirrorlist}" 192 | fi 193 | 194 | [ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}" 195 | return 0 196 | } 197 | 198 | usage() { 199 | cat < [-p|--path=] [-a|--arch=] 202 | [-r|--root_password=] [-P|--packages=] 203 | [-e|--enable_units=unit1,unit2...] [-d|--disable_units=unit1,unit2...] 204 | [-c|--config=] [-h|--help] 205 | 206 | Mandatory args: 207 | -n,--name container name, used to as an identifier for that container from now on 208 | Optional args: 209 | -p,--path path to where the container rootfs will be created (${default_path}) 210 | --rootfs path for actual container rootfs, (${default_path}/rootfs) 211 | -P,--packages preinstall additional packages, comma-separated list 212 | -e,--enable_units enable systemd services, comma-separated list 213 | -d,--disable_units disable systemd services, comma-separated list 214 | -c,--config use specified pacman config when installing container packages 215 | -a,--arch use specified architecture instead of host's architecture 216 | -r,--root_password set container root password 217 | -h,--help print this help 218 | EOF 219 | return 0 220 | } 221 | 222 | options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}") 223 | if [ ${?} -ne 0 ]; then 224 | usage $(basename ${0}) 225 | exit 1 226 | fi 227 | eval set -- "${options}" 228 | 229 | while true 230 | do 231 | case "${1}" in 232 | -h|--help) usage ${0} && exit 0;; 233 | -p|--path) path=${2}; shift 2;; 234 | -n|--name) name=${2}; shift 2;; 235 | --rootfs) rootfs_path=${2}; shift 2;; 236 | -P|--packages) additional_packages=${2}; shift 2;; 237 | -e|--enable_units) enable_units=${2}; shift 2;; 238 | -d|--disable_units) disable_units=${2}; shift 2;; 239 | -c|--config) pacman_config=${2}; shift 2;; 240 | -a|--arch) arch=${2}; shift 2;; 241 | -r|--root_password) root_passwd=${2}; shift 2;; 242 | --) shift 1; break ;; 243 | *) break ;; 244 | esac 245 | done 246 | 247 | if [ -z "${name}" ]; then 248 | echo "missing required 'name' parameter" 249 | exit 1 250 | fi 251 | 252 | type pacman >/dev/null 2>&1 253 | if [ ${?} -ne 0 ]; then 254 | echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman" 255 | exit 1 256 | fi 257 | 258 | if [ -z "${path}" ]; then 259 | path="${default_path}/${name}" 260 | fi 261 | 262 | if [ "${EUID}" != "0" ]; then 263 | echo "This script should be run as 'root'" 264 | exit 1 265 | fi 266 | 267 | if [ -z "$rootfs_path" ]; then 268 | rootfs_path="${path}/rootfs" 269 | fi 270 | config_path="${path}" 271 | 272 | revert() { 273 | echo "Interrupted, cleaning up" 274 | lxc-destroy -n "${name}" 275 | rm -rf "${path}/${name}" 276 | rm -rf "${default_path}/${name}" 277 | exit 1 278 | } 279 | 280 | trap revert SIGHUP SIGINT SIGTERM 281 | 282 | copy_configuration 283 | if [ ${?} -ne 0 ]; then 284 | echo "failed to write configuration file" 285 | rm -rf "${config_path}" 286 | exit 1 287 | fi 288 | 289 | if [ ${#additional_packages[@]} -gt 0 ]; then 290 | split_string ${additional_packages} 291 | base_packages+=(${result[@]}) 292 | fi 293 | 294 | mkdir -p "${rootfs_path}" 295 | install_arch 296 | if [ ${?} -ne 0 ]; then 297 | echo "failed to install Arch Linux" 298 | rm -rf "${config_path}" "${path}" 299 | exit 1 300 | fi 301 | 302 | configure_arch 303 | if [ ${?} -ne 0 ]; then 304 | echo "failed to configure Arch Linux for a container" 305 | rm -rf "${config_path}" "${path}" 306 | exit 1 307 | fi 308 | 309 | if [ ${#enable_units[@]} -gt 0 ]; then 310 | split_string ${enable_units} 311 | for unit in ${result[@]}; do 312 | [ "${unit##*.}" = "service" ] || unit="${unit}.service" 313 | ln -s "/usr/lib/systemd/system/${unit}" \ 314 | "${rootfs_path}/etc/systemd/system/multi-user.target.wants/" 315 | done 316 | fi 317 | 318 | if [ ${#disable_units[@]} -gt 0 ]; then 319 | split_string ${disable_units} 320 | for unit in ${result[@]}; do 321 | [ "${unit##*.}" = "service" ] || unit="${unit}.service" 322 | ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}" 323 | done 324 | fi 325 | 326 | if [ -n "${root_passwd}" ]; then 327 | echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd 328 | fi 329 | 330 | cat << EOF 331 | Arch Linux container ${name} is successfully created! The configuration is 332 | stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for 333 | information about configuring Arch Linux. 334 | EOF 335 | -------------------------------------------------------------------------------- /templates/lxc-ubuntu-cloud.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # template script for generating ubuntu container for LXC based on released 4 | # cloud images. 5 | # 6 | # Copyright © 2012 Serge Hallyn 7 | # 8 | # This library is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU Lesser General Public 10 | # License as published by the Free Software Foundation; either 11 | # version 2.1 of the License, or (at your option) any later version. 12 | 13 | # This library is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | # Lesser General Public License for more details. 17 | 18 | # You should have received a copy of the GNU Lesser General Public 19 | # License along with this library; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | 22 | set -e 23 | 24 | STATE_DIR="@LOCALSTATEDIR@" 25 | HOOK_DIR="@LXCHOOKDIR@" 26 | CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep" 27 | LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@" 28 | KNOWN_RELEASES="precise trusty xenial yakkety zesty" 29 | skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0} 30 | 31 | # Make sure the usual locations are in PATH 32 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 33 | 34 | if [ -r /etc/default/lxc ]; then 35 | . /etc/default/lxc 36 | fi 37 | 38 | am_in_userns() { 39 | [ -e /proc/self/uid_map ] || { echo no; return; } 40 | [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; } 41 | line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map) 42 | [ "$line" = "0 0 4294967295" ] && { echo no; return; } 43 | echo yes 44 | } 45 | 46 | in_userns=0 47 | [ $(am_in_userns) = "yes" ] && in_userns=1 48 | 49 | copy_configuration() 50 | { 51 | path=$1 52 | rootfs=$2 53 | name=$3 54 | arch=$4 55 | release=$5 56 | 57 | if [ $arch = "i386" ]; then 58 | arch="i686" 59 | fi 60 | 61 | # if there is exactly one veth network entry, make sure it has an 62 | # associated hwaddr. 63 | nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' $path/config | wc -l` 64 | if [ $nics -eq 1 ]; then 65 | grep -q "^lxc.net.0.hwaddr" $path/config || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config 66 | fi 67 | 68 | # Generate the configuration file 69 | ## Relocate all the network config entries 70 | sed -i -e "/lxc.net.0/{w ${path}/config-network" -e "d}" $path/config 71 | 72 | ## Relocate any other config entries 73 | sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config 74 | 75 | ## Add all the includes 76 | echo "" >> $path/config 77 | echo "# Common configuration" >> $path/config 78 | if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" ]; then 79 | echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" >> $path/config 80 | fi 81 | if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" ]; then 82 | echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" >> $path/config 83 | fi 84 | if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then 85 | echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" >> $path/config 86 | fi 87 | 88 | ## Add the container-specific config 89 | echo "" >> $path/config 90 | echo "# Container specific configuration" >> $path/config 91 | [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto 92 | grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config 93 | cat <> $path/config 94 | lxc.uts.name = $name 95 | lxc.arch = $arch 96 | EOF 97 | 98 | ## Re-add the previously removed network config 99 | echo "" >> $path/config 100 | echo "# Network configuration" >> $path/config 101 | cat $path/config-network >> $path/config 102 | rm $path/config-network 103 | 104 | # Set initial timezone as on host 105 | if [ -f /etc/timezone ]; then 106 | cat /etc/timezone > $rootfs/etc/timezone 107 | chroot $rootfs dpkg-reconfigure -f noninteractive tzdata 108 | elif [ -f /etc/sysconfig/clock ]; then 109 | . /etc/sysconfig/clock 110 | echo $ZONE > $rootfs/etc/timezone 111 | chroot $rootfs dpkg-reconfigure -f noninteractive tzdata 112 | else 113 | echo "Timezone in container is not configured. Adjust it manually." 114 | fi 115 | 116 | # rmdir /dev/shm for containers that have /run/shm 117 | # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did 118 | # get bind mounted to the host's /run/shm. So try to rmdir 119 | # it, and in case that fails move it out of the way. 120 | # NOTE: This can only be removed once 12.04 goes out of support 121 | if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then 122 | rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak 123 | ln -s /run/shm $rootfs/dev/shm 124 | fi 125 | 126 | return 0 127 | } 128 | 129 | usage() 130 | { 131 | cat < ]: Release name of container, defaults to host 136 | [ --rootfs ]: Path in which rootfs will be placed 137 | [ -a | --arch ]: Architecture of container, defaults to host architecture 138 | [ -T | --tarball ]: Location of tarball 139 | [ -d | --debug ]: Run with 'set -x' to debug errors 140 | [ -s | --stream]: Use specified stream rather than 'tryreleased' 141 | 142 | Additionally, clone hooks can be passed through (ie, --userdata). For those, 143 | see: 144 | $CLONE_HOOK_FN --help 145 | EOF 146 | return 0 147 | } 148 | 149 | options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,vendordata:,mapped-uid:,mapped-gid: -- "$@") 150 | if [ $? -ne 0 ]; then 151 | usage $(basename $0) 152 | exit 1 153 | fi 154 | eval set -- "$options" 155 | 156 | mapped_uid=-1 157 | mapped_gid=-1 158 | # default release is trusty, or the systems release if recognized 159 | release=trusty 160 | if [ -f /etc/lsb-release ]; then 161 | . /etc/lsb-release 162 | rels=$(ubuntu-distro-info --supported 2>/dev/null) || 163 | rels="$KNOWN_RELEASES" 164 | for r in $rels; do 165 | [ "$DISTRIB_CODENAME" = "$r" ] && release="$r" 166 | done 167 | fi 168 | 169 | # Code taken from debootstrap 170 | if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then 171 | arch=`/usr/bin/dpkg --print-architecture` 172 | elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then 173 | arch=`/usr/bin/udpkg --print-architecture` 174 | else 175 | arch=$(uname -m) 176 | if [ "$arch" = "i686" ]; then 177 | arch="i386" 178 | elif [ "$arch" = "x86_64" ]; then 179 | arch="amd64" 180 | elif [ "$arch" = "armv7l" ]; then 181 | # note: arm images don't exist before oneiric; are called armhf in 182 | # trusty and later; and are not supported by the query, so we don't actually 183 | # support them yet (see check later on). When Query2 is available, 184 | # we'll use that to enable arm images. 185 | arch="armhf" 186 | elif [ "$arch" = "aarch64" ]; then 187 | arch="arm64" 188 | elif [ "$arch" = "ppc64le" ]; then 189 | arch="ppc64el" 190 | fi 191 | fi 192 | 193 | debug=0 194 | hostarch=$arch 195 | cloud=0 196 | locales=1 197 | flushcache=0 198 | stream="tryreleased" 199 | cloneargs=() 200 | while true 201 | do 202 | case "$1" in 203 | -h|--help) usage $0 && exit 1;; 204 | -p|--path) path=$2; shift 2;; 205 | -n|--name) name=$2; shift 2;; 206 | -F|--flush-cache) flushcache=1; shift 1;; 207 | -r|--release) release=$2; shift 2;; 208 | -a|--arch) arch=$2; shift 2;; 209 | -T|--tarball) tarball=$2; shift 2;; 210 | -d|--debug) debug=1; shift 1;; 211 | -s|--stream) stream=$2; shift 2;; 212 | --rootfs) rootfs=$2; shift 2;; 213 | -L|--no?locales) cloneargs[${#cloneargs[@]}]="--no-locales"; shift 1;; 214 | -i|--hostid) cloneargs[${#cloneargs[@]}]="--hostid=$2"; shift 2;; 215 | -u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;; 216 | -V|--vendordata) cloneargs[${#cloneargs[@]}]="--vendordata=$2"; shift 2;; 217 | -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;; 218 | -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;; 219 | --mapped-uid) mapped_uid=$2; shift 2;; 220 | --mapped-gid) mapped_gid=$2; shift 2;; 221 | --) shift 1; break ;; 222 | *) break ;; 223 | esac 224 | done 225 | 226 | cloneargs=( "--name=$name" "${cloneargs[@]}" ) 227 | 228 | if [ $debug -eq 1 ]; then 229 | set -x 230 | fi 231 | 232 | if [ "$arch" = "i686" ]; then 233 | arch=i386 234 | fi 235 | 236 | if [ "$skip_arch_check" = "0" ]; then 237 | case "$hostarch:$arch" in 238 | $arch:$arch) : ;; # the host == container 239 | amd64:i386) :;; # supported "cross" 240 | arm64:arm*) :;; # supported "cross" 241 | armel:armhf) :;; # supported "cross" 242 | armhf:armel) :;; # supported "cross" 243 | *) echo "cannot create '$arch' container on hostarch '$hostarch'"; 244 | exit 1;; 245 | esac 246 | fi 247 | 248 | if [ "$stream" != "daily" -a "$stream" != "released" -a "$stream" != "tryreleased" ]; then 249 | echo "Only 'daily' and 'released' and 'tryreleased' streams are supported" 250 | exit 1 251 | fi 252 | 253 | if [ -z "$path" ]; then 254 | echo "'path' parameter is required" 255 | exit 1 256 | fi 257 | 258 | if [ "$(id -u)" != "0" ]; then 259 | echo "This script should be run as 'root'" 260 | exit 1 261 | fi 262 | 263 | # detect rootfs 264 | config="$path/config" 265 | if [ -z "$rootfs" ]; then 266 | if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then 267 | rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config) 268 | else 269 | rootfs=$path/rootfs 270 | fi 271 | fi 272 | 273 | type ubuntu-cloudimg-query 274 | type wget 275 | 276 | # determine the url, tarball, and directory names 277 | # download if needed 278 | # Allow the cache base to be set by environment variable 279 | cache=${LXC_CACHE_PATH:-"$STATE_DIR/cache/lxc"}/cloud-$release 280 | if [ $in_userns -eq 1 ]; then 281 | STATE_DIR="$HOME/.cache/lxc" 282 | cache=${LXC_CACHE_PATH:-"$STATE_DIR"}/cloud-$release 283 | fi 284 | 285 | mkdir -p $cache 286 | 287 | if [ "$stream" = "tryreleased" ]; then 288 | stream=released 289 | ubuntu-cloudimg-query $release $stream $arch 1>/dev/null 2>/dev/null || stream=daily 290 | fi 291 | 292 | if [ -n "$tarball" ]; then 293 | url2="$tarball" 294 | else 295 | if ! url1=`ubuntu-cloudimg-query $release $stream $arch --format "%{url}\n"`; then 296 | echo "There is no download available for release=$release, stream=$stream, arch=$arch" 297 | [ "$stream" = "daily" ] || echo "You may try with '--stream=daily'" 298 | exit 1 299 | fi 300 | if [ "$release" = "precise" ] || [ "$release" = "trusty" ]; then 301 | url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'` 302 | else 303 | url2=`echo $url1 | sed -e 's/.tar.gz/.squashfs/'` 304 | fi 305 | fi 306 | 307 | filename=`basename $url2` 308 | 309 | wgetcleanup() 310 | { 311 | rm -f $filename 312 | } 313 | 314 | do_extract_rootfs() { 315 | 316 | cd $cache 317 | if [ $flushcache -eq 1 ]; then 318 | echo "Clearing the cached images" 319 | rm -f $filename 320 | fi 321 | 322 | trap wgetcleanup EXIT SIGHUP SIGINT SIGTERM 323 | if [ ! -f $filename ]; then 324 | wget $url2 325 | fi 326 | trap EXIT 327 | trap SIGHUP 328 | trap SIGINT 329 | trap SIGTERM 330 | 331 | echo "Extracting container rootfs" 332 | mkdir -p $rootfs 333 | cd $rootfs 334 | if [ "${filename##*.}" = "squashfs" ]; then 335 | unsquashfs -n -f -d "$rootfs" "$cache/$filename" 336 | else 337 | if [ $in_userns -eq 1 ]; then 338 | tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename" 339 | mkdir -p $rootfs/dev/pts/ 340 | else 341 | tar --numeric-owner -xpf "$cache/$filename" 342 | fi 343 | fi 344 | } 345 | 346 | if [ -n "$tarball" ]; then 347 | do_extract_rootfs 348 | else 349 | mkdir -p "$STATE_DIR/lock/subsys/" 350 | ( 351 | flock -x 9 352 | do_extract_rootfs 353 | ) 9>"$STATE_DIR/lock/subsys/lxc-ubuntu-cloud" 354 | fi 355 | 356 | copy_configuration $path $rootfs $name $arch $release 357 | 358 | "$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs" 359 | 360 | if [ $mapped_uid -ne -1 ]; then 361 | chown $mapped_uid $path/config 362 | chown -R $mapped_uid $STATE_DIR 363 | chown -R $mapped_uid $cache 364 | fi 365 | if [ $mapped_gid -ne -1 ]; then 366 | chgrp $mapped_gid $path/config 367 | chgrp -R $mapped_gid $STATE_DIR 368 | chgrp -R $mapped_gid $cache 369 | fi 370 | 371 | echo "Container $name created." 372 | exit 0 373 | 374 | # vi: ts=4 expandtab 375 | -------------------------------------------------------------------------------- /templates/lxc-openmandriva.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # template script for generating openmandriva container for LXC 5 | # 6 | 7 | # 8 | # lxc: linux Container library 9 | 10 | # Authors: 11 | # Alexander Stefanov 12 | # Vokhmin Alexey V 13 | # Bernhard Rosenkraenzer 14 | 15 | # This library is free software; you can redistribute it and/or 16 | # modify it under the terms of the GNU Lesser General Public 17 | # License as published by the Free Software Foundation; either 18 | # version 2.1 of the License, or (at your option) any later version. 19 | 20 | # This library is distributed in the hope that it will be useful, 21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | # Lesser General Public License for more details. 24 | 25 | # You should have received a copy of the GNU Lesser General Public 26 | # License along with this library; if not, write to the Free Software 27 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 | # 29 | 30 | # Detect use under userns (unsupported) 31 | for arg in "$@"; do 32 | [ "$arg" = "--" ] && break 33 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 34 | echo "This template can't be used for unprivileged containers." 1>&2 35 | echo "You may want to try the \"download\" template instead." 1>&2 36 | exit 1 37 | fi 38 | done 39 | 40 | # Make sure the usual locations are in PATH 41 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 42 | 43 | #Configurations 44 | #distro=cooker 45 | hostarch=$(uname -m) 46 | # Allow the cache base to be set by environment variable 47 | cache_base="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/openmandriva/$arch}" 48 | default_path=@LXCPATH@ 49 | default_profile=default 50 | lxc_network_type=veth 51 | lxc_network_link=lxcbr0 52 | 53 | # is this openmandriva? 54 | grep -q OpenMandriva /etc/os-release && is_openmandriva=true 55 | 56 | configure_openmandriva() 57 | { 58 | # set the hostname 59 | echo "${utsname}" > ${rootfs_path}/etc/hostname 60 | 61 | # set minimal hosts 62 | cat < $rootfs_path/etc/hosts 63 | 127.0.0.1 localhost.localdomain localhost $utsname 64 | ::1 localhost6.localdomain6 localhost6 65 | EOF 66 | } 67 | 68 | populate_dev() 69 | { 70 | echo -n "Create devices in /dev/" 71 | dev_path="${rootfs_path}/dev" 72 | rm -rf $dev_path 73 | mkdir -p $dev_path 74 | mknod -m 666 ${dev_path}/null c 1 3 75 | mknod -m 666 ${dev_path}/zero c 1 5 76 | mknod -m 666 ${dev_path}/random c 1 8 77 | mknod -m 666 ${dev_path}/urandom c 1 9 78 | mkdir -m 755 ${dev_path}/pts 79 | mkdir -m 1777 ${dev_path}/shm 80 | mknod -m 666 ${dev_path}/tty c 5 0 81 | mknod -m 666 ${dev_path}/tty0 c 4 0 82 | mknod -m 666 ${dev_path}/tty1 c 4 1 83 | mknod -m 666 ${dev_path}/tty2 c 4 2 84 | mknod -m 666 ${dev_path}/tty3 c 4 3 85 | mknod -m 666 ${dev_path}/tty4 c 4 4 86 | mknod -m 666 ${dev_path}/tty5 c 4 5 87 | mknod -m 666 ${dev_path}/tty6 c 4 6 88 | mknod -m 600 ${dev_path}/console c 5 1 89 | mknod -m 666 ${dev_path}/full c 1 7 90 | mknod -m 600 ${dev_path}/initctl p 91 | mknod -m 666 ${dev_path}/ptmx c 5 2 92 | mkdir -m 755 ${dev_path}/net 93 | mknod -m 666 ${dev_path}/net/tun c 10 200 94 | } 95 | 96 | set_guest_root_password() 97 | { 98 | [ -z "$root_password" ] && return # pass is empty, abort 99 | 100 | echo " - setting guest root password.." 101 | echo "root passwd is: $root_password" 102 | echo "root:$root_password" | chroot "$rootfs_path" chpasswd 103 | echo "done." 104 | } 105 | 106 | create_chroot_openmandriva() 107 | { 108 | # check the mini openmandriva was not already downloaded 109 | INSTALL_ROOT=$cache/cache 110 | mkdir -p $INSTALL_ROOT 111 | if [ $? -ne 0 ]; then 112 | echo "Failed to create '$INSTALL_ROOT' directory" 113 | return 1 114 | fi 115 | 116 | # Poor man's version of "dnf install --installroot=" -- 117 | # need to get the repository configs from rpm packages 118 | # without having the repositories configured... 119 | PKGS=http://abf-downloads.rosalinux.ru/$release/repository/$arch/main/release/ 120 | curl -s -L $PKGS |grep '^PACKAGES 121 | PRE_PACKAGES="rosa-repos" 122 | for i in $PRE_PACKAGES; do 123 | P=`grep "^$i-[0-9].*" PACKAGES` 124 | if [ "$?" != "0" ]; then 125 | echo "Can't find $i package for target" >&2 126 | exit 1 127 | fi 128 | curl -O $PKGS/$P 129 | rpm -r $INSTALL_ROOT -Uvh --ignorearch --nodeps $P 130 | done 131 | 132 | # package list to install 133 | PKG_LIST="basesystem-minimal locales locales-en systemd dnf networkmanager kbd" 134 | # download a mini openmandriva into a cache 135 | echo "Downloading openmandriva minimal ..." 136 | DNF="/usr/bin/dnf -y install --nogpgcheck --installroot=$INSTALL_ROOT --releasever=$release --forcearch=$arch $PKG_LIST" 137 | echo $DNF 138 | $DNF 139 | # We're splitting the old loop into two loops plus a directory retrival. 140 | # First loop... Try and retrive a mirror list with retries and a slight 141 | # delay between attempts... 142 | if [ $? -ne 0 ]; then 143 | echo "Failed to download the rootfs, aborting." 144 | return 1 145 | fi 146 | 147 | mv "$INSTALL_ROOT" "$cache/rootfs" 148 | echo "Download complete." 149 | 150 | return 0 151 | } 152 | 153 | copy_openmandriva() 154 | { 155 | 156 | echo -n "Copying rootfs to $rootfs_path ..." 157 | mkdir -p $rootfs_path 158 | rsync -SHaAX $cache/rootfs/ $rootfs_path/ 159 | return 0 160 | } 161 | 162 | update_openmandriva() 163 | { 164 | echo "automated update in progress..." 165 | dnf -y distro-sync --installroot=$cache/rootfs 166 | } 167 | 168 | configure_openmandriva_systemd() 169 | { 170 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount 171 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd.service 172 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket 173 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket 174 | # remove numlock service 175 | # KDGKBLED: Inappropriate ioctl for device 176 | rm -f ${rootfs_path}/etc/systemd/system/getty@.service.d/enable-numlock.conf 177 | 178 | unlink ${rootfs_path}/etc/systemd/system/default.target 179 | chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target 180 | sed -i 's!ConditionPathExists=/dev/tty0!ConditionPathExists=|/dev/tty0\nConditionVirtualization=|lxc!' \ 181 | ${rootfs_path}/lib/systemd/system/getty\@.service 182 | } 183 | 184 | 185 | install_openmandriva() 186 | { 187 | mkdir -p @LOCALSTATEDIR@/lock/subsys/ 188 | ( 189 | flock -x 9 190 | if [ $? -ne 0 ]; then 191 | echo "Cache repository is busy." 192 | return 1 193 | fi 194 | 195 | echo "Checking cache download in $cache/rootfs ... " 196 | if [ ! -e "$cache/rootfs" ]; then 197 | echo $cache/rootfs 198 | create_chroot_openmandriva 199 | if [ $? -ne 0 ]; then 200 | echo "Failed to download 'openmandriva basesystem-minimal'" 201 | return 1 202 | fi 203 | else 204 | echo "Cache found. Updating..." 205 | update_openmandriva 206 | if [ $? -ne 0 ]; then 207 | echo "Failed to update 'openmandriva base', continuing with last known good cache" 208 | else 209 | echo "Update finished" 210 | fi 211 | fi 212 | 213 | echo "Copy $cache/rootfs to $rootfs_path ... " 214 | copy_openmandriva 215 | if [ $? -ne 0 ]; then 216 | echo "Failed to copy rootfs" 217 | return 1 218 | fi 219 | return 0 220 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva 221 | 222 | return $? 223 | } 224 | 225 | copy_configuration() 226 | { 227 | 228 | mkdir -p $config_path 229 | grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config 230 | cat <> $config_path/config 231 | lxc.uts.name = $name 232 | lxc.tty.max = 4 233 | lxc.pty.max = 1024 234 | lxc.cap.drop = sys_module mac_admin mac_override sys_time 235 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed 236 | 237 | # When using LXC with apparmor, uncomment the next line to run unconfined: 238 | #lxc.apparmor.profile = unconfined 239 | 240 | #networking 241 | lxc.net.0.type = $lxc_network_type 242 | lxc.net.0.flags = up 243 | lxc.net.0.link = $lxc_network_link 244 | lxc.net.0.name = eth0 245 | lxc.net.0.mtu = 1500 246 | EOF 247 | if [ ! -z ${ipv4} ]; then 248 | cat <> $config_path/config 249 | lxc.net.0.ipv4.address = $ipv4 250 | EOF 251 | fi 252 | if [ ! -z ${gw} ]; then 253 | cat <> $config_path/config 254 | lxc.net.0.ipv4.gateway = $gw 255 | EOF 256 | fi 257 | if [ ! -z ${ipv6} ]; then 258 | cat <> $config_path/config 259 | lxc.net.0.ipv6.address = $ipv6 260 | EOF 261 | fi 262 | if [ ! -z ${gw6} ]; then 263 | cat <> $config_path/config 264 | lxc.net.0.ipv6.gateway = $gw6 265 | EOF 266 | fi 267 | cat <> $config_path/config 268 | #cgroups 269 | lxc.cgroup.devices.deny = a 270 | # /dev/null and zero 271 | lxc.cgroup.devices.allow = c 1:3 rwm 272 | lxc.cgroup.devices.allow = c 1:5 rwm 273 | # consoles 274 | lxc.cgroup.devices.allow = c 5:1 rwm 275 | lxc.cgroup.devices.allow = c 5:0 rwm 276 | lxc.cgroup.devices.allow = c 4:0 rwm 277 | lxc.cgroup.devices.allow = c 4:1 rwm 278 | # /dev/{,u}random 279 | lxc.cgroup.devices.allow = c 1:9 rwm 280 | lxc.cgroup.devices.allow = c 1:8 rwm 281 | lxc.cgroup.devices.allow = c 136:* rwm 282 | lxc.cgroup.devices.allow = c 5:2 rwm 283 | # rtc 284 | lxc.cgroup.devices.allow = c 10:135 rwm 285 | EOF 286 | 287 | if [ $? -ne 0 ]; then 288 | echo "Failed to add configuration" 289 | return 1 290 | fi 291 | 292 | return 0 293 | } 294 | 295 | clean() 296 | { 297 | 298 | if [ ! -e $cache ]; then 299 | exit 0 300 | fi 301 | 302 | # lock, so we won't purge while someone is creating a repository 303 | ( 304 | flock -x 9 305 | if [ $? != 0 ]; then 306 | echo "Cache repository is busy." 307 | exit 1 308 | fi 309 | 310 | echo -n "Purging the download cache for OpenMandriva-$release..." 311 | rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 312 | exit 0 313 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva 314 | } 315 | 316 | usage() 317 | { 318 | cat < 321 | [-p|--path=] [-c|--clean] [-R|--release=] 322 | [-4|--ipv4=] [-6|--ipv6=] 323 | [-g|--gw=] [-d|--dns=] 324 | [-P|--profile=] [--rootfs=] 325 | [-A|--arch=] 326 | [-h|--help] 327 | Mandatory args: 328 | -n,--name container name, used to as an identifier for that container from now on 329 | Optional args: 330 | -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case 331 | -c,--clean clean the cache 332 | -R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release. 333 | -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 334 | -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 335 | -g,--gw specify the default gw, eg. 192.168.1.1 336 | -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 337 | -d,--dns specify the DNS server, eg. 192.168.1.2 338 | -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. 339 | -A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl] 340 | ---rootfs rootfs path 341 | -h,--help print this help 342 | EOF 343 | return 0 344 | } 345 | 346 | options=$(getopt -o hp:n:P:cR:4:6:g:d:A -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch: -- "$@") 347 | if [ $? -ne 0 ]; then 348 | usage $(basename $0) 349 | exit 1 350 | fi 351 | eval set -- "$options" 352 | 353 | release=${release:-"cooker"} 354 | 355 | while true 356 | do 357 | case "$1" in 358 | -h|--help) usage $0 && exit 0;; 359 | -p|--path) path=$2; shift 2;; 360 | --rootfs) rootfs_path=$2; shift 2;; 361 | -n|--name) name=$2; shift 2;; 362 | -P|--profile) profile=$2; shift 2;; 363 | -c|--clean) clean=1; shift 1;; 364 | -R|--release) release=$2; shift 2;; 365 | -A|--arch) arch=$2; shift 2;; 366 | -4|--ipv4) ipv4=$2; shift 2;; 367 | -6|--ipv6) ipv6=$2; shift 2;; 368 | -g|--gw) gw=$2; shift 2;; 369 | -d|--dns) dns=$2; shift 2;; 370 | --) shift 1; break ;; 371 | *) break ;; 372 | esac 373 | done 374 | 375 | arch=${arch:-$hostarch} 376 | 377 | if [ ! -z "$clean" -a -z "$path" ]; then 378 | clean || exit 1 379 | exit 0 380 | fi 381 | 382 | if [ -z "${utsname}" ]; then 383 | utsname=${name} 384 | fi 385 | 386 | type urpmi >/dev/null 2>&1 387 | if [ $? -ne 0 ]; then 388 | echo "'urpmi' command is missing" 389 | exit 1 390 | fi 391 | 392 | if [ -z "$path" ]; then 393 | path=$default_path 394 | fi 395 | 396 | if [ -z "$profile" ]; then 397 | profile=$default_profile 398 | fi 399 | 400 | if [ $hostarch = "i686" -a $arch = "x86_64" ]; then 401 | echo "can't create x86_64 container on i686" 402 | exit 1 403 | fi 404 | 405 | if [ -z "$ipv4" -a -z "$ipv6" ]; then 406 | BOOTPROTO="dhcp" 407 | else 408 | BOOTPROTO="static" 409 | fi 410 | 411 | if [ "$(id -u)" != "0" ]; then 412 | echo "This script should be run as 'root'" 413 | exit 1 414 | fi 415 | 416 | # check for 'lxc.rootfs.path' passed in through default config by lxc-create 417 | if [ -z "$rootfs_path" ]; then 418 | if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then 419 | rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) 420 | else 421 | rootfs_path=$path/$name/rootfs 422 | fi 423 | fi 424 | 425 | config_path=$default_path/$name 426 | cache=$cache_base/$release/$arch/$profile 427 | 428 | if [ ! -f $config_path/config ]; then 429 | echo "A container with that name exists, chose a different name" 430 | exit 1 431 | fi 432 | 433 | install_openmandriva 434 | if [ $? -ne 0 ]; then 435 | echo "failed to install openmandriva" 436 | exit 1 437 | fi 438 | 439 | configure_openmandriva 440 | if [ $? -ne 0 ]; then 441 | echo "failed to configure openmandriva for a container" 442 | exit 1 443 | fi 444 | 445 | # If the systemd configuration directory exists - set it up for what we need. 446 | if [ -d ${rootfs_path}/etc/systemd/system ] 447 | then 448 | configure_openmandriva_systemd 449 | fi 450 | 451 | populate_dev 452 | if [ $? -ne 0 ]; then 453 | echo "failed to populated /dev/ devices" 454 | exit 1 455 | fi 456 | 457 | set_guest_root_password 458 | if [ $? -ne 0 ]; then 459 | echo "failed to configure password for chroot" 460 | exit 1 461 | fi 462 | 463 | copy_configuration 464 | if [ $? -ne 0 ]; then 465 | echo "failed write configuration file" 466 | exit 1 467 | fi 468 | 469 | if [ ! -z "$clean" ]; then 470 | clean || exit 1 471 | exit 0 472 | fi 473 | echo "container rootfs and config created" 474 | -------------------------------------------------------------------------------- /templates/lxc-pld.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # template script for generating PLD Linux container for LXC 5 | # 6 | 7 | # 8 | # lxc: Linux Container library 9 | 10 | # Authors: 11 | # Elan Ruusamäe 12 | 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 | 27 | # Detect use under userns (unsupported) 28 | for arg in "$@"; do 29 | [ "$arg" = "--" ] && break 30 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 31 | echo "This template can't be used for unprivileged containers." 1>&2 32 | echo "You may want to try the \"download\" template instead." 1>&2 33 | exit 1 34 | fi 35 | done 36 | 37 | # Configuration 38 | arch=$(uname -m) 39 | cache_base=@LOCALSTATEDIR@/cache/lxc/pld/$arch 40 | default_path=@LXCPATH@ 41 | 42 | if [ -e /etc/os-release ]; then 43 | # This is a shell friendly configuration file. We can just source it. 44 | # What we're looking for in here is the ID, VERSION_ID and the CPE_NAME 45 | . /etc/os-release 46 | echo "Host CPE ID from /etc/os-release: ${CPE_NAME}" 47 | fi 48 | 49 | if [ "${CPE_NAME}" != "" -a "${ID}" = "pld" -a "${VERSION_ID}" != "" ]; then 50 | pld_host_ver=${VERSION_ID} 51 | is_pld=true 52 | elif [ -e /etc/pld-release ]; then 53 | # Only if all other methods fail, try to parse the pld-release file. 54 | pld_host_ver=$(sed -e '/PLD /!d' -e 's/^\([0-9.]*\)\sPLD.*/\1/' < /etc/pld-release) 55 | if [ "$pld_host_ver" != "" ]; then 56 | is_pld=true 57 | fi 58 | fi 59 | 60 | # Map a few architectures to their generic PLD Linux repository archs. 61 | case "$pld_host_ver:$arch" in 62 | 3.0:i586) arch=i486 ;; 63 | esac 64 | 65 | configure_pld() 66 | { 67 | 68 | # disable selinux 69 | mkdir -p $rootfs_path/selinux 70 | echo 0 > $rootfs_path/selinux/enforce 71 | 72 | # configure the network using the dhcp 73 | sed -i -e "s/^HOSTNAME=.*/HOSTNAME=${utsname}/" ${rootfs_path}/etc/sysconfig/network 74 | 75 | # set hostname on systemd 76 | if [ $release = "3.0" ]; then 77 | echo "${utsname}" > ${rootfs_path}/etc/hostname 78 | fi 79 | 80 | # set minimal hosts 81 | test -e $rootfs_path/etc/hosts || \ 82 | cat < $rootfs_path/etc/hosts 83 | 127.0.0.1 localhost.localdomain localhost $utsname 84 | ::1 localhost6.localdomain6 localhost6 85 | EOF 86 | 87 | dev_path="${rootfs_path}/dev" 88 | rm -rf $dev_path 89 | mkdir -p $dev_path 90 | mknod -m 666 ${dev_path}/null c 1 3 91 | mknod -m 666 ${dev_path}/zero c 1 5 92 | mknod -m 666 ${dev_path}/random c 1 8 93 | mknod -m 666 ${dev_path}/urandom c 1 9 94 | mkdir -m 755 ${dev_path}/pts 95 | mkdir -m 1777 ${dev_path}/shm 96 | mknod -m 666 ${dev_path}/tty c 5 0 97 | mknod -m 666 ${dev_path}/tty0 c 4 0 98 | mknod -m 666 ${dev_path}/tty1 c 4 1 99 | mknod -m 666 ${dev_path}/tty2 c 4 2 100 | mknod -m 666 ${dev_path}/tty3 c 4 3 101 | mknod -m 666 ${dev_path}/tty4 c 4 4 102 | mknod -m 600 ${dev_path}/console c 5 1 103 | mknod -m 666 ${dev_path}/full c 1 7 104 | mknod -m 600 ${dev_path}/initctl p 105 | mknod -m 666 ${dev_path}/ptmx c 5 2 106 | 107 | if [ -n "${root_password}" ]; then 108 | echo "setting root passwd to $root_password" 109 | echo "root:$root_password" | chroot $rootfs_path chpasswd 110 | fi 111 | 112 | return 0 113 | } 114 | 115 | configure_pld_init() 116 | { 117 | # default powerfail action waits 2 minutes. for lxc we want it immediately 118 | sed -i -e '/^pf::powerfail:/ s,/sbin/shutdown.*,/sbin/halt,' ${rootfs_path}/etc/inittab 119 | } 120 | 121 | configure_pld_systemd() 122 | { 123 | unlink ${rootfs_path}/etc/systemd/system/default.target 124 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service 125 | chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target 126 | 127 | # Actually, the After=dev-%i.device line does not appear in the 128 | # Fedora 17 or Fedora 18 systemd getty@.service file. It may be left 129 | # over from an earlier version and it's not doing any harm. We do need 130 | # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are 131 | # started on the ttys in the container. Lets do it in an override copy of 132 | # the service so it can still pass rpm verifies and not be automatically 133 | # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/ 134 | 135 | sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \ 136 | -e 's/After=dev-%i.device/After=/' \ 137 | < ${rootfs_path}/lib/systemd/system/getty@.service \ 138 | > ${rootfs_path}/etc/systemd/system/getty@.service 139 | 140 | # Setup getty service on the 4 ttys we are going to allow in the 141 | # default config. Number should match lxc.tty.max 142 | for i in 1 2 3 4; do 143 | ln -sf ../getty@.service ${rootfs_path}/etc/systemd/system/getty.target.wants/getty@tty${i}.service 144 | done 145 | } 146 | 147 | download_pld() 148 | { 149 | 150 | # check the mini pld was not already downloaded 151 | INSTALL_ROOT=$cache/partial 152 | mkdir -p $INSTALL_ROOT 153 | if [ $? -ne 0 ]; then 154 | echo "Failed to create '$INSTALL_ROOT' directory" 155 | return 1 156 | fi 157 | 158 | # download a mini pld into a cache 159 | echo "Downloading PLD Linux minimal ..." 160 | POLDEK="poldek --root $INSTALL_ROOT --noask --nohold --noignore" 161 | PKG_LIST="basesystem filesystem pld-release rpm poldek vserver-packages rc-scripts pwdutils mingetty" 162 | 163 | mkdir -p $INSTALL_ROOT@LOCALSTATEDIR@/lib/rpm 164 | rpm --root $INSTALL_ROOT --initdb 165 | $POLDEK -u $PKG_LIST 166 | 167 | if [ $? -ne 0 ]; then 168 | echo "Failed to download the rootfs, aborting." 169 | return 1 170 | fi 171 | 172 | mv "$INSTALL_ROOT" "$cache/rootfs" 173 | echo "Download complete." 174 | 175 | return 0 176 | } 177 | 178 | copy_pld() 179 | { 180 | 181 | # make a local copy of the minipld 182 | echo -n "Copying rootfs to $rootfs_path ..." 183 | cp -a $cache/rootfs/* $rootfs_path || return 1 184 | return 0 185 | } 186 | 187 | update_pld() 188 | { 189 | POLDEK="poldek --root $cache/rootfs --noask" 190 | $POLDEK --upgrade-dist 191 | } 192 | 193 | install_pld() 194 | { 195 | mkdir -p @LOCALSTATEDIR@/lock/subsys/ 196 | ( 197 | flock -x 9 198 | if [ $? -ne 0 ]; then 199 | echo "Cache repository is busy." 200 | return 1 201 | fi 202 | 203 | echo "Checking cache download in $cache/rootfs ... " 204 | if [ ! -e "$cache/rootfs" ]; then 205 | download_pld 206 | if [ $? -ne 0 ]; then 207 | echo "Failed to download 'pld base'" 208 | return 1 209 | fi 210 | else 211 | echo "Cache found. Updating..." 212 | update_pld 213 | if [ $? -ne 0 ]; then 214 | echo "Failed to update 'pld base', continuing with last known good cache" 215 | else 216 | echo "Update finished" 217 | fi 218 | fi 219 | 220 | echo "Copy $cache/rootfs to $rootfs_path ... " 221 | copy_pld 222 | if [ $? -ne 0 ]; then 223 | echo "Failed to copy rootfs" 224 | return 1 225 | fi 226 | 227 | return 0 228 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld 229 | 230 | return $? 231 | } 232 | 233 | copy_configuration() 234 | { 235 | 236 | mkdir -p $config_path 237 | grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config 238 | cat <> $config_path/config 239 | # Most of below settings should be taken as defaults from 240 | # lxc.include = /usr/share/lxc/config/common.conf 241 | lxc.uts.name = $utsname 242 | lxc.tty.max = 4 243 | lxc.pty.max = 1024 244 | # Consider if below line is right for systemd container 245 | lxc.mount.fstab = $config_path/fstab 246 | lxc.cap.drop = sys_module mac_admin mac_override sys_time 247 | 248 | lxc.autodev = $auto_dev 249 | 250 | # When using LXC with apparmor, uncomment the next line to run unconfined: 251 | #lxc.apparmor.profile = unconfined 252 | 253 | ## Devices 254 | # Allow all devices 255 | #lxc.cgroup.devices.allow = a 256 | # Deny all devices 257 | lxc.cgroup.devices.deny = a 258 | # Allow to mknod all devices (but not using them) 259 | lxc.cgroup.devices.allow = c *:* m 260 | lxc.cgroup.devices.allow = b *:* m 261 | 262 | # /dev/null and zero 263 | lxc.cgroup.devices.allow = c 1:3 rwm 264 | lxc.cgroup.devices.allow = c 1:5 rwm 265 | # consoles 266 | lxc.cgroup.devices.allow = c 5:1 rwm 267 | lxc.cgroup.devices.allow = c 5:0 rwm 268 | lxc.cgroup.devices.allow = c 4:0 rwm 269 | lxc.cgroup.devices.allow = c 4:1 rwm 270 | # /dev/{,u}random 271 | lxc.cgroup.devices.allow = c 1:9 rwm 272 | lxc.cgroup.devices.allow = c 1:8 rwm 273 | lxc.cgroup.devices.allow = c 136:* rwm 274 | lxc.cgroup.devices.allow = c 5:2 rwm 275 | # rtc 276 | lxc.cgroup.devices.allow = c 254:0 rm 277 | EOF 278 | 279 | cat < $config_path/fstab 280 | proc proc proc nodev,noexec,nosuid 0 0 281 | sysfs sys sysfs defaults 0 0 282 | EOF 283 | if [ $? -ne 0 ]; then 284 | echo "Failed to add configuration" 285 | return 1 286 | fi 287 | 288 | return 0 289 | } 290 | 291 | clean() 292 | { 293 | 294 | if [ ! -e $cache ]; then 295 | exit 0 296 | fi 297 | 298 | # lock, so we won't purge while someone is creating a repository 299 | ( 300 | flock -x 9 301 | if [ $? != 0 ]; then 302 | echo "Cache repository is busy." 303 | exit 1 304 | fi 305 | 306 | echo -n "Purging the download cache for PLD Linux $release..." 307 | rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 308 | exit 0 309 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld 310 | } 311 | 312 | usage() 313 | { 314 | cat < 317 | [-p|--path=] [-c|--clean] [-R|--release=] [--fqdn=] [-A|--arch=] 318 | [-h|--help] 319 | Mandatory args: 320 | -n,--name container name, used to as an identifier for that container from now on 321 | Optional args: 322 | -p,--path path to where the container will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case 323 | --rootfs path for actual rootfs. 324 | -c,--clean clean the cache 325 | -R,--release PLD Linux release for the new container. if the host is PLD Linux, then it will default to the host's release. 326 | --fqdn fully qualified domain name (FQDN) for DNS and system naming 327 | -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64] 328 | -h,--help print this help 329 | EOF 330 | return 0 331 | } 332 | 333 | options=$(getopt -o hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,fqdn: -- "$@") 334 | if [ $? -ne 0 ]; then 335 | usage $(basename $0) 336 | exit 1 337 | fi 338 | eval set -- "$options" 339 | 340 | while :; do 341 | case "$1" in 342 | -h|--help) usage $0 && exit 0;; 343 | -p|--path) path=$2; shift 2;; 344 | --rootfs) rootfs=$2; shift 2;; 345 | -n|--name) name=$2; shift 2;; 346 | -c|--clean) clean=$2; shift 2;; 347 | -R|--release) release=$2; shift 2;; 348 | --fqdn) utsname=$2; shift 2;; 349 | --) shift 1; break ;; 350 | *) break ;; 351 | esac 352 | done 353 | 354 | if [ ! -z "$clean" -a -z "$path" ]; then 355 | clean || exit 1 356 | exit 0 357 | fi 358 | 359 | if [ -z "${utsname}" ]; then 360 | utsname=${name} 361 | fi 362 | 363 | # This follows a standard "resolver" convention that an FQDN must have 364 | # at least two dots or it is considered a local relative host name. 365 | # If it doesn't, append the dns domain name of the host system. 366 | # 367 | # This changes one significant behavior when running 368 | # "lxc_create -n Container_Name" without using the 369 | # --fqdn option. 370 | # 371 | # Old behavior: 372 | # utsname and hostname = Container_Name 373 | # New behavior: 374 | # utsname and hostname = Container_Name.Domain_Name 375 | 376 | if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then 377 | if [ -n "$(dnsdomainname)" ]; then 378 | utsname=${utsname}.$(dnsdomainname) 379 | fi 380 | fi 381 | 382 | needed_pkgs="" 383 | type poldek >/dev/null 2>&1 384 | if [ $? -ne 0 ]; then 385 | needed_pkgs="poldek $needed_pkgs" 386 | fi 387 | 388 | #type curl >/dev/null 2>&1 389 | #if [ $? -ne 0 ]; then 390 | # needed_pkgs="curl $needed_pkgs" 391 | #fi 392 | 393 | if [ -n "$needed_pkgs" ]; then 394 | echo "Missing commands: $needed_pkgs" 395 | echo "Please install these using \"sudo poldek -u $needed_pkgs\"" 396 | exit 1 397 | fi 398 | 399 | if [ -z "$path" ]; then 400 | path=$default_path/$name 401 | fi 402 | 403 | if [ -z "$release" ]; then 404 | if [ "$is_pld" -a "$pld_host_ver" ]; then 405 | release=$pld_host_ver 406 | else 407 | echo "This is not a PLD Linux host and release missing, defaulting to 3.0. use -R|--release to specify release" 408 | release=3.0 409 | fi 410 | fi 411 | 412 | # pld th have systemd. We need autodev enabled to keep systemd from causing problems. 413 | if [ $release = 3.0 ]; then 414 | auto_dev="0" 415 | else 416 | auto_dev="0" 417 | fi 418 | 419 | if [ "$(id -u)" != "0" ]; then 420 | echo "This script should be run as 'root'" 421 | exit 1 422 | fi 423 | 424 | if [ -z "$rootfs" ]; then 425 | rootfs_path=$path/rootfs 426 | # check for 'lxc.rootfs.path' passed in through default config by lxc-create 427 | # TODO: should be lxc.rootfs.mount used instead? 428 | if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then 429 | rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) 430 | fi 431 | else 432 | rootfs_path=$rootfs 433 | fi 434 | config_path=$default_path/$name 435 | cache=$cache_base/$release 436 | 437 | revert() 438 | { 439 | echo "Interrupted, so cleaning up" 440 | lxc-destroy -n $name 441 | # maybe was interrupted before copy config 442 | rm -rf $path 443 | rm -rf $default_path/$name 444 | echo "exiting..." 445 | exit 1 446 | } 447 | 448 | trap revert SIGHUP SIGINT SIGTERM 449 | 450 | copy_configuration 451 | if [ $? -ne 0 ]; then 452 | echo "Failed write configuration file" 453 | exit 1 454 | fi 455 | 456 | install_pld 457 | if [ $? -ne 0 ]; then 458 | echo "Failed to install PLD Linux" 459 | exit 1 460 | fi 461 | 462 | configure_pld 463 | if [ $? -ne 0 ]; then 464 | echo "Failed to configure PLD Linux for a container" 465 | exit 1 466 | fi 467 | 468 | # If the systemd configuration directory exists - set it up for what we need. 469 | if [ -d ${rootfs_path}/etc/systemd/system ]; then 470 | configure_pld_systemd 471 | fi 472 | 473 | # This configuration (rc.sysinit) is not inconsistent with the systemd stuff 474 | # above and may actually coexist on some upgraded systems. Let's just make 475 | # sure that, if it exists, we update this file, even if it's not used... 476 | if [ -f ${rootfs_path}/etc/rc.sysinit ]; then 477 | configure_pld_init 478 | fi 479 | 480 | if [ ! -z $clean ]; then 481 | clean || exit 1 482 | exit 0 483 | fi 484 | echo "container rootfs and config created" 485 | -------------------------------------------------------------------------------- /templates/lxc-plamo.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | # 4 | # template script for generating Plamo Linux container for LXC 5 | # 6 | 7 | # 8 | # lxc: linux Container library 9 | 10 | # Authors: 11 | # KATOH Yasufumi 12 | # TAMUKI Shoichi 13 | 14 | # This library is free software; you can redistribute it and/or 15 | # modify it under the terms of the GNU Lesser General Public 16 | # License as published by the Free Software Foundation; either 17 | # version 2.1 of the License, or (at your option) any later version. 18 | 19 | # This library is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | # Lesser General Public License for more details. 23 | 24 | # You should have received a copy of the GNU Lesser General Public 25 | # License along with this library; if not, write to the Free Software 26 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | # ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware 29 | # lxc-ubuntu script 30 | 31 | # Detect use under userns (unsupported) 32 | for arg in "$@"; do 33 | [ "$arg" = "--" ] && break 34 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 35 | echo "This template can't be used for unprivileged containers." 1>&2 36 | echo "You may want to try the \"download\" template instead." 1>&2 37 | exit 1 38 | fi 39 | done 40 | 41 | # Make sure the usual locations are in PATH 42 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 43 | 44 | [ -r /etc/default/lxc ] && . /etc/default/lxc 45 | 46 | download_plamo() { 47 | # check the mini plamo was not already downloaded 48 | if ! mkdir -p $ptcache ; then 49 | echo "Failed to create '$ptcache' directory." 50 | return 1 51 | fi 52 | # download a mini plamo into a cache 53 | echo "Downloading Plamo-$release minimal..." 54 | cd $ptcache 55 | case $DLSCHEME in 56 | http|https) depth=2 ;; 57 | ftp) depth=3 ;; 58 | esac 59 | rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*" 60 | if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then 61 | for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done 62 | fi 63 | for i in $CATEGORIES ; do 64 | wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz,.tzst -R "$rej" \ 65 | -I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \ 66 | -X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \ 67 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i 68 | if [ $? -ne 0 ] ; then 69 | echo "Failed to download the rootfs, aborting." 70 | return 1 71 | fi 72 | done 73 | for i in $EXTRACTGRS ; do 74 | wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz,.tzst -R "$rej" \ 75 | -I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \ 76 | -X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \ 77 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i 78 | if [ $? -ne 0 ] ; then 79 | echo "Failed to download the rootfs, aborting." 80 | return 1 81 | fi 82 | done 83 | for p in $ADDONPKGS ; do 84 | wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \ 85 | -I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \ 86 | -X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \ 87 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p` 88 | if [ $? -ne 0 ] ; then 89 | echo "Failed to download the rootfs, aborting." 90 | return 1 91 | fi 92 | done 93 | mv $ptcache $dlcache 94 | echo "Download complete." 95 | return 0 96 | } 97 | 98 | copy_plamo() { 99 | # make a local copy of the mini plamo 100 | echo "Copying $rtcache to $rootfs..." 101 | mkdir -p $rootfs 102 | find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1 103 | return 0 104 | } 105 | 106 | install_plamo() { 107 | mkdir -p @LOCALSTATEDIR@/lock/subsys 108 | ( 109 | if ! flock -n 9 ; then 110 | echo "Cache repository is busy." 111 | return 1 112 | fi 113 | echo "Checking cache download in $dlcache..." 114 | if [ ! -d $dlcache ] ; then 115 | if ! download_plamo ; then 116 | echo "Failed to download plamo $release base packages." 117 | return 1 118 | fi 119 | fi 120 | # install "installpkg" command temporarily with static linked tar 121 | # command into the lxc cache directory to keep the original uid/ 122 | # gid of files/directories. 123 | echo "Installing 'installpkg' command into $dlcache/sbin..." 124 | 125 | if [ $majorver -ge 7 ]; then 126 | pkgtool="pkgtools" 127 | pkgtool=$( cd $dlcache ; ls "$pkgtool"* ) 128 | pkgtool=${pkgtool%%-*} 129 | pkgtool=${pkgtool:0:-1} 130 | else 131 | pkgtool="hdsetup" 132 | LANG=C 133 | fi 134 | 135 | ( cd $dlcache ; tar xpf "$pkgtool"*-*.t*z* ; rm -rf tmp usr var ) 136 | if [ $pkgtool = "pkgtools" ]; then 137 | ( cd $dlcache/sbin 138 | mv installer_new installer 139 | pkg_scripts="installpkg installpkg2 installpkg2.mes makepkg updatepkg removepkg" 140 | for s in $pkg_scripts 141 | do 142 | mv new_"$s" $s 143 | done 144 | cd installer 145 | ln -sf zstd-* zstd 146 | ) 147 | fi 148 | 149 | sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg* 150 | PATH=$dlcache/sbin:$PATH 151 | echo "Installing packages to $rtcache..." 152 | if [ ! -d $rtcache ] ; then 153 | mkdir -p $rtcache 154 | for p in `ls -cr $dlcache/*.t*z*` ; do 155 | installpkg -root $rtcache -priority ADD $p 156 | done 157 | fi 158 | echo "Copy $rtcache to $rootfs..." 159 | if ! copy_plamo ; then 160 | echo "Failed to copy rootfs." 161 | return 1 162 | fi 163 | return 0 164 | ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo 165 | } 166 | 167 | configure_plamo6() { 168 | # suppress log level output for udev 169 | sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf 170 | # /etc/fstab 171 | cat <<- "EOF" > $rootfs/etc/fstab 172 | none /proc proc defaults 0 0 173 | none /sys sysfs defaults 0 0 174 | none /dev tmpfs defaults 0 0 175 | none /tmp tmpfs defaults 0 0 176 | none /dev/pts devpts gid=5,mode=620 0 0 177 | none /proc/bus/usb usbfs noauto 0 0 178 | none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0 179 | EOF 180 | # /etc/inittab 181 | cat <<- "EOF" | patch $rootfs/etc/inittab 182 | 32,33c32,33 183 | < # What to do when power fails (shutdown to single user). 184 | < pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING" 185 | --- 186 | > # What to do when power fails (shutdown). 187 | > pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING" 188 | 47a48 189 | > 1:1235:respawn:/sbin/agetty 38400 console 190 | 52,53d52 191 | < c5:1235:respawn:/sbin/agetty 38400 tty5 linux 192 | < c6:12345:respawn:/sbin/agetty 38400 tty6 linux 193 | EOF 194 | # configure the network using the dhcp 195 | echo "DHCP" > $rootfs/var/run/inet1-scheme 196 | 197 | # delete unnecessary process from rc.S 198 | ed - $rootfs/etc/rc.d/rc.S <<- "EOF" 199 | /^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d 200 | /^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d 201 | /^# copy the rules/;/^# Set the hostname/-1d 202 | /^# Check the integrity/;/^# Clean up temporary/-1d 203 | w 204 | EOF 205 | 206 | # delete unnecessary process from rc.M 207 | ed - $rootfs/etc/rc.d/rc.M <<- "EOF" 208 | /^# Screen blanks/;/^# Initialize ip6tables/-1d 209 | /^# Initialize sysctl/;/^echo "Starting services/-1d 210 | /^sync/;/^# All done/-1d 211 | w 212 | EOF 213 | 214 | # delete unnecessary process from rc.6 215 | ed - $rootfs/etc/rc.d/rc.6 <<- "EOF" 216 | /^# Save system time/;/^# Unmount any remote filesystems/-1d 217 | /^# Turn off swap/;/^# See if this is a powerfail situation/-1d 218 | w 219 | EOF 220 | 221 | # /etc/rc.d/rc.inet1.tradnet 222 | head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly 223 | cat <<- EOF >> /tmp/netconfig.rconly 224 | PCMCIA=n 225 | RC=$rootfs/etc/rc.d/rc.inet1.tradnet 226 | IFCONFIG=sbin/ifconfig 227 | ROUTE=sbin/route 228 | INET1SCHEME=var/run/inet1-scheme 229 | IPADDR=127.0.0.1 230 | NETWORK=127.0.0.0 231 | DHCPCD=usr/sbin/dhclient 232 | LOOPBACK=y 233 | make_config_file 234 | EOF 235 | rm -f $rootfs/etc/rc.d/rc.inet1.tradnet 236 | sh /tmp/netconfig.rconly 237 | rm -f /tmp/netconfig.rconly 238 | sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet 239 | # /etc/rc.d/rc.inet2 240 | sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2 241 | sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2 242 | # configure to start only the minimum of service 243 | chmod 644 $rootfs/etc/rc.d/init.d/saslauthd 244 | chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi 245 | rm -f $rootfs/etc/rc.d/init.d/postfix 246 | rm -f $rootfs/var/log/initpkg/shadow 247 | return 0 248 | } 249 | 250 | configure_plamo7() { 251 | # fstab 252 | cat <<- "EOF" >> $rootfs/etc/fstab 253 | proc /proc proc defaults 0 0 254 | tmpfs /run tmpfs defaults 0 0 255 | sysfs /sys sysfs defaults 0 0 256 | tmpfs /tmp tmpfs defaults 0 0 257 | devpts /dev/pts devpts gid=5,mode=620 0 0 258 | usbfs /proc/bus/usb usbfs noauto 0 0 259 | EOF 260 | 261 | # inittab 262 | sed -i -e '/^1:2345/i c:1235:respawn:/sbin/agetty console 38400'\ 263 | -e '/^ca:/a pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING"' \ 264 | -e '/^4:2345/d' \ 265 | -e '/^5:2345/d' \ 266 | -e '/^6:2345/d' $rootfs/etc/inittab 267 | 268 | # tweak init script on startup 269 | remove_init_S="S05modules S10eudev S20swap S30checkfs S35setclock S50eudev_retry S70console" 270 | for f in $remove_init_S 271 | do 272 | rm -f $rootfs/etc/rc.d/rcS.d/"$f" 273 | done 274 | 275 | # remove init script in runlevel3 276 | remove_init="rc3.d/S30sshd 277 | rc6.d/K30sshd rc6.d/K35setclock rc6.d/S65swap rc6.d/S70mountfs 278 | rc0.d/K30sshd rc0.d/K35setclock rc0.d/S65swap rc0.d/S70mountfs" 279 | for f in $remove_init 280 | do 281 | rm -f $rootfs/etc/rc.d/"$f" 282 | done 283 | 284 | # Tweak rc script 285 | sed -i -e '/wait_for_user/d' \ 286 | -e '/Press Enter to/d' \ 287 | $rootfs/etc/rc.d/init.d/rc 288 | 289 | # network 290 | cat <<- "EOF" > $rootfs/etc/sysconfig/ifconfig.eth0 291 | ONBOOT="yes" 292 | IFACE="eth0" 293 | SERVICE="dhclient" 294 | EOF 295 | 296 | # remove initpkg that do not execute on containers 297 | noexec="shadow netconfig7 eudev openssh" 298 | for f in $noexec 299 | do 300 | rm -f $rootfs/var/log/initpkg/"$f" 301 | done 302 | } 303 | 304 | configure_plamo() { 305 | # set the hostname 306 | echo "$name" > $rootfs/etc/HOSTNAME 307 | # set minimal hosts 308 | echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts 309 | # localtime (JST) 310 | ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime 311 | # disable pam_loginuid.so in /etc/pam.d/login 312 | sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login 313 | if [ $majorver -ge 7 ]; then 314 | configure_plamo7 315 | else 316 | configure_plamo6 317 | fi 318 | } 319 | 320 | copy_configuration() { 321 | ret=0 322 | cat <<- EOF >> $path/config || let ret++ 323 | lxc.uts.name = $name 324 | lxc.arch = $arch 325 | EOF 326 | if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then 327 | cat <<- "EOF" >> $path/config || let ret++ 328 | 329 | lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf 330 | EOF 331 | fi 332 | if [ $ret -ne 0 ] ; then 333 | echo "Failed to add configuration." 334 | return 1 335 | fi 336 | return 0 337 | } 338 | 339 | post_process() { 340 | # nothing do in Plamo Linux 341 | true 342 | } 343 | 344 | do_bindhome() { 345 | # bind-mount the user's path into the container's /home 346 | h=`getent passwd $bindhome | cut -d: -f6` 347 | mkdir -p $rootfs/$h 348 | echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config 349 | # copy /etc/passwd, /etc/shadow, and /etc/group entries into container 350 | if ! pwd=`getent passwd $bindhome` ; then 351 | echo "Warning: failed to copy password entry for $bindhome." 352 | else 353 | echo $pwd >> $rootfs/etc/passwd 354 | fi 355 | echo `getent shadow $bindhome` >> $rootfs/etc/shadow 356 | } 357 | 358 | cleanup() { 359 | [ -d $dlcache -a -d $rtcache ] || return 0 360 | # lock, so we won't purge while someone is creating a repository 361 | ( 362 | if ! flock -n 9 ; then 363 | echo "Cache repository is busy." 364 | return 1 365 | fi 366 | echo "Purging the download cache..." 367 | rm -rf --one-file-system $dlcache $rtcache || return 1 368 | echo "Done." 369 | return 0 370 | ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo 371 | } 372 | 373 | usage() { 374 | cat <<- EOF 375 | $prog [-h|--help] -p|--path= -n|--name= --rootfs= 376 | [-c|--clean] [-r|--release=] [-a|--arch=] 377 | [-b|--bindhome=] 378 | release: $release 379 | arch: x86 or x86_64: defaults to host arch 380 | bindhome: bind 's home into the container 381 | EOF 382 | } 383 | 384 | prog=`basename $0` 385 | path="" ; name="" ; rootfs="" 386 | clean=0 387 | release=${release:-7.x} 388 | arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch 389 | bindhome="" 390 | sopts=hp:n:cr:a:b: 391 | lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome: 392 | if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then 393 | usage 394 | exit 1 395 | fi 396 | eval set -- "$options" 397 | while true ; do 398 | case "$1" in 399 | -h|--help) usage && exit 0 ;; 400 | -p|--path) path=$2 ; shift 2 ;; 401 | -n|--name) name=$2 ; shift 2 ;; 402 | --rootfs) rootfs=$2 ; shift 2 ;; 403 | -c|--clean) clean=1 ; shift 1 ;; 404 | -r|--release) release=$2 ; shift 2 ;; 405 | -a|--arch) arch=$2 ; shift 2 ;; 406 | -b|--bindhome) bindhome=$2 ; shift 2 ;; 407 | --) shift 1 ; break ;; 408 | *) break ;; 409 | esac 410 | done 411 | if [ $clean -eq 1 -a -z "$path" ] ; then 412 | cleanup || exit 1 413 | exit 0 414 | fi 415 | if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then 416 | echo "Can't create x86_64 container on x86." 417 | exit 1 418 | fi 419 | if [ -z "$path" ] ; then 420 | echo "'path' parameter is required." 421 | exit 1 422 | fi 423 | if [ -z "$name" ] ; then 424 | echo "'name' parameter is required." 425 | exit 1 426 | fi 427 | if [ `id -u` -ne 0 ] ; then 428 | echo "This script should be run as 'root'." 429 | exit 1 430 | fi 431 | 432 | majorver=${release%.*} 433 | if [ $majorver -ge 7 ]; then 434 | CATEGORIES=${CATEGORIES-"00_base"} 435 | ADDONPKGS=${ADDONPKGS-""} 436 | else 437 | CATEGORIES=${CATEGORIES-"00_base 01_minimum"} 438 | ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"} 439 | fi 440 | 441 | DLSCHEME=${DLSCHEME:-"https"} 442 | MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"} 443 | MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"} 444 | CATEGORIES=${CATEGORIES-"00_base 01_minimum"} 445 | EXTRACTGRS=${EXTRACTGRS-""} 446 | IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl 447 | linux_firmwares cpufreqd cpufrequtils gpm ntp kmod kmscon"} 448 | ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"} 449 | 450 | cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}" 451 | ptcache=$cache/partial-${prog##*-}-$release-$arch 452 | dlcache=$cache/cache-${prog##*-}-$release-$arch 453 | rtcache=$cache/rootfs-${prog##*-}-$release-$arch 454 | if [ -z "$rootfs" ] ; then 455 | if grep -q "^lxc.rootfs.path" $path/config ; then 456 | rootfs=`awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config` 457 | else 458 | rootfs=$path/rootfs 459 | fi 460 | fi 461 | if ! install_plamo ; then 462 | echo "Failed to install plamo $release." 463 | exit 1 464 | fi 465 | if ! configure_plamo ; then 466 | echo "Failed to configure plamo $release for a container." 467 | exit 1 468 | fi 469 | if ! copy_configuration ; then 470 | echo "Failed to write configuration file." 471 | exit 1 472 | fi 473 | post_process 474 | if [ -n "$bindhome" ] ; then 475 | do_bindhome 476 | fi 477 | if [ $clean -eq 1 ] ; then 478 | cleanup || exit 1 479 | exit 0 480 | fi 481 | -------------------------------------------------------------------------------- /templates/lxc-altlinux.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # template script for generating altlinux container for LXC 5 | # 6 | 7 | # 8 | # lxc: linux Container library 9 | 10 | # Authors: 11 | # Alexey Shabalin 12 | 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 | 27 | # Detect use under userns (unsupported) 28 | for arg in "$@"; do 29 | [ "$arg" = "--" ] && break 30 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then 31 | echo "This template can't be used for unprivileged containers." 1>&2 32 | echo "You may want to try the \"download\" template instead." 1>&2 33 | exit 1 34 | fi 35 | done 36 | 37 | # Make sure the usual locations are in PATH 38 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 39 | 40 | #Configurations 41 | arch=$(uname -m) 42 | cache_base=@LOCALSTATEDIR@/cache/lxc/altlinux/$arch 43 | default_path=@LXCPATH@ 44 | default_profile=default 45 | profile_dir=/etc/lxc/profiles 46 | lxc_network_type=veth 47 | lxc_network_link=virbr0 48 | 49 | # is this altlinux? 50 | [ -f /etc/altlinux-release ] && is_altlinux=true 51 | 52 | configure_altlinux() 53 | { 54 | 55 | # disable selinux in altlinux 56 | mkdir -p $rootfs_path/selinux 57 | echo 0 > $rootfs_path/selinux/enforce 58 | 59 | mkdir -p ${rootfs_path}/etc/net/ifaces/eth0 60 | cat < ${rootfs_path}/etc/net/ifaces/eth0/options 61 | BOOTPROTO=${BOOTPROTO} 62 | ONBOOT=yes 63 | NM_CONTROLLED=yes 64 | TYPE=eth 65 | EOF 66 | 67 | if [ ${BOOTPROTO} != "dhcp" ]; then 68 | # ip address 69 | cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4address 70 | ${ipv4} 71 | EOF 72 | 73 | cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv4route 74 | ${gw} 75 | EOF 76 | 77 | cat < ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf 78 | nameserver ${dns} 79 | EOF 80 | 81 | cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6address 82 | ${ipv6} 83 | EOF 84 | 85 | cat < ${rootfs_path}/etc/net/ifaces/eth0/ipv6route 86 | ${gw6} 87 | EOF 88 | 89 | fi 90 | 91 | # set the hostname 92 | cat < ${rootfs_path}/etc/sysconfig/network 93 | NETWORKING=yes 94 | CONFMETHOD=etcnet 95 | HOSTNAME=${UTSNAME} 96 | RESOLV_MODS=yes 97 | EOF 98 | 99 | # set minimal hosts 100 | cat < $rootfs_path/etc/hosts 101 | 127.0.0.1 localhost.localdomain localhost $name 102 | EOF 103 | # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd. 104 | # sed -i 's/^.*loginuid.so.*$/\#&/' ${rootfs_path}/etc/pam.d/common-login 105 | 106 | # Allow root to login at virsh console 107 | echo "pts/0" >> ${rootfs_path}/etc/securetty 108 | echo "console" >> ${rootfs_path}/etc/securetty 109 | 110 | # Enable services 111 | for service in network syslogd random NetworkManager 112 | do 113 | chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service on || true 114 | # For systemd 115 | chroot ${rootfs_path} systemctl -q enable $service &>/dev/null|| true 116 | done 117 | # Disable services 118 | for service in rawdevices fbsetfont 119 | do 120 | chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service off || true 121 | chroot ${rootfs_path} systemctl -q disable $service &>/dev/null || true 122 | done 123 | 124 | subst 's/^\([3-9]\+:[0-9]\+:respawn:\/sbin\/mingetty.*\)/#\1/' ${rootfs_path}/etc/inittab 125 | echo "c1:2345:respawn:/sbin/mingetty --noclear console" >> ${rootfs_path}/etc/inittab 126 | 127 | [ -f "${rootfs_path}/etc/syslog.conf" ] && \ 128 | subst 's,\/dev\/tty12,/var/log/syslog/console,' ${rootfs_path}/etc/syslog.conf 129 | 130 | dev_path="${rootfs_path}/dev" 131 | rm -rf ${dev_path} 132 | mkdir -p ${dev_path} 133 | mknod -m 666 ${dev_path}/null c 1 3 134 | mknod -m 666 ${dev_path}/zero c 1 5 135 | mknod -m 644 ${dev_path}/random c 1 8 136 | mknod -m 644 ${dev_path}/urandom c 1 9 137 | mkdir -m 755 ${dev_path}/pts 138 | mkdir -m 1777 ${dev_path}/shm 139 | mknod -m 666 ${dev_path}/tty c 5 0 140 | chown root:tty ${dev_path}/tty 141 | mknod -m 600 ${dev_path}/tty0 c 4 0 142 | mknod -m 600 ${dev_path}/tty1 c 4 1 143 | mknod -m 600 ${dev_path}/tty2 c 4 2 144 | mknod -m 600 ${dev_path}/tty3 c 4 3 145 | mknod -m 600 ${dev_path}/tty4 c 4 4 146 | mknod -m 600 ${dev_path}/console c 5 1 147 | mknod -m 666 ${dev_path}/full c 1 7 148 | mknod -m 600 ${dev_path}/initctl p 149 | mknod -m 666 ${dev_path}/ptmx c 5 2 150 | chown root:tty ${dev_path}/ptmx 151 | ln -s /proc/self/fd ${dev_path}/fd 152 | ln -s /proc/kcore ${dev_path}/core 153 | mkdir -m 755 ${dev_path}/mapper 154 | mknod -m 600 ${dev_path}/mapper/control c 10 236 155 | mkdir -m 755 ${dev_path}/net 156 | mknod -m 666 ${dev_path}/net/tun c 10 200 157 | 158 | if [ -n "${root_password}" ]; then 159 | echo "setting root passwd to $root_password" 160 | echo "root:$root_password" | chroot $rootfs_path chpasswd 161 | fi 162 | 163 | return 0 164 | } 165 | 166 | download_altlinux() 167 | { 168 | 169 | if [ -z "$aptconfver" ]; then 170 | case "$release" in 171 | sisyphus) 172 | aptconfver=apt-conf-sisyphus ;; 173 | *) 174 | aptconfver=apt-conf-branch ;; 175 | esac 176 | fi 177 | 178 | # check the mini altlinux was not already downloaded 179 | INSTALL_ROOT=$cache/partial 180 | mkdir -p $INSTALL_ROOT 181 | if [ $? -ne 0 ]; then 182 | echo "Failed to create '$INSTALL_ROOT' directory" 183 | return 1 184 | fi 185 | 186 | # download a mini altlinux into a cache 187 | echo "Downloading altlinux minimal ..." 188 | APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y" 189 | PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")" 190 | # if no configuration file $profile -- fall back to default list of packages 191 | [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt $aptconfver etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon" 192 | 193 | mkdir -p $INSTALL_ROOT/var/lib/rpm 194 | rpm --root $INSTALL_ROOT --initdb 195 | 196 | # some scripts want to have /dev/null at least 197 | dev_path="$INSTALL_ROOT/dev" 198 | if [ ! -c "${dev_path}/null" ]; then 199 | mkdir -p "${dev_path}" 200 | mknod -m 666 "${dev_path}/null" c 1 3 201 | fi 202 | 203 | $APT_GET install $PKG_LIST 204 | 205 | if [ $? -ne 0 ]; then 206 | echo "Failed to download the rootfs, aborting." 207 | return 1 208 | fi 209 | 210 | mv "$INSTALL_ROOT" "$cache/rootfs" 211 | echo "Download complete." 212 | 213 | return 0 214 | } 215 | 216 | copy_altlinux() 217 | { 218 | 219 | # make a local copy of the minialtlinux 220 | echo -n "Copying rootfs to $rootfs_path ..." 221 | #cp -a $cache/rootfs-$arch $rootfs_path || return 1 222 | # i prefer rsync (no reason really) 223 | mkdir -p $rootfs_path 224 | rsync -SHaAX $cache/rootfs/ $rootfs_path/ 225 | return 0 226 | } 227 | 228 | update_altlinux() 229 | { 230 | chroot $cache/rootfs apt-get update 231 | chroot $cache/rootfs apt-get -y dist-upgrade 232 | } 233 | 234 | install_altlinux() 235 | { 236 | mkdir -p @LOCALSTATEDIR@/lock/subsys/ 237 | ( 238 | flock -x 9 239 | if [ $? -ne 0 ]; then 240 | echo "Cache repository is busy." 241 | return 1 242 | fi 243 | 244 | echo "Checking cache download in $cache/rootfs ... " 245 | if [ ! -e "$cache/rootfs" ]; then 246 | download_altlinux 247 | if [ $? -ne 0 ]; then 248 | echo "Failed to download 'altlinux base'" 249 | return 1 250 | fi 251 | else 252 | echo "Cache found. Updating..." 253 | update_altlinux 254 | if [ $? -ne 0 ]; then 255 | echo "Failed to update 'altlinux base', continuing with last known good cache" 256 | else 257 | echo "Update finished" 258 | fi 259 | fi 260 | 261 | echo "Copy $cache/rootfs to $rootfs_path ... " 262 | copy_altlinux 263 | if [ $? -ne 0 ]; then 264 | echo "Failed to copy rootfs" 265 | return 1 266 | fi 267 | return 0 268 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux 269 | 270 | return $? 271 | } 272 | 273 | copy_configuration() 274 | { 275 | 276 | mkdir -p $config_path 277 | grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config 278 | cat <> $config_path/config 279 | lxc.uts.name = $name 280 | lxc.tty.max = 4 281 | lxc.pty.max = 1024 282 | lxc.cap.drop = sys_module mac_admin mac_override sys_time 283 | 284 | # When using LXC with apparmor, uncomment the next line to run unconfined: 285 | #lxc.apparmor.profile = unconfined 286 | 287 | #networking 288 | #lxc.net.0.type = $lxc_network_type 289 | #lxc.net.0.flags = up 290 | #lxc.net.0.link = $lxc_network_link 291 | #lxc.net.0.name = veth0 292 | #lxc.net.0.mtu = 1500 293 | EOF 294 | if [ ! -z ${ipv4} ]; then 295 | cat <> $config_path/config 296 | lxc.net.0.ipv4.address = $ipv4 297 | EOF 298 | fi 299 | if [ ! -z ${gw} ]; then 300 | cat <> $config_path/config 301 | lxc.net.0.ipv4.gateway = $gw 302 | EOF 303 | fi 304 | if [ ! -z ${ipv6} ]; then 305 | cat <> $config_path/config 306 | lxc.net.0.ipv6.address = $ipv6 307 | EOF 308 | fi 309 | if [ ! -z ${gw6} ]; then 310 | cat <> $config_path/config 311 | lxc.net.0.ipv6.gateway = $gw6 312 | EOF 313 | fi 314 | cat <> $config_path/config 315 | #cgroups 316 | lxc.cgroup.devices.deny = a 317 | # /dev/null and zero 318 | lxc.cgroup.devices.allow = c 1:3 rwm 319 | lxc.cgroup.devices.allow = c 1:5 rwm 320 | # consoles 321 | lxc.cgroup.devices.allow = c 5:1 rwm 322 | lxc.cgroup.devices.allow = c 5:0 rwm 323 | lxc.cgroup.devices.allow = c 4:0 rwm 324 | lxc.cgroup.devices.allow = c 4:1 rwm 325 | # /dev/{,u}random 326 | lxc.cgroup.devices.allow = c 1:9 rwm 327 | lxc.cgroup.devices.allow = c 1:8 rwm 328 | lxc.cgroup.devices.allow = c 136:* rwm 329 | lxc.cgroup.devices.allow = c 5:2 rwm 330 | # rtc 331 | lxc.cgroup.devices.allow = c 10:135 rwm 332 | 333 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed 334 | EOF 335 | 336 | if [ $? -ne 0 ]; then 337 | echo "Failed to add configuration" 338 | return 1 339 | fi 340 | 341 | return 0 342 | } 343 | 344 | clean() 345 | { 346 | 347 | if [ ! -e $cache ]; then 348 | exit 0 349 | fi 350 | 351 | # lock, so we won't purge while someone is creating a repository 352 | ( 353 | flock -x 9 354 | if [ $? != 0 ]; then 355 | echo "Cache repository is busy." 356 | exit 1 357 | fi 358 | 359 | echo -n "Purging the download cache for ALTLinux-$release..." 360 | rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 361 | exit 0 362 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux 363 | } 364 | 365 | usage() 366 | { 367 | cat < 370 | [-p|--path=] [-c|--clean] [-R|--release=] 371 | [-4|--ipv4=] [-6|--ipv6=] 372 | [-g|--gw=] [-d|--dns=] 373 | [-P|--profile=] [--rootfs=] 374 | [-a|--apt-conf=] 375 | [-A|--arch=] 376 | [-h|--help] 377 | Mandatory args: 378 | -n,--name container name, used to as an identifier for that container from now on 379 | Optional args: 380 | -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case 381 | -c,--clean clean the cache 382 | -R,--release ALTLinux release for the new container. if the host is ALTLinux, then it will defaultto the host's release. 383 | -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 384 | -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 385 | -g,--gw specify the default gw, eg. 192.168.1.1 386 | -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 387 | -d,--dns specify the DNS server, eg. 192.168.1.2 388 | -a,--apt-conf specify preferred 'apt-conf' package, eg. 'apt-conf-branch' 389 | -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. 390 | -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64] 391 | ---rootfs rootfs path 392 | -h,--help print this help 393 | EOF 394 | return 0 395 | } 396 | 397 | options=$(getopt -o hp:n:P:cR:4:6:g:d:a: -l help,rootfs:,path:,name:,profile:,clean,release:,ipv4:,ipv6:,gw:,dns:,apt-conf: -- "$@") 398 | if [ $? -ne 0 ]; then 399 | usage $(basename $0) 400 | exit 1 401 | fi 402 | eval set -- "$options" 403 | 404 | while true 405 | do 406 | case "$1" in 407 | -h|--help) usage $0 && exit 0;; 408 | -p|--path) path=$2; shift 2;; 409 | --rootfs) rootfs_path=$2; shift 2;; 410 | -n|--name) name=$2; shift 2;; 411 | -P|--profile) profile=$2; shift 2;; 412 | -c|--clean) clean=1; shift 1;; 413 | -R|--release) release=$2; shift 2;; 414 | -4|--ipv4) ipv4=$2; shift 2;; 415 | -6|--ipv6) ipv6=$2; shift 2;; 416 | -g|--gw) gw=$2; shift 2;; 417 | -d|--dns) dns=$2; shift 2;; 418 | -a|--apt-conf) aptconfver=$2; shift 2;; 419 | --) shift 1; break ;; 420 | *) break ;; 421 | esac 422 | done 423 | 424 | if [ ! -z "$clean" -a -z "$path" ]; then 425 | clean || exit 1 426 | exit 0 427 | fi 428 | 429 | type apt-get >/dev/null 2>&1 430 | if [ $? -ne 0 ]; then 431 | echo "'apt-get' command is missing" 432 | exit 1 433 | fi 434 | 435 | if [ -z "$path" ]; then 436 | path=$default_path 437 | fi 438 | 439 | if [ -z "$profile" ]; then 440 | profile=$default_profile 441 | fi 442 | 443 | if [ -z "$release" ]; then 444 | if [ "$is_altlinux" ]; then 445 | release=$(cat /etc/altlinux-release |awk '/^ALT/ {print $3}') 446 | else 447 | echo "This is not a ALTLinux host and release missing, use -R|--release to specify release" 448 | exit 1 449 | fi 450 | fi 451 | 452 | if [ -z "$ipv4" -a -z "$ipv6" ]; then 453 | BOOTPROTO="dhcp" 454 | else 455 | BOOTPROTO="static" 456 | fi 457 | 458 | if [ "$(id -u)" != "0" ]; then 459 | echo "This script should be run as 'root'" 460 | exit 1 461 | fi 462 | 463 | # check for 'lxc.rootfs.path' passed in through default config by lxc-create 464 | if [ -z "$rootfs_path" ]; then 465 | if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then 466 | rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) 467 | else 468 | rootfs_path=$path/rootfs 469 | fi 470 | fi 471 | 472 | config_path=$default_path/$name 473 | cache=$cache_base/$release/$profile 474 | 475 | install_altlinux 476 | if [ $? -ne 0 ]; then 477 | echo "failed to install altlinux" 478 | exit 1 479 | fi 480 | 481 | configure_altlinux 482 | if [ $? -ne 0 ]; then 483 | echo "failed to configure altlinux for a container" 484 | exit 1 485 | fi 486 | 487 | copy_configuration 488 | if [ $? -ne 0 ]; then 489 | echo "failed write configuration file" 490 | exit 1 491 | fi 492 | 493 | if [ ! -z "$clean" ]; then 494 | clean || exit 1 495 | exit 0 496 | fi 497 | echo "container rootfs and config created" 498 | echo "network configured as $lxc_network_type in the $lxc_network_link" 499 | -------------------------------------------------------------------------------- /templates/lxc-sabayon.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # vim: set ts=4 sw=4 expandtab 3 | 4 | # Exit on error and treat unset variables as an error. 5 | set -eu 6 | 7 | # 8 | # LXC template for Sabayon OS, based of Alpine script. 9 | # 10 | 11 | # Authors: 12 | # Geaaru 13 | 14 | # This library is free software; you can redistribute it and/or 15 | # modify it under the terms of the GNU Lesser General Public 16 | # License as published by the Free Software Foundation; either 17 | # version 2.1 of the License, or (at your option) any later version. 18 | # 19 | # This library is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | # Lesser General Public License for more details. 23 | # 24 | # You should have received a copy of the GNU Lesser General Public 25 | # License along with this library; if not, write to the Free Software 26 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | 29 | #=========================== Constants ============================# 30 | 31 | # Make sure the usual locations are in PATH 32 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 33 | 34 | readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@' 35 | readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@' 36 | 37 | 38 | # Temporary static MIRROR LIST. I will get list from online path on the near future. 39 | readonly MIRRORS_LIST=" 40 | http://mirror.it.sabayon.org/ 41 | http://dl.sabayon.org/ 42 | ftp://ftp.klid.dk/sabayonlinux/ 43 | http://ftp.fsn.hu/pub/linux/distributions/sabayon/ 44 | http://ftp.cc.uoc.gr/mirrors/linux/SabayonLinux/ 45 | http://ftp.rnl.ist.utl.pt/pub/sabayon/ 46 | ftp://ftp.nluug.nl/pub/os/Linux/distr/sabayonlinux/ 47 | http://mirror.internode.on.net/pub/sabayon/ 48 | http://mirror.yandex.ru/sabayon/ 49 | http://sabayon.c3sl.ufpr.br/ 50 | http://mirror.clarkson.edu/sabayon/ 51 | http://na.mirror.garr.it/mirrors/sabayonlinux/" 52 | 53 | #======================== Global variables ========================# 54 | 55 | # Clean variables and set defaults. 56 | arch="$(uname -m)" 57 | debug='no' 58 | flush_cache='no' 59 | mirror_url= 60 | name= 61 | path= 62 | release="DAILY" 63 | rootfs= 64 | unprivileged=false 65 | mapped_uid= 66 | mapped_gid= 67 | flush_owner=false 68 | 69 | #======================== Helper Functions ========================# 70 | 71 | usage() { 72 | cat <<-EOF 73 | Template specific options can be passed to lxc-create after a '--' like this: 74 | 75 | lxc-create --name=NAME [lxc-create-options] -- [template-options] 76 | 77 | Template options: 78 | -a ARCH, --arch=ARCH The container architecture (e.g. x86_64, armv7); defaults 79 | to the host arch. 80 | -d, --debug Run this script in a debug mode (set -x and wget w/o -q). 81 | -m URL --mirror=URL The Sabayon mirror to use; defaults to random mirror. 82 | -u, --unprivileged Tuning of rootfs for unprivileged containers. 83 | -r, --release Identify release to use. Default is DAILY. 84 | --mapped-gid Group Id to use on unprivileged container 85 | (based of value present on file /etc/subgid). 86 | --mapped-uid User Id to use on unprivileged container 87 | (based of value present on file /etc/subuid) 88 | --flush-owner Only for directly creation of unprivileged containers 89 | through lxc-create command. Execute fuidshift command. 90 | Require --mapped-gid,--mapped-uid and --unprivileged 91 | options. 92 | 93 | Environment variables: 94 | RELEASE Release version of Sabayon. Default is ${RELEASE}. 95 | EOF 96 | } 97 | 98 | random_mirror_url() { 99 | local url="" 100 | 101 | if [ $arch == 'amd64' ] ; then 102 | url=$(echo $MIRRORS_LIST | sed -e 's/ /\n/g' | sort -R --random-source=/dev/urandom | head -n 1) 103 | else 104 | if [ $arch == 'armv7l' ] ; then 105 | # Currently armv7l tarball is not on sabayon mirrored tree. 106 | url="https://dockerbuilder.sabayon.org/" 107 | fi 108 | fi 109 | 110 | [ -n "$url" ] && echo "$url" 111 | } 112 | 113 | die() { 114 | local retval=$1; shift 115 | 116 | echo -e "==> $@\n" 117 | exit $retval 118 | } 119 | 120 | einfo() { 121 | echo -e "==> $@\n" 122 | } 123 | 124 | fetch() { 125 | if [ "$debug" = 'yes' ]; then 126 | wget -T 10 -O - $@ 127 | else 128 | wget -T 10 -O - -q $@ 129 | fi 130 | } 131 | 132 | parse_arch() { 133 | case "$1" in 134 | x86_64 | amd64) echo 'amd64';; 135 | armv7 | armv7l) echo 'armv7l';; 136 | #arm*) echo 'armhf';; 137 | *) return 1;; 138 | esac 139 | } 140 | 141 | run_exclusively() { 142 | 143 | local lock_name="$1" 144 | local timeout=$2 145 | local method=$3 146 | shift 3 147 | 148 | mkdir -p "$LOCAL_STATE_DIR/lock/subsys" 149 | 150 | local retval 151 | { 152 | echo -n "Obtaining an exclusive lock..." 153 | if ! flock -x 9; then 154 | echo ' failed.' 155 | return 1 156 | fi 157 | echo ' done' 158 | 159 | ${method} $@ 160 | retval=$? 161 | } 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-sabayon-$lock_name" 162 | 163 | return $retval 164 | } 165 | 166 | create_url () { 167 | 168 | local url="" 169 | # Example of amd64 tarball url 170 | # http://mirror.yandex.ru/sabayon/iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz 171 | 172 | if [ $arch == 'amd64' ] ; then 173 | 174 | if [ $release = 'DAILY' ] ; then 175 | url="${MIRROR_URL}iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz" 176 | else 177 | url="${MIRROR_URL}iso/monthly/Sabayon_Linux_${release}_amd64_tarball.tar.gz" 178 | fi 179 | else 180 | # https://dockerbuilder.sabayon.org/Sabayon_Linux_16_armv7l.tar.bz2 181 | if [ $arch == 'armv7l' ] ; then 182 | 183 | # Currently $arch tarball is not on sabayon mirrored tree. 184 | url="${MIRROR_URL}Sabayon_Linux_16_armv7l.tar.bz2" 185 | 186 | fi 187 | fi 188 | 189 | echo $url 190 | } 191 | 192 | 193 | #=========================== Configure ===========================# 194 | 195 | unprivileged_rootfs() { 196 | 197 | pushd ${rootfs}/etc/systemd/system 198 | 199 | # Disable systemd-journald-audit.socket because it seems that doesn't 200 | # start correctly on unprivileged container 201 | ln -s /dev/null systemd-journald-audit.socket 202 | 203 | # Disable systemd-remount-fs.service because on unprivileged container 204 | # systemd can't remount filesystem 205 | ln -s /dev/null systemd-remount-fs.service 206 | 207 | # Remove mount of FUSE Control File system 208 | ln -s /dev/null sys-fs-fuse-connections.mount 209 | 210 | # Change execution of service systemd-sysctl to avoid errors. 211 | mkdir systemd-sysctl.service.d 212 | cat < systemd-sysctl.service.d/00gentoo.conf 213 | [Service] 214 | ExecStart= 215 | ExecStart=/usr/lib/systemd/systemd-sysctl --prefix=/etc/sysctl.d/ 216 | EOF 217 | 218 | # Disable mount of hugepages 219 | ln -s /dev/null dev-hugepages.mount 220 | 221 | popd 222 | 223 | pushd ${rootfs} 224 | 225 | # Disable sabayon-anti-fork-bomb limits (already apply to lxc container manager) 226 | sed -i -e 's/^*/#*/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1 227 | sed -i -e 's/^root/#root/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1 228 | 229 | popd 230 | 231 | return 0 232 | } 233 | 234 | unprivileged_shift_owner () { 235 | 236 | # I use /usr/bin/fuidshift from LXD project. 237 | 238 | einfo "Executing: fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 ..." 239 | 240 | fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 || 241 | die 1 "Error on change owners of ${rootfs} directory" 242 | 243 | einfo "Done." 244 | 245 | # Fix permission of container directory 246 | chmod a+rx ${path} 247 | 248 | return 0 249 | } 250 | 251 | systemd_container_tuning () { 252 | 253 | # To avoid error on start systemd-tmpfiles-setup service 254 | # it is needed clean journal directory 255 | rm -rf ${rootfs}/var/log/journal/ 256 | 257 | # Remove LVM service. Normally not needed on container system. 258 | rm -rf ${rootfs}/etc/systemd/system/sysinit.target.wants/lvm2-lvmetad.service 259 | 260 | # Comment unneeded entry on /etc/fstab 261 | sed -e 's/\/dev/#\/dev/g' -i ${rootfs}/etc/fstab 262 | 263 | # Fix this stupid error until fix is available on sabayon image 264 | # /usr/lib/systemd/system-generators/gentoo-local-generator: line 4: cd: /etc/local.d: No such file or directory 265 | mkdir -p ${rootfs}/etc/local.d/ 266 | 267 | mkdir -p ${rootfs}/etc/systemd/system/NetworkManager.service.d/ 268 | cat < ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf 269 | [Service] 270 | ExecStartPre=-/bin/ip -4 link set dev eth0 down 271 | EOF 272 | chmod 644 ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf 273 | 274 | return 0 275 | } 276 | 277 | configure_container() { 278 | local config="$1" 279 | local hostname="$2" 280 | local arch="$3" 281 | local privileged_options="" 282 | local unprivileged_options="" 283 | 284 | if [[ $unprivileged && $unprivileged == true ]] ; then 285 | if [[ $flush_owner == true ]] ; then 286 | unprivileged_options=" 287 | lxc.idmap = u 0 ${mapped_uid} 65536 288 | lxc.idmap = g 0 ${mapped_gid} 65536 289 | " 290 | fi 291 | 292 | unprivileged_options=" 293 | $unprivileged_options 294 | 295 | # Force use of cgroup v1. Currently systemd doesn't support 296 | # correctly cgroup v2. See: https://github.com/lxc/lxc/issues/1669 297 | # about discussion of default-hierarchy option. 298 | lxc.init.cmd = /sbin/init systemd.legacy_systemd_cgroup_controller=yes 299 | 300 | # Include common configuration. 301 | lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.userns.conf 302 | " 303 | 304 | else 305 | privileged_options=" 306 | ## Allow any mknod (but not reading/writing the node) 307 | lxc.cgroup.devices.allow = b *:* m 308 | lxc.cgroup.devices.allow = c *:* m 309 | 310 | ### /dev/pts/* 311 | lxc.cgroup.devices.allow = c 136:* rwm 312 | ### /dev/tty 313 | lxc.cgroup.devices.allow = c 5:0 rwm 314 | ### /dev/console 315 | lxc.cgroup.devices.allow = c 5:1 rwm 316 | ### /dev/ptmx 317 | lxc.cgroup.devices.allow = c 5:2 rwm 318 | ### fuse 319 | lxc.cgroup.devices.allow = c 10:229 rwm 320 | 321 | " 322 | fi 323 | 324 | cat <<-EOF >> "$config" 325 | # Specify container architecture. 326 | lxc.arch = $arch 327 | 328 | # Set hostname. 329 | lxc.uts.name = $hostname 330 | 331 | # Include common configuration. 332 | lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.common.conf 333 | 334 | $unprivileged_options 335 | $privileged_options 336 | EOF 337 | } 338 | 339 | 340 | #============================= Main ==============================# 341 | 342 | parse_cmdline() { 343 | 344 | # Parse command options. 345 | local short_options="a:dm:n:p:r:hu" 346 | local long_options="arch:,debug,mirror:,name:,path:,release:,rootfs:,mapped-uid:,mapped-gid:,flush-owner,help" 347 | 348 | options=$(getopt -u -q -a -o "$short_options" -l "$long_options" -- "$@") 349 | 350 | eval set -- "$options" 351 | 352 | # Process command options. 353 | while [ $# -gt 0 ]; do 354 | case $1 in 355 | -a | --arch) 356 | arch=$2 357 | shift 358 | ;; 359 | -d | --debug) 360 | debug='yes' 361 | ;; 362 | -m | --mirror) 363 | mirror_url=$2 364 | shift 365 | ;; 366 | -n | --name) 367 | name=$2 368 | shift 369 | ;; 370 | -p | --path) 371 | path=$2 372 | shift 373 | ;; 374 | -r | --release) 375 | release=$2 376 | shift 377 | ;; 378 | --rootfs) 379 | rootfs=$2 380 | shift 381 | ;; 382 | -u | --unprivileged) 383 | unprivileged=true 384 | ;; 385 | -h | --help) 386 | usage 387 | exit 1 388 | ;; 389 | --mapped-uid) 390 | mapped_uid=$2 391 | shift 392 | ;; 393 | --mapped-gid) 394 | mapped_gid=$2 395 | shift 396 | ;; 397 | --flush-owner) 398 | flush_owner=true 399 | ;; 400 | --) 401 | break 402 | ;; 403 | *) 404 | einfo "Unknown option: $1" 405 | usage 406 | exit 1 407 | ;; 408 | esac 409 | shift 410 | done 411 | 412 | if [ "$(id -u)" != "0" ]; then 413 | die 1 "This script must be run as 'root'" 414 | fi 415 | 416 | # Validate options. 417 | [ -n "$name" ] || die 1 'Missing required option --name' 418 | [ -n "$path" ] || die 1 'Missing required option --path' 419 | 420 | if [ -z "$rootfs" ] && [ -f "$path/config" ]; then 421 | rootfs="$(sed -nE 's/^lxc.rootfs\s*=\s*(.*)$/\1/p' "$path/config")" 422 | fi 423 | if [ -z "$rootfs" ]; then 424 | rootfs="$path/rootfs" 425 | fi 426 | 427 | [ -z "$path" ] && die 1 "'path' parameter is required." 428 | 429 | arch=$(parse_arch "$arch") \ 430 | || die 1 "Unsupported architecture: $arch" 431 | 432 | [[ $unprivileged == true && $flush_owner == true &&-z "$mapped_uid" ]] && \ 433 | die 1 'Missing required option --mapped-uid with --unprivileged option' 434 | 435 | [[ $unprivileged == true && $flush_owner == true && -z "$mapped_gid" ]] && \ 436 | die 1 'Missing required option --mapped-gid with --unprivileged option' 437 | 438 | [[ $flush_owner == true && $unprivileged == false ]] && \ 439 | die 1 'flush-owner require --unprivileged option' 440 | 441 | return 0 442 | } 443 | 444 | main () { 445 | 446 | local tarball="" 447 | 448 | # Set global variables. 449 | RELEASE="${RELEASE:-"DAILY"}" 450 | ARCH="${ARCH:-`uname -m`}" 451 | OS="${OS:-"sabayon"}" 452 | 453 | einfo "Processing command line arguments: $@" 454 | 455 | # Parse command line options 456 | parse_cmdline "$@" 457 | 458 | DEBUG="$debug" 459 | MIRROR_URL="${mirror_url:-$(random_mirror_url)}" 460 | 461 | einfo "Use arch = $arch, mirror_url = $MIRROR_URL, path = $path, name = $name, release = $release, unprivileged = $unprivileged, rootfs = $rootfs, mapped_uid = $mapped_uid, mapped_gid = $mapped_gid, flush_owner = $flush_owner" 462 | 463 | [ "$debug" = 'yes' ] && set -x 464 | 465 | # Download sabayon tarball 466 | tarball=$(create_url) 467 | einfo "Fetching tarball $tarball..." 468 | 469 | # TODO: use only a compression mode 470 | if [ $arch == 'amd64' ] ; then 471 | fetch "${tarball}" | tar -xpz -C "${rootfs}" 472 | else 473 | if [ $arch == 'armv7l' ] ; then 474 | fetch "${tarball}" | tar -xpj -C "${rootfs}" 475 | fi 476 | fi 477 | 478 | einfo "Tarball ${tarball} Extracted." 479 | 480 | systemd_container_tuning 481 | 482 | # Fix container for unprivileged mode. 483 | if [[ $unprivileged == true ]] ; then 484 | unprivileged_rootfs 485 | if [[ $flush_owner == true ]] ; then 486 | unprivileged_shift_owner 487 | fi 488 | fi 489 | 490 | return 0 491 | } 492 | 493 | 494 | einfo "Prepare creation of sabayon container with params: $@ ($#)" 495 | 496 | # Here we go! 497 | run_exclusively 'main' 10 main "$@" 498 | configure_container "$path/config" "$name" "$arch" 499 | 500 | einfo "Container's rootfs and config have been created" 501 | cat <<-EOF 502 | Edit the config file $path/config to check/enable networking setup. 503 | The installed system is preconfigured for a loopback and single network 504 | interface configured via DHCP. 505 | 506 | To start the container, run "lxc-start -n $name". 507 | The root password is not set; to enter the container run "lxc-attach -n $name". 508 | 509 | Note: From kenel >= 4.6 for use unprivileged containers it is needed this mount on host: 510 | 511 | mkdir /sys/fs/cgroup/systemd 512 | mount -t cgroup -o none,name=systemd systemd /sys/fs/cgroup/systemd 513 | EOF 514 | -------------------------------------------------------------------------------- /templates/lxc-alpine.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4: 3 | 4 | # Exit on error and treat unset variables as an error. 5 | set -eu 6 | 7 | # 8 | # LXC template for Alpine Linux 3+ 9 | # 10 | 11 | # Note: Do not replace tabs with spaces, it would break heredocs! 12 | 13 | # Authors: 14 | # Jakub Jirutka 15 | 16 | # This library is free software; you can redistribute it and/or 17 | # modify it under the terms of the GNU Lesser General Public 18 | # License as published by the Free Software Foundation; either 19 | # version 2.1 of the License, or (at your option) any later version. 20 | # 21 | # This library is distributed in the hope that it will be useful, 22 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | # Lesser General Public License for more details. 25 | # 26 | # You should have received a copy of the GNU Lesser General Public 27 | # License along with this library; if not, write to the Free Software 28 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 | 30 | 31 | #=========================== Constants ============================# 32 | 33 | # Make sure the usual locations are in PATH 34 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin 35 | 36 | readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@' 37 | readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@' 38 | readonly LXC_CACHE_DIR="${LXC_CACHE_PATH:-"$LOCAL_STATE_DIR/cache/lxc"}/alpine" 39 | 40 | # SHA256 checksums of GPG keys for APK. 41 | readonly APK_KEYS_SHA256="\ 42 | 9c102bcc376af1498d549b77bdbfa815ae86faa1d2d82f040e616b18ef2df2d4 alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub 43 | ebf31683b56410ecc4c00acd9f6e2839e237a3b62b5ae7ef686705c7ba0396a9 alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub 44 | 1bb2a846c0ea4ca9d0e7862f970863857fc33c32f5506098c636a62a726a847b alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub 45 | 12f899e55a7691225603d6fb3324940fc51cd7f133e7ead788663c2b7eecb00c alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub 46 | 73867d92083f2f8ab899a26ccda7ef63dfaa0032a938620eda605558958a8041 alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub 47 | 9a4cd858d9710963848e6d5f555325dc199d1c952b01cf6e64da2c15deedbd97 alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub 48 | 780b3ed41786772cbc7b68136546fa3f897f28a23b30c72dde6225319c44cfff alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub 49 | 59c01c57b446633249f67c04b115dd6787f4378f183dff2bbf65406df93f176d alpine-devel@lists.alpinelinux.org-5e69ca50.rsa.pub 50 | db0b49163f07ffba64a5ca198bcf1688610b0bd1f0d8d5afeaf78559d73f2278 alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub 51 | 207e4696d3c05f7cb05966aee557307151f1f00217af4143c1bcaf33b8df733f alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub 52 | 128d34d4aec39b0daedea8163cd8dc24dff36fd3d848630ab97eeb1d3084bbb3 alpine-devel@lists.alpinelinux.org-61666e3f.rsa.pub 53 | 10877cce0a935e46ad88cb79e174a2491680508eccda08e92bf04fb9bf37fbc1 alpine-devel@lists.alpinelinux.org-616a9724.rsa.pub 54 | 4a095a9daca86da496a3cd9adcd95ee2197fdbeb84638656d469f05a4d740751 alpine-devel@lists.alpinelinux.org-616abc23.rsa.pub 55 | 0caf5662fde45616d88cfd7021b7bda269a2fcaf311e51c48945a967a609ec0b alpine-devel@lists.alpinelinux.org-616ac3bc.rsa.pub 56 | ebe717d228555aa58133c202314a451f81e71f174781fd7ff8d8970d6cfa60da alpine-devel@lists.alpinelinux.org-616adfeb.rsa.pub 57 | d11f6b21c61b4274e182eb888883a8ba8acdbf820dcc7a6d82a7d9fc2fd2836d alpine-devel@lists.alpinelinux.org-616ae350.rsa.pub 58 | 40a216cbd163f22e5f16a9e0929de7cde221b9cbae8e36aa368b1e128afe0a31 alpine-devel@lists.alpinelinux.org-616db30d.rsa.pub" 59 | 60 | readonly APK_KEYS_URI='https://git.alpinelinux.org/aports/plain/main/alpine-keys/' 61 | readonly DEFAULT_MIRROR_URL='http://dl-cdn.alpinelinux.org/alpine' 62 | 63 | : ${APK_KEYS_DIR:=/etc/apk/keys} 64 | if ! ls "$APK_KEYS_DIR"/alpine* >/dev/null 2>&1; then 65 | APK_KEYS_DIR="$LXC_CACHE_DIR/bootstrap/keys" 66 | fi 67 | readonly APK_KEYS_DIR 68 | 69 | : ${APK:=$(command -v apk || true)} 70 | if [ ! -x "$APK" ]; then 71 | APK="$LXC_CACHE_DIR/bootstrap/sbin/apk.static" 72 | fi 73 | readonly APK 74 | 75 | 76 | #======================== Helper Functions ========================# 77 | 78 | usage() { 79 | cat <<-EOF 80 | Template specific options can be passed to lxc-create after a '--' like this: 81 | 82 | lxc-create --name=NAME [lxc-create-options] -- [template-options] [PKG...] 83 | 84 | PKG Additional APK package(s) to install into the container. 85 | 86 | Template options: 87 | -a ARCH, --arch=ARCH The container architecture (e.g. x86, x86_64); defaults 88 | to the host arch. 89 | -d, --debug Run this script in a debug mode (set -x and wget w/o -q). 90 | -F, --flush-cache Remove cached files before build. 91 | -m URL --mirror=URL The Alpine mirror to use; defaults to $DEFAULT_MIRROR_URL. 92 | -r VER, --release=VER The Alpine release branch to install; default is the 93 | latest stable. 94 | 95 | Environment variables: 96 | APK The apk-tools binary to use when building rootfs. If not set 97 | or not executable and apk is not on PATH, then the script 98 | will download the latest apk-tools-static. 99 | APK_KEYS_DIR Path to directory with GPG keys for APK. If not set and 100 | /etc/apk/keys does not contain alpine keys, then the script 101 | will download the keys from ${APK_KEYS_URI}. 102 | LXC_CACHE_PATH Path to the cache directory where to store bootstrap files 103 | and APK packages. 104 | EOF 105 | } 106 | 107 | die() { 108 | local retval=$1; shift 109 | 110 | printf 'ERROR: %s\n' "$@" 1>&2 111 | exit $retval 112 | } 113 | 114 | einfo() { 115 | printf "\n==> $1\n" 116 | } 117 | 118 | fetch() { 119 | if [ "$DEBUG" = 'yes' ]; then 120 | wget -T 10 -O - $@ 121 | else 122 | wget -T 10 -O - -q $@ 123 | fi 124 | } 125 | 126 | latest_release_branch() { 127 | local arch="$1" 128 | local branch=$(fetch "$MIRROR_URL/latest-stable/releases/$arch/latest-releases.yaml" \ 129 | | sed -En 's/^[ \t]*branch: (.*)$/\1/p' \ 130 | | head -n 1) 131 | [ -n "$branch" ] && echo "$branch" 132 | } 133 | 134 | parse_arch() { 135 | case "$1" in 136 | x86 | i[3-6]86) echo 'x86';; 137 | x86_64 | amd64) echo 'x86_64';; 138 | aarch64 | arm64) echo 'aarch64';; 139 | armv7) echo 'armv7';; 140 | arm*) echo 'armhf';; 141 | ppc64le) echo 'ppc64le';; 142 | *) return 1;; 143 | esac 144 | } 145 | 146 | run_exclusively() { 147 | local lock_name="$1" 148 | local timeout=$2 149 | shift 2 150 | 151 | mkdir -p "$LOCAL_STATE_DIR/lock/subsys" 152 | 153 | local retval 154 | { 155 | echo -n "Obtaining an exclusive lock..." 156 | if ! flock -x 9; then 157 | echo ' failed.' 158 | return 1 159 | fi 160 | echo ' done' 161 | 162 | "$@"; retval=$? 163 | } 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-alpine-$lock_name" 164 | 165 | return $retval 166 | } 167 | 168 | 169 | #============================ Bootstrap ===========================# 170 | 171 | bootstrap() { 172 | if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$LXC_CACHE_DIR/bootstrap" ]; then 173 | einfo 'Cleaning cached bootstrap files' 174 | rm -Rf "$LXC_CACHE_DIR/bootstrap" 175 | fi 176 | 177 | einfo 'Fetching and/or verifying APK keys' 178 | fetch_apk_keys "$APK_KEYS_DIR" 179 | 180 | if [ ! -x "$APK" ]; then 181 | einfo 'Fetching apk-tools static binary' 182 | 183 | local host_arch=$(parse_arch $(uname -m)) 184 | fetch_apk_static "$LXC_CACHE_DIR/bootstrap" "$host_arch" 185 | fi 186 | } 187 | 188 | fetch_apk_keys() { 189 | local dest="$1" 190 | local line keyname 191 | 192 | mkdir -p "$dest" 193 | cd "$dest" 194 | 195 | echo "$APK_KEYS_SHA256" | while read -r line; do 196 | keyname="${line##* }" 197 | if [ ! -s "$keyname" ]; then 198 | fetch "$APK_KEYS_URI/$keyname" > "$keyname" 199 | fi 200 | echo "$line" | sha256sum -c - 201 | done || exit 2 202 | 203 | cd - >/dev/null 204 | } 205 | 206 | find_keyfile() { 207 | ls -1 "$1".alpine-*.pub 2>/dev/null | head -n 1 208 | } 209 | 210 | fetch_apk_static() { 211 | local dest="$1" 212 | local arch="$2" 213 | local pkg_name='apk-tools-static' 214 | 215 | mkdir -p "$dest" 216 | 217 | local pkg_ver=$(fetch "$MIRROR_URL/latest-stable/main/$arch/APKINDEX.tar.gz" \ 218 | | tar -xzO APKINDEX \ 219 | | sed -n "/P:${pkg_name}/,/^$/ s/V:\(.*\)$/\1/p") 220 | 221 | [ -n "$pkg_ver" ] || die 2 "Cannot find a version of $pkg_name in APKINDEX" 222 | 223 | fetch "$MIRROR_URL/latest-stable/main/$arch/${pkg_name}-${pkg_ver}.apk" \ 224 | | tar -xz -C "$dest" sbin/ # --extract --gzip --directory 225 | 226 | local apk=$dest/sbin/apk.static 227 | [ -s "$apk" ] || die 2 'apk.static not found' 228 | 229 | local sigprefix=$apk.SIGN.RSA.sha256 230 | local algorithm=sha256 231 | if ! [ -s "$(find_keyfile "$sigprefix")" ]; then 232 | sigprefix=${sigprefix%.*} 233 | algorithm=sha1 234 | fi 235 | local keyfile=$(find_keyfile "$sigprefix") 236 | if ! openssl dgst -$algorithm \ 237 | -verify "$APK_KEYS_DIR/${keyfile#$sigprefix.}" \ 238 | -signature "$keyfile" \ 239 | "$apk"; then 240 | 241 | rm -f "$apk" 242 | die 2 'Signature verification for apk.static failed' 243 | fi 244 | 245 | # Note: apk doesn't return 0 for --version 246 | local out=$("$apk" --version) 247 | echo "$out" 248 | 249 | [ "${out%% *}" = 'apk-tools' ] || die 3 'apk.static --version failed' 250 | } 251 | 252 | 253 | #============================ Install ============================# 254 | 255 | install() { 256 | local dest="$1" 257 | local arch="$2" 258 | local branch="$3" 259 | local extra_packages="$4" 260 | local apk_cache="$LXC_CACHE_DIR/apk/$arch" 261 | 262 | if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$apk_cache" ]; then 263 | einfo "Cleaning cached APK packages for $arch" 264 | rm -Rf "$apk_cache" 265 | fi 266 | mkdir -p "$apk_cache" 267 | 268 | einfo "Installing Alpine Linux in $dest" 269 | cd "$dest" 270 | 271 | mkdir -p etc/apk 272 | ln -s "$apk_cache" etc/apk/cache 273 | 274 | local repo; for repo in main community; do 275 | echo "$MIRROR_URL/$branch/$repo" >> etc/apk/repositories 276 | done 277 | 278 | install_packages "$arch" "alpine-base $extra_packages" 279 | make_dev_nodes 280 | setup_inittab 281 | setup_hosts 282 | setup_network 283 | setup_services 284 | 285 | chroot . /bin/true \ 286 | || die 3 'Failed to execute /bin/true in chroot, the builded rootfs is broken!' 287 | 288 | rm etc/apk/cache 289 | cd - >/dev/null 290 | } 291 | 292 | install_packages() { 293 | local arch="$1" 294 | local packages="$2" 295 | 296 | $APK --arch="$arch" --root=. --keys-dir="$APK_KEYS_DIR" \ 297 | --update-cache --initdb add $packages 298 | } 299 | 300 | make_dev_nodes() { 301 | mkdir -p -m 755 dev/pts 302 | mkdir -p -m 1777 dev/shm 303 | 304 | local i; for i in $(seq 0 4); do 305 | mknod -m 620 dev/tty$i c 4 $i 306 | chown 0:5 dev/tty$i # root:tty 307 | done 308 | 309 | mknod -m 666 dev/tty c 5 0 310 | chown 0:5 dev/tty # root:tty 311 | mknod -m 666 dev/ptmx c 5 2 312 | chown 0:5 dev/ptmx # root:tty 313 | } 314 | 315 | setup_inittab() { 316 | # Remove unwanted ttys. 317 | sed -i '/^tty[5-9]\:\:.*$/d' etc/inittab 318 | 319 | cat <<-EOF >> etc/inittab 320 | # Main LXC console console 321 | ::respawn:/sbin/getty 38400 console 322 | EOF 323 | } 324 | 325 | setup_hosts() { 326 | # This runscript injects localhost entries with the current hostname 327 | # into /etc/hosts. 328 | cat <<'EOF' > etc/init.d/hosts 329 | #!/sbin/openrc-run 330 | 331 | start() { 332 | local start_tag='# begin generated' 333 | local end_tag='# end generated' 334 | 335 | local content=$( 336 | cat <<-EOF 337 | $start_tag by /etc/init.d/hosts 338 | 127.0.0.1 $(hostname).local $(hostname) localhost 339 | ::1 $(hostname).local $(hostname) localhost 340 | $end_tag 341 | EOF 342 | ) 343 | 344 | if grep -q "^${start_tag}" /etc/hosts; then 345 | # escape \n, busybox sed doesn't like them 346 | content=${content//$'\n'/\\$'\n'} 347 | 348 | sed -ni "/^${start_tag}/ { 349 | a\\${content} 350 | # read and discard next line and repeat until $end_tag or EOF 351 | :a; n; /^${end_tag}/!ba; n 352 | }; p" /etc/hosts 353 | else 354 | printf "$content" >> /etc/hosts 355 | fi 356 | } 357 | EOF 358 | chmod +x etc/init.d/hosts 359 | 360 | # Wipe it, will be generated by the above runscript. 361 | echo -n > etc/hosts 362 | } 363 | 364 | setup_network() { 365 | # Note: loopback is automatically started by LXC. 366 | cat <<-EOF > etc/network/interfaces 367 | auto eth0 368 | iface eth0 inet dhcp 369 | hostname \$(hostname) 370 | EOF 371 | } 372 | 373 | setup_services() { 374 | local svc_name 375 | 376 | # Specify the LXC subsystem. 377 | sed -i 's/^#*rc_sys=.*/rc_sys="lxc"/' etc/rc.conf 378 | 379 | # boot runlevel 380 | for svc_name in bootmisc hosts syslog; do 381 | ln -s /etc/init.d/$svc_name etc/runlevels/boot/$svc_name 382 | done 383 | 384 | # default runlevel 385 | for svc_name in networking cron crond; do 386 | # issue 1164: alpine renamed cron to crond 387 | # Use the one that exists. 388 | if [ -e etc/init.d/$svc_name ]; then 389 | ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name 390 | fi 391 | done 392 | } 393 | 394 | 395 | #=========================== Configure ===========================# 396 | 397 | configure_container() { 398 | local config="$1" 399 | local hostname="$2" 400 | local arch="$3" 401 | 402 | cat <<-EOF >> "$config" 403 | 404 | # Specify container architecture. 405 | lxc.arch = $arch 406 | 407 | # Set hostname. 408 | lxc.uts.name = $hostname 409 | 410 | # If something doesn't work, try to comment this out. 411 | # Dropping sys_admin disables container root from doing a lot of things 412 | # that could be bad like re-mounting lxc fstab entries rw for example, 413 | # but also disables some useful things like being able to nfs mount, and 414 | # things that are already namespaced with ns_capable() kernel checks, like 415 | # hostname(1). 416 | lxc.cap.drop = sys_admin 417 | 418 | # Comment this out if you have to debug processes by tracing. 419 | lxc.cap.drop = sys_ptrace 420 | 421 | # Comment this out if required by your applications. 422 | lxc.cap.drop = setpcap 423 | 424 | # Include common configuration. 425 | lxc.include = $LXC_TEMPLATE_CONFIG/alpine.common.conf 426 | EOF 427 | } 428 | 429 | 430 | #============================= Main ==============================# 431 | 432 | if [ "$(id -u)" != "0" ]; then 433 | die 1 "This script must be run as 'root'" 434 | fi 435 | 436 | # Parse command options. 437 | options=$(getopt -o a:dFm:n:p:r:h -l arch:,debug,flush-cache,mirror:,name:,\ 438 | path:,release:,rootfs:,help,mapped-uid:,mapped-gid: -- "$@") 439 | eval set -- "$options" 440 | 441 | # Clean variables and set defaults. 442 | arch="$(uname -m)" 443 | debug='no' 444 | flush_cache='no' 445 | mirror_url= 446 | name= 447 | path= 448 | release= 449 | rootfs= 450 | 451 | # Process command options. 452 | while [ $# -gt 0 ]; do 453 | case $1 in 454 | -a | --arch) 455 | arch=$2; shift 2 456 | ;; 457 | -d | --debug) 458 | debug='yes'; shift 1 459 | ;; 460 | -F | --flush-cache) 461 | flush_cache='yes'; shift 1 462 | ;; 463 | -m | --mirror) 464 | mirror_url=$2; shift 2 465 | ;; 466 | -n | --name) 467 | name=$2; shift 2 468 | ;; 469 | -p | --path) 470 | path=$2; shift 2 471 | ;; 472 | -r | --release) 473 | release=$2; shift 2 474 | ;; 475 | --rootfs) 476 | rootfs=$2; shift 2 477 | ;; 478 | -h | --help) 479 | usage; exit 0 480 | ;; 481 | --) 482 | shift; break 483 | ;; 484 | --mapped-[ug]id) 485 | die 1 "This template can't be used for unprivileged containers." \ 486 | 'You may want to try the "download" template instead.' 487 | ;; 488 | *) 489 | echo "Unknown option: $1" 1>&2 490 | usage; exit 1 491 | ;; 492 | esac 493 | done 494 | 495 | extra_packages="$@" 496 | 497 | [ "$debug" = 'yes' ] && set -x 498 | 499 | # Set global variables. 500 | readonly DEBUG="$debug" 501 | readonly FLUSH_CACHE="$flush_cache" 502 | readonly MIRROR_URL="${mirror_url:-$DEFAULT_MIRROR_URL}" 503 | 504 | # Validate options. 505 | [ -n "$name" ] || die 1 'Missing required option --name' 506 | [ -n "$path" ] || die 1 'Missing required option --path' 507 | 508 | if [ -z "$rootfs" ] && [ -f "$path/config" ]; then 509 | rootfs="$(sed -nE 's/^lxc.rootfs.path\s*=\s*(.*)$/\1/p' "$path/config")" 510 | fi 511 | if [ -z "$rootfs" ]; then 512 | rootfs="$path/rootfs" 513 | fi 514 | 515 | arch=$(parse_arch "$arch") \ 516 | || die 1 "Unsupported architecture: $arch" 517 | 518 | if [ -z "$release" ]; then 519 | release=$(latest_release_branch "$arch") \ 520 | || die 2 'Failed to resolve Alpine last release branch' 521 | fi 522 | 523 | # Here we go! 524 | run_exclusively 'bootstrap' 10 bootstrap 525 | run_exclusively "$arch" 30 install "$rootfs" "$arch" "$release" "$extra_packages" 526 | configure_container "$path/config" "$name" "$arch" 527 | 528 | einfo "Container's rootfs and config have been created" 529 | cat <<-EOF 530 | Edit the config file $path/config to check/enable networking setup. 531 | The installed system is preconfigured for a loopback and single network 532 | interface configured via DHCP. 533 | 534 | To start the container, run "lxc-start -n $name". 535 | The root password is not set; to enter the container run "lxc-attach -n $name". 536 | EOF 537 | --------------------------------------------------------------------------------