Syncing Configs¶
Let’s say we want to configure a daemon called demonio
(which is spanish
for daemon).
About daemonio
:
- It stores it’s configs in the directory
/etc/daemonio.d
- It can detect configuration changes itself (See Reloading Configs)
- This config of daemon is named
my_daemonio
[1]
[1] | If we ever run multiple instances of the daemon on the same machine or accross the same cluster we need to differentiate different config folders |
Server Setup¶
Configure the service to read configs from
/etc/daemonio-configs/current
instead of/etc/daemonio.d
Note
The point here is: ciruela can sync whole directory of configs and replace it atomically. But to do that we need to grant access for user to the parent directory of the actual config folder. We don’t want to grant access to the whole
/etc
.Drop the following file into
/etc/ciruela/configs/my-daemonio.yaml
:directory: /etc/daemonio-configs num-levels: 1 append-only: false upload-keys: [my_daemonio]
Drop the public key allowed to upload new config into
/etc/ciruela/keys/my_daemonio.key
. (See Client Setup)Note
Multiple keys can be put into the file as well as multiple files can be specified in
upload-keys
in the configuration of the directory. It’s useful to create a file per actual user (potentially having multiple keys) or organize keys in any way you want.Set
ciruela
as the owner of all the directories it should sync:chown -R ciruela /etc/daemonio-configs
Client Setup¶
Human Operator Setup¶
This is mostly useful for testing, because work well mostly for a single user.
Generate a key, it’s same as ssh but in
ed25519
format:ssh-keygen -t ed25519 -f ~/.ssh/id_ciruela -P ""
Note
Ciruela doesn’t support password-protected keys yet.
This also means you can use your normal
~/.ssh/id_ed25519
key, if it isn’t password-protected, but leaving ssh key plain-text isn’t good idea. Ciruela keys are much more lower risk because they allow only uploading a limited set of directories rather than executing any script.Also you may wish to delete the key and use CI system when you finish testing the setup.
Upload the key into
/etc/ciruela/keys/my_daemonio.key
.Run the following every time you need to upload new configs:
ciruela sync server.name --replace local/config/path:/my-daemonio/current
CI Setup¶
Usually CI systems allow to put secret variables into environment, so
you can use CIRUELA_KEY
environment variable for storing keys.
Generate a key, it’s same as ssh but in
id_ed25519
format:ssh-keygen -t ed25519 -f tmp-key -P ""
Upload the private key into CI for
CIRUELA_KEY
, for example for travis you may usetravis encrypt
:travis encrypt "CIRUELA_KEY=$(cat tmp-key)" --add
Add upload command to the task:
ciruela sync server.name --replace ./cfg:/my-daemonio/current
Reloading Configs¶
All of this works if your service can pick up configuration on the fly without any kind of signals.
Making signals for configuration reload is out of scope of this article but here are some ideas:
- You can set a script that compares directory timestamp and signals service if that changes. Ciruela replaces directory atomically so reloading is safe at any time (or as quick as the directory is new)
- You can use some special programs for that (but I’m not sure they are suited for production):
- Some supervisors like supervisord (API) and systemd (API) have RPC for the task
- Maybe you have a UI for the service?
Just to show you that (1) is not as scareful as it sounds, here is an example script for nginx:
#!/bin/sh
DIR=/etc/nginx/conf
CMD="nginx -s reload"
last_stat="$(stat --format="%Z/%Y/%d:%i" "$DIR" || "<absent>")"
while sleep 1; do
new_stat="$(stat --format="%Z/%Y/%d:%i" "$DIR" || "<absent>")"
if [ "$last_stat" != "$new_stat" ]; then
$CMD
endif
done
Note
The script doesn’t detect most changes done on individual config
files, but ciruela always replaces the directory with the new one. And we
detect it by checking inode number "%i"
. Other stat parameters here are
just for being more cautious.
Additional Options¶
If your service has only one configuration file, you should put it into a directory anyway, as ciruela syncs directories. But it’s a good idea since you can add another include file later or just put a README into the dir.
You may want to check configs before uploading. For example run
daemonio --config=./local_config_dir --check-config
on the CI server before upload.You can override keys via
-i
,-e
(seeciruela sync --help
)You can upload multiple dirs simultaneously via:
ciruela sync s1.example.org --replace ./dir1:/dest1 --replace ./dir2:/dest
If server name resolves to multiple IP addresses, ciruela will try to upload to at most three of them (random ones if there are more) and will return non-zero exit status if none of them accepts the upload.
Multiple names on command-line treated as a separate clusters. So ciruela will upload on three servers on each of them:
ciruela sync s1.example.org s1.example.org --replace ./dir1:/dest1
This will report upload progress for every cluster on it’s own.
If these are individual servers use
-m
:ciruela sync -m s1.example.org s1.example.org --replace ./dir1:/dest1
With > 4 servers this makes ciruela upload to at least 75% of them and tolerate few failures. Just like it does for a single cluster name and multiple servers behind.
Mutliple instances of
daemonio
can be configured with a single upload key you may put multiple configurations into the single directory:- /etc/daemonio-configs/my_daemonio
- /etc/daemonio-configs/other_daemonio
Or you can group all configured services under single folder (if you don’t need to differentiate permissions for them):
- /etc/syncing-configs/daemonio
- /etc/syncing-configs/nginx
- /etc/syncing-configs/my-other-service