]> git.proxmox.com Git - dab.git/blame - dab
ubuntu: exclude libdrm* and libplymouth* from the base set
[dab.git] / dab
CommitLineData
8ab34b87
DM
1#!/usr/bin/perl -w
2
3use strict;
300bd06d
TL
4use warnings;
5
8ab34b87 6use Getopt::Long;
300bd06d 7
8ab34b87
DM
8use PVE::DAB;
9
10$ENV{'LC_ALL'} = 'C';
11
300bd06d
TL
12my $commands = {
13 'init' => '',
7b3b1a35 14 'bootstrap' => '[--exim] [--include <a[,b..]]>] --exclude [<a[,b..]]>] [--minimal]',
88201924 15 'finalize' => '[--keepmycnf] [--compressor <gz[ip] (default)|zst[d]|zstd-max>]',
300bd06d
TL
16 'veid' => '',
17 'basedir' => '',
18 'packagefile' => '',
19 'list' => '[--verbose]',
20 'task' => '<postgres|mysql|php> [--version] [--password] [--memlimit]',
21 'install' => '<package or *.pkglist file> ...',
22 'exec' => '<cmd> ...',
23 'enter' => '',
24 'clean' => '',
25 'dist-clean' => '',
26 'help' => '',
27};
28
8ab34b87 29sub print_usage {
300bd06d 30 print STDERR "USAGE: dab <command> [parameters]\n\n";
8ab34b87 31
300bd06d
TL
32 for my $cmd (sort keys %$commands) {
33 if (my $opts = $commands->{$cmd}) {
34 print STDERR " dab $cmd $opts\n";
35 } else {
36 print STDERR " dab $cmd\n";
37 }
38 }
39}
8ab34b87 40
b02da6e1
TL
41sub fatal_usage {
42 my ($msg) = @_;
43
44 print STDERR "\nERROR: $msg\n\n" if $msg;
45 print_usage();
46
8ab34b87
DM
47 exit (-1);
48}
49
b02da6e1
TL
50if (scalar (@ARGV) == 0) {
51 fatal_usage("no command specified");
52}
53
8ab34b87 54my $cmdline = join (' ', @ARGV);
8ab34b87
DM
55my $cmd = shift @ARGV;
56
57if (!$cmd) {
b02da6e1 58 fatal_usage("no command specified");
300bd06d 59} elsif (!exists $commands->{$cmd}) {
b02da6e1 60 fatal_usage("unknown command '$cmd'");
300bd06d
TL
61} elsif ($cmd eq 'help') {
62 print_usage();
63 exit (0);
8ab34b87
DM
64}
65
300bd06d
TL
66my $dab;
67sub dab() {
68 $dab = PVE::DAB->new() if !$dab;
69 return $dab;
70}
8ab34b87 71
300bd06d 72dab->writelog ("dab: $cmdline\n");
8ab34b87
DM
73
74$SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
75 die "interrupted by signal\n";
76};
77
78eval {
8ab34b87 79 if ($cmd eq 'init') {
8ab34b87
DM
80 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
81
300bd06d 82 dab->initialize();
8ab34b87
DM
83
84 } elsif ($cmd eq 'bootstrap') {
8ab34b87 85 my $opts = {};
7b3b1a35 86 if (!GetOptions ($opts, 'exim', 'minimal', 'include=s', 'exclude=s')) {
b02da6e1 87 fatal_usage();
8ab34b87 88 }
8ab34b87
DM
89 die "command 'bootstrap' expects no arguments.\n" if scalar (@ARGV) != 0;
90
91 $dab->ve_init();
8ab34b87
DM
92 $dab->bootstrap ($opts);
93
94 } elsif ($cmd eq 'finalize') {
8ab34b87 95 my $opts = {};
f06fe8dc 96 if (!GetOptions ($opts, 'keepmycnf', 'compressor=s')) {
b02da6e1 97 fatal_usage();
8ab34b87 98 }
8ab34b87
DM
99 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
100
101 $dab->finalize($opts);
102
103 } elsif ($cmd eq 'veid') {
8ab34b87
DM
104 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
105
106 print $dab->{veid} . "\n";
107
108 } elsif ($cmd eq 'basedir') {
8ab34b87
DM
109 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
110
f0134ed2 111 print $dab->{rootfs} . "\n";
8ab34b87
DM
112
113 } elsif ($cmd eq 'packagefile') {
8ab34b87
DM
114 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
115
116 print "$dab->{targetname}.tar.gz\n";
117
118 } elsif ($cmd eq 'list') {
8ab34b87 119 my $verbose;
8ab34b87 120 if (!GetOptions ('verbose' =>\$verbose)) {
b02da6e1 121 fatal_usage();
8ab34b87 122 }
8ab34b87
DM
123 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
124
125 my $instpkgs = $dab->read_installed ();
126
127 foreach my $pkg (sort keys %$instpkgs) {
128 if ($verbose) {
129 my $version = $instpkgs->{$pkg}->{version};
130 print "$pkg $version\n";
131 } else {
132 print "$pkg\n";
133 }
134 }
135
136 } elsif ($cmd eq 'task') {
8ab34b87 137 my $task = shift @ARGV;
8ab34b87 138 if (!$task) {
b02da6e1 139 fatal_usage("no task specified");
8ab34b87
DM
140 }
141
142 my $opts = {};
8ab34b87 143 if ($task eq 'mysql') {
8ab34b87 144 if (!GetOptions ($opts, 'password=s', 'start')) {
b02da6e1 145 fatal_usage();
8ab34b87 146 }
8ab34b87
DM
147 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
148
149 $dab->task_mysql ($opts);
8ab34b87 150
300bd06d 151 } elsif ($task eq 'postgres') {
8ab34b87 152 if (!GetOptions ($opts, 'version=s', 'start')) {
b02da6e1 153 fatal_usage();
8ab34b87 154 }
8ab34b87
DM
155 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
156
157 $dab->task_postgres ($opts);
158
159 } elsif ($task eq 'php') {
8ab34b87 160 if (!GetOptions ($opts, 'memlimit=i')) {
b02da6e1 161 fatal_usage();
8ab34b87 162 }
8ab34b87
DM
163 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
164
165 $dab->task_php ($opts);
300bd06d 166
8ab34b87 167 } else {
b02da6e1 168 fatal_usage("unknown task '$task'");
8ab34b87
DM
169 }
170
171 } elsif ($cmd eq 'install' || $cmd eq 'unpack') {
8ab34b87
DM
172 my $required;
173 foreach my $arg (@ARGV) {
174 if ($arg =~ m/\.pkglist$/) {
175 open (TMP, $arg) ||
176 die "cant open package list '$arg' - $!";
177 while (defined (my $line = <TMP>)) {
178 chomp $line;
179 next if $line =~ m/^\s*$/;
180 next if $line =~ m/\#/;
181 if ($line =~ m/^\s*(\S+)\s*$/) {
182 push @$required, $1;
183 } else {
184 die "invalid package name in '$arg' - $line\n";
185 }
186 }
187 } else {
188 push @$required, $arg;
189 }
190
191 close (TMP);
192 }
193
194 $dab->install ($required, $cmd eq 'unpack');
195
196 } elsif ($cmd eq 'exec') {
197
198 $dab->ve_exec (@ARGV);
199
200 } elsif ($cmd eq 'enter') {
8ab34b87
DM
201 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
202
203 $dab->enter();
204
205 } elsif ($cmd eq 'clean') {
8ab34b87
DM
206 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
207
300bd06d 208 $dab->cleanup(0);
8ab34b87
DM
209
210 } elsif ($cmd eq 'dist-clean') {
8ab34b87
DM
211 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
212
300bd06d 213 $dab->cleanup(1);
8ab34b87
DM
214
215 } else {
b02da6e1 216 fatal_usage("invalid command '$cmd'");
8ab34b87
DM
217 }
218
219};
8ab34b87
DM
220if (my $err = $@) {
221 $dab->logmsg ($@);
222 die ($@);
223}
224
225exit 0;
226
227__END__
228
229=head1 NAME
300bd06d 230
f0134ed2 231dab - Debian LXC Appliance Builder
8ab34b87
DM
232
233=head1 SYNOPSIS
234
235=over
236
237=item B<dab> I<command> I<[OPTIONS]>
238
239=item B<dab init>
240
300bd06d
TL
241Downloads the package descriptions form the repository. Also truncates the
242C<logfile>.
8ab34b87
DM
243
244=item B<dab bootstrap>
245
300bd06d
TL
246Bootstrap a debian system and allocate a temporary container (we use IDs 90000
247and above).
8ab34b87
DM
248
249=over
88201924 250
8ab34b87
DM
251=item I<--exim>
252
88201924 253Use exim as MTA (dab selects postfix by default)
8ab34b87
DM
254
255=item I<--minimal>
256
88201924
TL
257Do not auto-select packages with standard priority for installation.
258
259=item I<--include <a[,b..]]>
260
261A comma-separated list of packages to always include in bootstrap. Note that no
262transitive dependency resolution is done, you may need to specify those
263yourself.
264
265=item I<--exclude <a[,b..]]>
266
267A comma-separated list of packages to exlcude in bootstrap. Note that no
268transitive dependency resolution is done for others to get excluded, you may
269need to specify those yourself.
8ab34b87
DM
270
271=back
272
273=item B<dab veid>
274
275Print used container ID.
276
277=item B<dab basedir>
278
279Print container private directory.
280
281=item B<dab packagefile>
282
283Print the appliance file name.
284
285=item B<dab install I<pkg ...>>
286
287Install one or more packages. I<pkg> can also refer to a file named
300bd06d
TL
288C<xyz.pkglist> which contains a list of packages. All dependencies are
289automatically installed.
8ab34b87
DM
290
291=item B<dab unpack I<pkg ...>>
292
293Unpack one or more packages. I<pkg> can also refer to a file named
300bd06d
TL
294C<xyz.pkglist> which contains a list of packages. All dependencies are
295automatically unpacked.
8ab34b87
DM
296
297=item B<dab exec I<CMD> I<ARGS>>
298
299Executes command CMD inside the container.
300
301=item B<dab enter>
302
f0134ed2 303Calls C<lxc-attach> - this is for debugging only.
8ab34b87
DM
304
305=item B<dab task mysql>
306
300bd06d
TL
307Install a mysql database server. During appliance generation we use C<admin> as
308mysql root password (also stored in /root/.my.cnf).
8ab34b87
DM
309
310=over
311
312=item I<--password=XXX>
313
300bd06d
TL
314Specify the mysql root password. The special value C<random> can be use to
315generate a random root password when the appliance is started first time
316(stored in /root/.my.cnf)
8ab34b87
DM
317
318=item I<--start>
319
320Start the mysql server (if you want to execute sql commands during
321appliance generation).
322
323=back
324
325=item B<dab task postgres>
326
327Install a postgres database server.
328
329=over
330
331=item I<--version=XXX>
332
093b1acf
TL
333Select Postgres version. Posible values are for example C<9.6>, C<11> or C<13>,
334they depend on the selected distribution suite. Defaults to none, which selects
335the unversioned metapackage that pulls in the suites default version, normally
336a good choice to make.
8ab34b87
DM
337
338=item I<--start>
339
093b1acf
TL
340Start the postgres server immediately. Useful, for example, if you want to
341execute sql commands during appliance generation.
8ab34b87
DM
342
343=back
344
345=item B<dab task php>
346
347Install php5.
348
349=over
350
351=item I<--memlimit=i>
352
353Set the php I<memory_limit>.
354
355=back
356
357=item B<dab finalize>
358
300bd06d
TL
359Cleanup everything inside the container and generate the final appliance
360package.
8ab34b87
DM
361
362=over
363
364=item I<--keepmycnf>
365
366Do not delete file C</root/.my.cfg> (mysql).
367
88201924
TL
368=item I<--compressor <gz[ip] (default)|zst[d]|zstd-max>]>
369
370Select the compressor to process the rootfs archive with. C<gzip> is a good
371choice to make the archive also available on older systems, but using C<zstd>
372or even C<zstd-max> results in a higher compression ration while keeping
373decompression very fast and highly efficient. Note that C<zstd-max> uses the
374highest compression ratio without any decompression performance hit possible,
375it will use as many threads as there are onlince CPU threads and may thus
376increase the system load significantly for tens of seconds up to minutes.
377
8ab34b87
DM
378=back
379
380=item B<dab list>
381
382List installed packages.
300bd06d 383
8ab34b87
DM
384=over
385
386=item I<--verbose>
387
388Also print package versions.
389
390=back
391
392=item B<dab clean>
393
f0134ed2 394Remove all temporary files and destroy the container.
8ab34b87
DM
395
396=item B<dab dist-clean>
397
300bd06d
TL
398Like clean, but also removes the package cache (except when you specified your
399own cache directory in the config file)
8ab34b87
DM
400
401=back
402
8ab34b87
DM
403=head1 DESCRIPTION
404
300bd06d
TL
405dab is a script to automate the creation of LXC appliances. It is basically a
406rewrite of debootstrap in perl, but uses LXC instead of chroot and generates
407LXC templates. Another difference is that it supports multi-stage building of
408templates. That way you can execute arbitrary scripts between to accomplish
409what you want.
8ab34b87 410
300bd06d
TL
411Furthermore some common tasks are fully automated, like setting up a database
412server (mysql or postgres).
8ab34b87 413
300bd06d
TL
414To accomplish minimal template creation time, packages are cached to a local
415directory, so you do not need a local debian mirror (although this would speed
416up the first run).
8ab34b87
DM
417
418See http://pve.proxmox.com/wiki/Debian_Appliance_Builder for examples.
419
300bd06d
TL
420This script need to be run as root, so it is not recommended to start it on a
421production machine with running containers. So many people run Proxmox VE
422inside a KVM or VMWare 64bit virtual machine to build appliances.
8ab34b87 423
300bd06d
TL
424All generated templates includes an appliance description file. Those can be
425used to build appliance repositories.
8ab34b87
DM
426
427=head1 CONFIGURATION
428
429Configuration is read from the file C<dab.conf> inside the current working
430directory. The files contains key value pairs, separated by colon.
431
432=over 2
433
3a9c8648 434=item B<Suite:> I<squeeze|wheezy|jessie|trusty|vivid>
8ab34b87
DM
435
436The Debian or Ubuntu suite.
437
438=item B<Source:> I<URL [components]>
439
440Defines a source location. By default we use the following for debian:
441
442 Source: http://ftp.debian.org/debian SUITE main contrib
443 Source: http://security.debian.org SUITE/updates main contrib
444
445Note: SUITE is a variable and will be substituted.
446
300bd06d
TL
447There are also reasonable defaults for Ubuntu. If you do not specify any source
448the defaults are used.
8ab34b87
DM
449
450=item B<Depends:> I<dependencies>
451
300bd06d
TL
452Debian like package dependencies. This can be used to make sure that speific
453package versions are available.
8ab34b87
DM
454
455=item B<CacheDir>: I<path>
456
300bd06d 457Allows you to specify the directory where downloaded packages are cached.
8ab34b87
DM
458
459=item B<Mirror:> I<SRCURL> => I<DSTURL>
460
461Define a mirror location. for example:
462
463 Mirror: http://ftp.debian.org/debian => ftp://mirror/debian
464
465=back
466
467All other settings in this files are also included into the appliance
468description file.
469
470=over 2
471
472=item B<Name:> I<name>
473
300bd06d 474The name of the appliance.
8ab34b87 475
300bd06d
TL
476Appliance names must consist only of lower case letters (a-z), digits (0-9),
477plus (+) and minus (-) signs, and periods (.). They must be at least two
478characters long and must start with an alphanumeric character.
8ab34b87
DM
479
480=item B<Architecture:> I<i386|amd64>
481
482Target architecture.
483
484=item B<Version:> I<upstream_version[-build_revision]>
485
486The version number of an appliance.
487
488=item: B<Section:> I<section>
489
300bd06d
TL
490This field specifies an application area into which the appliance has been
491classified. Currently we use the following section names: system, mail
8ab34b87
DM
492
493=item B<Maintainer:> I<name <email>>
494
300bd06d
TL
495The appliance maintainer's name and email address. The name should come first,
496then the email address inside angle brackets <> (in RFC822 format).
8ab34b87
DM
497
498=item B<Infopage:> I<URL>
499
500Link to web page containing more informations about this appliance.
501
502=item B<Description:> I<single line synopsis>
503
300bd06d 504extended description over several lines (indended by space) may follow.
8ab34b87
DM
505
506=back
507
508=head1 Appliance description file
509
510All generated templates includes an appliance description file called
511
512 /etc/appliance.info
513
300bd06d
TL
514this is the first file inside the tar archive. That way it can be easily
515exctracted without scanning the whole archive. The file itself contains
516informations like a debian C<control> file. It can be used to build appliance
517repositories.
8ab34b87
DM
518
519Most fields are directly copied from the configuration file C<dab.conf>.
520
521Additionally there are some auto-generated files:
522
523=over
524
525=item B<Installed-Size:> I<bytes>
526
527It gives the total amount of disk space required to install the named
300bd06d
TL
528appliance. The disk space is represented in megabytes as a simple decimal
529number.
8ab34b87
DM
530
531=item B<Type:> I<type>
532
f0134ed2 533This is always C<lxc>.
8ab34b87
DM
534
535=item B<OS:> I<[debian-4.0|debian-5.0|ubuntu-8.0]>
536
537Operation system.
538
539=back
540
541Appliance repositories usually add additional fields:
542
543=over
544
545=item B<md5sum:> I<md5sum>
546
547MD5 checksum
548
549=back
550
551=head1 FILES
552
553The following files are created inside your working directory:
554
555 dab.conf appliance configuration file
556
557 logfile contains installation logs
558
559 .veid stores the used container ID
560
561 cache/* default package cache directory
562
563 info/* package information cache
300bd06d 564
8ab34b87
DM
565=head1 AUTHOR
566
567Dietmar Maurer <dietmar@proxmox.com>
88201924 568Thomas Lamprecht <t.lamprecht@proxmox.com>
8ab34b87 569
300bd06d
TL
570Many thanks to Proxmox Server Solutions (www.proxmox.com) for sponsoring this
571work.
8ab34b87
DM
572
573=head1 COPYRIGHT AND DISCLAIMER
574
88201924 575Copyright (C) 2007-2021 Proxmox Server Solutions GmbH
8ab34b87
DM
576
577Copyright: dab is under GNU GPL, the GNU General Public License.
578
579This program is free software; you can redistribute it and/or modify
580it under the terms of the GNU General Public License as published by
581the Free Software Foundation; version 2 dated June, 1991.
582
583This program is distributed in the hope that it will be useful,
584but WITHOUT ANY WARRANTY; without even the implied warranty of
585MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
586GNU General Public License for more details.
587
588You should have received a copy of the GNU General Public License
589along with this program; if not, write to the
590Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
591MA 02110-1301, USA.