debianization and a wrapper program for /usr/bin

This commit is contained in:
Joey Hess 2014-04-03 00:59:26 -04:00
parent 167609746d
commit 42f207232b
13 changed files with 265 additions and 51 deletions

View File

@ -1,20 +1,30 @@
run: build
CABAL?=cabal
run: deps build
./propellor
dev: build tags
build: deps dist/setup-config
if ! cabal build; then cabal configure; cabal build; fi
ln -sf dist/build/propellor/propellor
build: dist/setup-config
if ! $(CABAL) build; then $(CABAL) configure; $(CABAL) build; fi
ln -sf dist/build/config/config propellor
deps:
@if [ $$(whoami) = root ]; then apt-get -y install gnupg ghc cabal-install libghc-missingh-dev libghc-ansi-terminal-dev libghc-ifelse-dev libghc-unix-compat-dev libghc-hslogger-dev libghc-network-dev libghc-async-dev; fi || true
dist/setup-config: propellor.cabal
cabal configure
if [ "$(CABAL)" = ./Setup ]; then ghc --make Setup; fi
$(CABAL) configure
install:
install -d $(DESTDIR)/usr/bin $(DESTDIR)/usr/src/propellor
install -s dist/build/propellor/propellor $(DESTDIR)/usr/bin
$(CABAL) sdist
cat dist/propellor-*.tar.gz | \
(cd $(DESTDIR)/usr/src/propellor && tar zx --strip-components=1)
clean:
rm -rf dist Setup tags propellor privdata/local
rm -rf dist Setup tags propellor propellor-wrapper privdata/local
find -name \*.o -exec rm {} \;
find -name \*.hi -exec rm {} \;
@ -22,4 +32,9 @@ clean:
tags:
find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$' | xargs hothasktags > tags 2>/dev/null
# Upload to hackage.
hackage:
@cabal sdist
@cabal upload dist/*.tar.gz
.PHONY: tags

View File

@ -74,9 +74,10 @@ defaultMain getprops = do
headMaybe $ catMaybes $ map (\get -> get host) getprops
unknownhost :: HostName -> IO a
unknownhost h = errorMessage $ unwords
[ "Unknown host:", h
, "(perhaps you should specify the real hostname on the command line?)"
unknownhost h = errorMessage $ unlines
[ "Unknown host: " ++ h
, "(Perhaps you should specify the real hostname on the command line?)"
, "(Or, edit propellor's config.hs to configure this host)"
]
buildFirst :: CmdLine -> IO () -> IO ()

View File

@ -1,18 +1,18 @@
This is a work in progress configuration management system using Haskell
and Git.
This is a configuration management system using Haskell and Git.
Propellor enures that the system it's run in satisfies a list of
Propellor enures that the system it's run against satisfies a list of
properties, taking action as necessary when a property is not yet met.
The design is intentionally very minimal.
Propellor is configured via a git repository, which typically lives
in ~/.propellor/. The git repository contains a config.hs file,
and also the entire source code to propellor.
Propellor lives in a git repository. You'll typically want to have
the repository checked out on a laptop, in order to make changes and push
them out to hosts. Each host will also have a clone of the repository,
and in that clone "make" can be used to build and run propellor.
This can be done by a cron job (which propellor can set up),
or a remote host can be triggered to update by running propellor
on your laptop: propellor --spin $host
You typically want to have the repository checked out on a laptop, in order
to make changes and push them out to hosts. Each host will also have a
clone of the repository, and in that clone "make" can be used to build and
run propellor. This can be done by a cron job (which propellor can set up),
or a remote host can be triggered to update by running propellor on your
laptop: propellor --spin $host
Properties are defined using Haskell. Edit config.hs to get started.
@ -28,35 +28,41 @@ and so it's easy to factor out things like classes of hosts as desired.
## quick start
1. Clone propellor's git repository to your laptop (or whatever).
git clone git://git.kitenet.net/propellor
or joeyh/propellor on github
2. Run: sudo make deps # installs build dependencies
3. Run: make build
4. If you don't have a gpg private key, generate one: gpg --gen-key
5. Run: ./propellor --add-key $KEYID
7. Pick a host and run: ./propellor --spin $HOST
8. Now you have a simple propellor deployment, but it doesn't do anything
to the host yet, besides installing propellor.
1. Get propellor installed
`cabal install propellor`
or
`apt-get install propellor`
2. Run propellor for the first time. It will set up a `~/.propellor/` git
repository for you.
3. In `~/.propellor/`, use git to push the repository to a central
server (github, or your own git server). Configure that central
server as the origin remote of the repository.
4. If you don't have a gpg private key, generate one: `gpg --gen-key`
5. Run: `propellor --add-key $KEYID`
6. Edit `~/.propellor/config.hs`, and add a host you want to manage.
You can start by not adding any properties, or only a few.
7. Pick a host and run: `propellor --spin $HOST`
8. Now you have a simple propellor deployment, but it doesn't do
much to the host yet, besides installing propellor.
So, edit config.hs to configure the host (maybe start with a few simple
properties), and re-run step 7. Repeat until happy and move on to the
next host. :)
So, edit `~/.propellor/config.hs` to configure the host (maybe
start with a few simple properties), and re-run step 7.
Repeat until happy and move on to the next host. :)
9. To move beyond manually running propellor --spin against hosts
when you change configuration, add a property to your hosts
like: Cron.runPropellor "30 * * * *"
like: `Cron.runPropellor "30 * * * *"`
Now they'll automatically update every 30 minutes, and you can
`git commit -S` and `git push` changes that affect any number of
hosts.
10. Write some neat new properties and send patches to propellor@joeyh.name!
8. Write some neat new properties and send patches to <propellor@joeyh.name>!
## security
Propellor's security model is that the hosts it's used to deploy are
untrusted, and that the central git repository server is untrusted.
The only trusted machine is the laptop where you run propellor --spin
The only trusted machine is the laptop where you run `propellor --spin`
to connect to a remote host. And that one only because you have a ssh key
or login password to the host.
@ -70,10 +76,10 @@ otherwise.
That is only done when privdata/keyring.gpg exists. To set it up:
gpg --gen-key # only if you don't already have a gpg key
propellor --add-key $MYKEYID
gpg --gen-key # only if you don't already have a gpg key
propellor --add-key $MYKEYID
In order to be secure from the beginning, when propellor --spin is used
In order to be secure from the beginning, when `propellor --spin` is used
to bootstrap propellor on a new host, it transfers the local git repositry
to the remote host over ssh. After that, the remote host knows the
gpg key, and will use it to verify git fetches.
@ -81,17 +87,17 @@ gpg key, and will use it to verify git fetches.
Since the propoellor git repository is public, you can't store
in cleartext private data such as passwords, ssh private keys, etc.
Instead, propellor --spin $host looks for a privdata/$host.gpg file and
Instead, `propellor --spin $host` looks for a `~/.propellor/privdata/$host.gpg` file and
if found decrypts it and sends it to the remote host using ssh. This lets
a remote host know its own private data, without seeing all the rest.
To securely store private data, use: propellor --set $host $field
To securely store private data, use: `propellor --set $host $field`
The field name will be something like 'Password "root"'; see PrivData.hs
for available fields.
## debugging
Set PROPELLOR_DEBUG=1 to make propellor print out all the commands it runs
and any other debug messages Properties choose to emit.
Set `PROPELLOR_DEBUG=1` to make propellor print out all the commands it runs
and any other debug messages that Properties choose to emit.
[1] http://reclass.pantsfullofunix.net/

8
debian/changelog vendored
View File

@ -1,4 +1,10 @@
propellor (0.2) unstable; urgency=low
propellor (0.2.1) unstable; urgency=medium
* First release with Debian package.
-- Joey Hess <joeyh@debian.org> Thu, 03 Apr 2014 01:43:14 -0400
propellor (0.2.0) unstable; urgency=low
* Added support for provisioning Docker containers.
* Bootstrap deployment now pushes the git repo to the remote host

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

36
debian/control vendored Normal file
View File

@ -0,0 +1,36 @@
Source: propellor
Section: admin
Priority: optional
Build-Depends:
debhelper (>= 9),
ghc (>= 7.4),
cabal-install,
libghc-async-dev,
libghc-missingh-dev,
libghc-hslogger-dev,
libghc-unix-compat-dev,
libghc-ansi-terminal-dev,
libghc-ifelse-dev,
Maintainer: Joey Hess <joeyh@debian.org>
Standards-Version: 3.9.5
Vcs-Git: git://git.kitenet.net/propellor
Homepage: http://joeyh.name/code/propellor/
Package: propellor
Architecture: any
Section: admin
Depends: ${misc:Depends}, ${shlibs:Depends},
ghc (>= 7.4),
cabal-install,
libghc-async-dev,
libghc-missingh-dev,
libghc-hslogger-dev,
libghc-unix-compat-dev,
libghc-ansi-terminal-dev,
libghc-ifelse-dev,
git,
Description: property-based host configuration management in haskell
Propellor enures that the system it's run in satisfies a list of
properties, taking action as necessary when a property is not yet met.
.
It is configured using haskell.

11
debian/copyright vendored Normal file
View File

@ -0,0 +1,11 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: native package
Files: *
Copyright: © 2010-2014 Joey Hess <joey@kitenet.net>
License: GPL-3+
License: GPL-3+
The full text of version 3 of the GPL is distributed as GPL in
this package's source, or in /usr/share/common-licenses/GPL-3 on
Debian systems.

3
debian/lintian-overrides vendored Normal file
View File

@ -0,0 +1,3 @@
# These files are used in a git repository that propellor sets up.
propellor: package-contains-vcs-control-file usr/src/propellor/.gitignore
propellor: extra-license-file usr/src/propellor/GPL

15
debian/propellor.1 vendored Normal file
View File

@ -0,0 +1,15 @@
.\" -*- nroff -*-
.TH propellor 1 "Commands"
.SH NAME
propellor \- property-based host configuration management in haskell
.SH SYNOPSIS
.B propellor [options] host
.SH DESCRIPTION
.I propellor
is a property-based host configuration management program written
and configured in haskell.
.PP
The first time you run propellor, it will set up a ~/.propellor/
repository. Edit ~/.propellor/config.hs to configure it.
.SH AUTHOR
Joey Hess <joey@kitenet.net>

14
debian/rules vendored Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/make -f
# Avoid using cabal, as it writes to $HOME
export CABAL=./Setup
%:
dh $@
override_dh_auto_build:
$(MAKE) build
override_dh_installdocs:
dh_installdocs README.md TODO
override_dh_installman:
dh_installman debian/propellor.1

View File

@ -1,5 +1,5 @@
Name: propellor
Version: 0.2.0
Version: 0.2.1
Cabal-Version: >= 1.6
License: GPL
Maintainer: Joey Hess <joey@kitenet.net>
@ -14,20 +14,35 @@ Extra-Source-Files:
README.md
TODO
CHANGELOG
simple-config.hs
Makefile
debian/changelog
debian/README
simple-config.hs
debian/README.Debian
debian/propellor.1
debian/compat
debian/control
debian/copyright
debian/rules
debian/lintian-overrides
.gitignore
Synopsis: property-based host configuration management in haskell
Description:
Propellor enures that the system it's run in satisfies a list of
properties, taking action as necessary when a property is not yet met.
.
While Propellor can be installed from hackage, to customize and use it
you should fork its git repository and modify it from there:
git clone git://git.kitenet.net/propellor
It is configured using haskell.
Executable propellor
Main-Is: propellor.hs
GHC-Options: -Wall
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
IfElse, process, bytestring, hslogger, unix-compat, ansi-terminal,
containers, network, async
if (! os(windows))
Build-Depends: unix
Executable config
Main-Is: config.hs
GHC-Options: -Wall -threaded
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
@ -38,7 +53,7 @@ Executable propellor
Build-Depends: unix
Library
GHC-Options: -Wall -threaded
GHC-Options: -Wall
Build-Depends: MissingH, directory, filepath, base >= 4.5, base < 5,
IfElse, process, bytestring, hslogger, unix-compat, ansi-terminal,
containers, network, async

91
propellor.hs Normal file
View File

@ -0,0 +1,91 @@
-- | Wrapper program for propellor distribution.
--
-- Distributions should install this program into PATH.
-- (Cabal builds it as dict/build/propellor.
--
-- This is not the propellor main program (that's config.hs)
--
-- This installs propellor's source into ~/.propellor,
-- uses it to build the real propellor program (if not already built),
-- and runs it.
--
-- The source is either copied from /usr/src/propellor, or is cloned from
-- git over the network.
import Utility.UserInfo
import Utility.Monad
import Utility.Process
import Utility.SafeCommand
import Utility.Directory
import Control.Monad
import Control.Monad.IfElse
import System.Directory
import System.FilePath
import System.Environment (getArgs)
import System.Exit
import System.Posix.Directory
srcdir :: FilePath
srcdir = "/usr/src/propellor"
-- Using the github mirror of the main propellor repo because
-- it is accessible over https for better security.
srcrepo :: String
srcrepo = "https://github.com/joeyh/propellor.git"
main :: IO ()
main = do
args <- getArgs
home <- myHomeDir
let propellordir = home </> ".propellor"
let propellorbin = propellordir </> "propellor"
wrapper args propellordir propellorbin
wrapper :: [String] -> FilePath -> FilePath -> IO ()
wrapper args propellordir propellorbin = do
unlessM (doesDirectoryExist propellordir) $
makeRepo
buildruncfg
where
chain = do
(_, _, _, pid) <- createProcess (proc propellorbin args)
exitWith =<< waitForProcess pid
makeRepo = do
putStrLn $ "Setting up your propellor repo in " ++ propellordir
putStrLn ""
ifM (doesDirectoryExist srcdir)
( do
void $ boolSystem "cp" [Param "-a", File srcdir, File propellordir]
changeWorkingDirectory propellordir
void $ boolSystem "git" [Param "init"]
void $ boolSystem "git" [Param "add", Param "."]
setuprepo True
, do
void $ boolSystem "git" [Param "clone", Param srcrepo, File propellordir]
void $ boolSystem "git" [Param "remote", Param "rm", Param "origin"]
setuprepo False
)
setuprepo fromsrcdir = do
changeWorkingDirectory propellordir
whenM (doesDirectoryExist "privdata") $
mapM_ nukeFile =<< dirContents "privdata"
void $ boolSystem "git" [Param "commit", Param "--allow-empty", Param "--quiet", Param "-m", Param "setting up propellor git repository"]
void $ boolSystem "git" [Param "remote", Param "add", Param "upstream", Param srcrepo]
-- Connect synthetic git repo with upstream history so
-- merging with upstream will work going forward.
-- Note -s outs is used to avoid getting any divergent
-- changes from upstream.
when fromsrcdir $ do
void $ boolSystem "git" [Param "fetch", Param "upstream"]
version <- readProcess "dpkg-query" ["--showformat", "${Version}", "--show", "propellor"]
void $ boolSystem "git" [Param "merge", Param "-s", Param "ours", Param version]
buildruncfg = do
changeWorkingDirectory propellordir
ifM (boolSystem "make" [Param "build"])
( do
putStrLn ""
putStrLn ""
chain
, error "Propellor build failed."
)