making your own repo, a comps.xml a group, using yum groupinstall make your own packages. sign them, key signing. about making packages in an appendix using yum, automatic for workstations, you control the repos.
[root@server0 ~]# useradd signer
[root@server0 ~]# passwd signer
Changing password for user signer.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
[root@server0 ~]# su - signer
[signer@server0 ~]$ gpg --gen-key
gpg (GnuPG) 1.4.5; Copyright (C) 2006 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.
Please select what kind of key you want:
(1) DSA and Elgamal (default)
(2) DSA (sign only)
(5) RSA (sign only)
Your selection? 5
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0) 10y
Key expires at Sun 21 Jul 2019 04:32:53 PM EDT
Is this correct? (y/N) y
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) "
Real name: Repository Signer
Email address: signer@example.com
Comment: Example Com
You selected this USER-ID:
"Repository Signer (Example Com) "
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
...+++++
..........+++++
gpg: key 44CB93FD marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2019-07-21
pub 2048R/44CB93FD 2009-07-23 [expires: 2019-07-21]
Key fingerprint = BD7F E3E1 3403 3F35 5DA7 C8AF CC08 B6BA 44CB 93FD
uid Repository Signer (Example Com)
Note that this key cannot be used for encryption. You may want to use
the command "--edit-key" to generate a subkey for this purpose.
Next, export the newly created key to a file.
[signer@server0 ~]$ gpg --export -a "Repository Signer (Example Com)Now, import the key into the rpm database to verify everything is working correctly." >RPM-GPG-KEY-example.com
[root@server0 install]# rpm -q gpg-pubkey-* gpg-pubkey-f51839ac-46362566 gpg-pubkey-b2980b13-3c1d0597 [root@server0 install]# rpm --import ~signer/RPM-GPG-KEY-example.com [root@server0 install]# rpm -q gpg-pubkey-* gpg-pubkey-f51839ac-46362566 gpg-pubkey-b2980b13-3c1d0597 gpg-pubkey-44cb93fd-4a68c9c4
| puppet puppet-server facter ruby-shadow |
augeas augeas-libs ruby-augeas |
func certmaster smolt python-ctypes python-paste python-simplejson |
Now, you'll need to either download the src rpm or binary rpms for the packages you wish to redistribute to your clients (Make sure you can legally redistribute these rpms). For our purposes we will need the func, puppet, facter and augeas rpms. We will download them from the epel repository. Using lftp is one of the quickest ways to find all the right files and download them. First we'll setup the directories for our repository, then we'll start downloading.
[root@server0 ~]# cd /var/www/html/install [root@server0 install]# mkdir -p Local/SRPMS Local/i386 Local/x86_64 [root@server0 install]# cd Local [root@server0 Local]# lftp http://download.fedora.redhat.com/pub/epel/5/x86_64/ cd ok, cwd=/pub/epel/5/x86_64 lftp download.fedora.redhat.com:/pub/epel/5/x86_64> get puppet-0.24.8-1.el5.1.noarch.rpm 554952 bytes transferred lftp download.fedora.redhat.com:/pub/epel/5/x86_64> get puppet-server-0.24.8-1.el5.1.noarch.rpm 26918 bytes transferred lftp download.fedora.redhat.com:/pub/epel/5/x86_64> get func-0.24-1.el5.noarch.rpm 282228 bytes transferred ... lftp download.fedora.redhat.com:/pub/epel/5/x86_64> quit [root@server0 Local]# ls augeas-0.5.1-1.el5.x86_64.rpm puppet-server-0.24.8-1.el5.1.noarch.rpm augeas-libs-0.5.1-1.el5.x86_64.rpm ruby-augeas-0.2.0-1.el5.x86_64.rpm ... python-simplejson-2.0.3-2.el5.x86_64.rpm
At this point we have our rpms downloaded, we need to place them in the appropriate directories, and also sign them (they are signed by the epel repo at this point). We'll sign them first, this requires giving the signer user permission to write in the Local directory and setting the .rpmmacros file in signers home directory to use the correct signing key.
[root@server0 Local]# rpm -K augeas-0.5.1-1.el5.x86_64.rpm augeas-0.5.1-1.el5.x86_64.rpm: (SHA1) DSA sha1 md5 (GPG) NOT OK (MISSING KEYS: GPG#217521f6) [root@server0 Local]# chown -R signer:signer . [root@server0 Local]# su - signer [signer@server0 ~]$ gpg --list-keys /home/signer/.gnupg/pubring.gpg ------------------------------- pub 2048R/44CB93FD 2009-07-23 [expires: 2019-07-21] uid Repository Signer (Example Com)[signer@server0 ~]$ cat < .rpmmacros > %_signature gpg > %_gpg_name Repository Signer (Example Com) [signer@server0 ~]$ cd /var/www/html/install/Local [signer@server0 Local]$ rpm --resign *.rpm Enter pass phrase: Pass phrase is good. augeas-0.5.1-1.el5.x86_64.rpm: augeas-libs-0.5.1-1.el5.x86_64.rpm: facter-1.5.5-1.el5.noarch.rpm: ... [signer@server0 Local]$ rpm -K augeas-0.5.1-1.el5.x86_64.rpm augeas-0.5.1-1.el5.x86_64.rpm: rsa sha1 (md5) pgp md5 OK> EOF
Now that the rpms are signed by our key, we can move the rpms to the correct directories. If disk space it not at a premium, just copy the noarch rpms into both the i386 and the x86_64 directories. If you are concerned about usage (like me), hard link the noarch file in i386 to the one in x86_64 (they are the same file anyway).
[signer@server0 Local]$ mv *x86_64.rpm x86_64 [signer@server0 Local]$ for file in *noarch.rpm > do > mv $file x86_64 > ln x86_64/$file i386 > done
<comps>
<!-- <meta> -->
<!-- Meta information will go here eventually -->
<!-- </meta> -->
<group>
<id>localclient</id>
<name>Local Client</name>
<default>true</default>
<description>Default RPMS from Local Clients</description>
<uservisible>true</uservisible>
<packagelist>
<packagereq type="default">puppet</packagereq>
<packagereq type="default">ruby-augeas</packagereq>
<packagereq type="default">facter</packagereq>
<packagereq type="default">func</packagereq>
</packagelist>
</group>
</comps>
[root@server0 install]# yum -y install createrepo Setting up Install Process Parsing package install arguments Resolving Dependencies --> Running transaction check ---> Package createrepo.noarch 0:0.4.4-2.fc6 set to be updated --> Finished Dependency Resolution Dependencies Resolved ======================================================================================================== Package Arch Version Repository Size ======================================================================================================== Installing: createrepo noarch 0.4.4-2.fc6 Install_Server_Client 37 k Transaction Summary ======================================================================================================== Install 1 Package(s) Update 0 Package(s) Remove 0 Package(s) Total download size: 37 k Downloading Packages: Running rpm_check_debug Running Transaction Test Finished Transaction Test Transaction Test Succeeded Running Transaction Installing : createrepo [1/1] Installed: createrepo.noarch 0:0.4.4-2.fc6 Complete! [root@server0 install]# cd Local [root@server0 Local]# mv comps.xml x86_64 [root@server0 Local]# ln x86_64/comps.xml i386 [root@server0 Local]# createrepo -g comps.xml x86_64 9/9 - augeas-0.5.1-1.el5.x86_64.rpm Saving Primary metadata Saving file lists metadata Saving other metadata [root@server0 Local]# createrepo -g comps.xml i386 5/5 - func-0.24-1.el5.noarch.rpm Saving Primary metadata Saving file lists metadata Saving other metadataNow that our repo files are in place, we need to create an rpm for our repository so we can install it with kickstart or we can install a repo file and add the key to rpm using kickstart. Creating an rpm is probably cleaner. If you want to test this repo at this point, you can add the following file to /etc/yum.repos.d, and copy the RPM-GPG-KEY-example.com that we created earlier into /etc/pki/rpm-gpg (actually, since we already imported the key with rpm --import, yum shouldn't complain about keys at this point, but copying the file is a good idea).
[root@server0 yum.repos.d]# cp ~signer/RPM-GPG-KEY-example.com /etc/pki/rpm-gpg/ [root@server0 yum.repos.d]# cat local.repo [Local] name=Local RPMS $releasever - $basearch baseurl=file:///var/www/html/install/Local/$basearch gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-example.com enabled=1 [root@server0 yum.repos.d]# yum search augeas Local | 1.1 kB 00:00 primary.xml.gz | 2.8 kB 00:00 Local 7/7 =========================================== Matched: augeas ============================================ augeas.x86_64 : A library for changing configuration files augeas-libs.x86_64 : Libraries for augeas ruby-augeas.x86_64 : Ruby bindings for Augeas [root@server0 yum.repos.d]# yum grouplist |grep Client Local Client
A somewhat better way to do it is to make a repository rpm that install the file and the key. To make such an rpm, create a working directory in signer's home directory
[root@server0 ~]# yum -y install rpm-build
[root@server0 ~]# su - signer
[signer@server0 ~]$ mkdir -p src/RPMS src/SPECS src/BUILD src/SRPMS
[signer@server0 ~]$ echo "%_topdir /home/signer/src" >> ~/.rpmmacros
[signer@server0 ~]$ cd src/SPECS
[signer@server0 SPECS]$ cat Example.com-local.spec
Summary: yum Local repository
Name: Example.com-Local
Version: 1
Release: 1
Group: System Environment/Base
License: GPL
BuildRoot: %{_tmppath}/%{name}-root
BuildArch: noarch
%description
This rpm contains the yum Example.com Local repository
%prep
%build
%install
mkdir -p $RPM_BUILD_ROOT/etc/yum.repos.d/
cat > $RPM_BUILD_ROOT/etc/yum.repos.d/local-%{version}-local.repo < $RPM_BUILD_ROOT/etc/pki/rpm-gpg/RPM-GPG-KEY-example.com <
- initial release
[signer@server0 SPECS]$ rpmbuild -ba Example.com-local.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.10406
+ umask 022
+ cd /home/signer/src/BUILD
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.10406
+ umask 022
+ cd /home/signer/src/BUILD
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.10406
+ umask 022
+ cd /home/signer/src/BUILD
+ mkdir -p /var/tmp/Example.com-Local-root/etc/yum.repos.d/
+ cat
+ mkdir -p /var/tmp/Example.com-Local-root/etc/pki/rpm-gpg/
+ cat
+ exit 0
Processing files: Example.com-Local-1-1
Requires(interp): /bin/sh /bin/sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires(post): /bin/sh
Requires(postun): /bin/sh
Checking for unpackaged file(s): /usr/lib/rpm/check-files /var/tmp/Example.com-Local-root
Wrote: /home/signer/src/SRPMS/Example.com-Local-1-1.src.rpm
Wrote: /home/signer/src/RPMS/noarch/Example.com-Local-1-1.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.10406
+ umask 022
+ cd /home/signer/src/BUILD
+ rm -rf /var/tmp/Example.com-Local-root
+ exit 0
[signer@server0 SPECS]$ cd ../
[signer@server0 src]$ cp RPMS/noarch/Example.com-Local-1-1.noarch.rpm SRPMS/Example.com-Local-1-1.src.rpm /var/www/html/install/Local
Now we need to move the rpms into the correct directories and rerun createrepo. We should script this at this point. Here is a simple script (modified from the one we use) that checks if rpms are signed and then links them into the appropriate directory. By linking first, we can make multiple links and then remove the copy in the current directory.
[signer@server0 Local]$ mkdir ~/bin
[signer@server0 Local]$ cat ~/bin/update_repo
#!/bin/sh
COMPS=comps.xml
# determine the architecture of the rpm (noarch x86_64 i386...)
rpm_arch() {
echo $1 | awk -F'.' '{NF=NF-1; print $NF}'
}
# build a list of rpms to move
for i in $@ *.rpm; do
if [ -f "$i" ]; then
case $i in
*rpm)
if rpm -K $i | awk '/pgp/ && /OK/ && !/NOT OK/' &>/dev/null; then
RPMLIST="$RPMLIST $i"
else
echo "ERROR: rpm $i is NOT SIGNED"
exit 1
fi
;;
*)
echo "ERROR: $i is not an rpm"
exit 1
;;
esac
else
if [ "XXX$i" != "XXX*.rpm" ]; then
echo "ERROR: $i is not a file"
exit 1
fi
fi
done
echo $RPMLIST
if [ -d i386 -a -d x86_64 -a -d SRPMS ]; then
for i in $RPMLIST; do
ARCH=`rpm_arch $i`
case $ARCH in
src)
ARCH=SRPMS
;;
i386|i486|i586|i686)
ARCH=i386
;;
x86_64)
;;
noarch)
ARCH="i386 x86_64"
;;
*)
ARCH=unknown
echo "$i unknown architecture"
;;
esac
ERROR=""
if [ "$ARCH" != "unknown" ]; then
for DESTARCH in $ARCH
do
if [ -e $DESTARCH/$i ]; then
echo "$i already exists in $DESTARCH"
ERROR=1
else
echo "linking $i into $DESTARCH"
ln $i $DESTARCH
fi
done
if [ -z "$ERROR" ]; then
# linking was successful, remove file
rm -f $i
else
echo "ERROR: could not link $i"
fi
fi
done
echo "Running createrepo now"
for ARCH in i386 x86_64
do
createrepo -g $COMPS $ARCH
done
else
echo "ERROR: required directories not found (i386 x86_64 SRPMS)"
fi
[signer@server0 Local]$ chmod 755 ~/bin/update_repo
[signer@server0 Local]$ ~/bin/update_repo
ERROR: rpm Example.com-Local-1-1.noarch.rpm is NOT SIGNED
We forgot to sign the rpms we just built. Sign them now.
[signer@server0 Local]$ rpm --addsign *rpm Enter pass phrase: Pass phrase is good. Example.com-Local-1-1.noarch.rpm: gpg: WARNING: standard input reopened gpg: WARNING: standard input reopened Example.com-Local-1-1.src.rpm: gpg: WARNING: standard input reopened gpg: WARNING: standard input reopenedNow try that update again
[signer@server0 Local]$ ~/bin/update_repo Example.com-Local-1-1.noarch.rpm Example.com-Local-1-1.src.rpm linking Example.com-Local-1-1.noarch.rpm into i386 linking Example.com-Local-1-1.noarch.rpm into x86_64 linking Example.com-Local-1-1.src.rpm into SRPMS Running createrepo now 4/4 - func-0.24-1.el5.noarch.rpm Saving Primary metadata Saving file lists metadata Saving other metadata 8/8 - augeas-0.5.1-1.el5.x86_64.rpm Saving Primary metadata Saving file lists metadata Saving other metadataNow we have our rpm signed and in our repo and can install it at install time using kickstart.
repo --name=Local --baseurl=http://server0.example.com/install/Local/x86_64We will want our group to be installed as well as our repository rpm, here is how we do that.
@localclientNow after installation our client will have the following packages installed from our repository
[root@client15 ~]# rpm -q puppet ruby-augeas func puppet-0.24.8-1.el5.1 ruby-augeas-0.2.0-1.el5 func-0.24-1.el5Now that we have our extra rpms installed, we can move on to configuring puppet.