Medic OS packages are similar in format to Debian-style .deb
packages: they
consist of a compressed tar
archive alongside an assortment of package
metadata files, all combined together into a single file using the ar
archive
utility. For lack of a better abbreviation, packages for Medic OS currently end
in .vpkg
.
Inside of the Medic OS source tree, packages are currently assembled using the
https://github.com/medic/medic-os/blob/master/platform/scripts/build-package
script. The enclosing ar
archive is created using GNU ar
– specifically,
via ar -rcs "$package_root_dir"
. The ar
utility can be found in the GNU
binutils
package on most systems.
Inside of the ar
archive, a typical Medic OS package contains the following
files:
- package.tar.xz
- The compressed
tar
payload, containing binaries, configuration data, and all other files required for the software to function properly. The archive should contain correct user/group and permission data; paths inside of this archive should be relative. The files will be extracted beneath/srv
at package installation time. Packages cannot directly place files outside of/srv
by design; if you need to make changes to files located on theinitrd
-based root filesystem, see the section on package setup scripts below. Thegz
,bz2
, andlzma
compression formats are also supported, but their use is discouraged for space-efficiency and uniformity reasons. - name
- The base name of the package, without any version or architecture/platform
information, e.g.
medic-core
. - version
- The package version. For simplicity purposes, this must be a whole integer expressed as ASCII text; the file should contain no other characters other than trailing whitespace. The version number must increase monotonically as the package is updated.
- build-timestamp
- An ISO 8601 timestamp indicating the date and time at which the package was assembled.
- platform
- The platform for which this package is intended. Currently, this must be
either
x64
,x86
, orarmv6
. - digest-md5, digest-sha1, digest-sha256, digest-sha512
- The cryptographic digest of the
tar
archive described above, stored in hexadecimal notation as ASCII text. At least one of these files must be present. -
signature
- A cryptographic signature for the
tar
archive described above. This is currently optional, but may be required in a future version.
Every package should have an env
script; this should be an ash
-compatible
shell script that, at a minimum, exports the PACKAGE_ROOT
, PACKAGE_NAME
,
and PACKAGE_VERSION
environment variables. The env
script should be
installed to /srv/scripts/$PACKAGE_NAME/env
.
For an example of an env
script, see
the Medic OS repository
on Github.
The env
file is not automatically sourced by any of the system scripts;
it is the responsibility of individual setup/init scripts to source
it.
The env
file does not need to be executable (i.e. does not need mode
+x
).
At boot, and following any package installation operations, the Medic OS
system will execute any scripts beneath /srv/scripts/$PACKAGE_NAME/setup
that have mode o+x
. These scripts bust be ash
-compatible, and are
largely used to apply changes to the in-memory initrd
filesystem – e.g.
installing cron jobs, creating/migrating credentials, or preprocessing
configuration files. Scripts placed beneath this directory should not
have a file extension.
Placing an executable script beneath /srv/scripts/$PACKAGE_NAME/run
creates a service – a long-running supervised process that is
automatically restarted upon termination, and can be controlled via the
set of management scripts described in
INTERNALS.md.
A service script must block for the duration of the service's lifetime,
typically by using the shell's exec
function. Scripts placed beneath
this directory should not have a file extension; the service name will
exactly match the name of its run
script. There is no support for
explicit startup ordering or dependency management; startup/init scripts
are currently left to fend for themselves in that regard.
Medic OS ships with Busybox's cron
, preconfigured to automatically run
scripts in any of several .d
style directories – cron.always
,
cron.daily
, cron.hourly
, cron.monthly
, and cron.weekly
. The
cron.always
directory is run every minute and should be used sparingly.
Scripts that are not explicitly marked as executable are ignored.
The .d
directories for cron
are located beneath
/srv/settings/system-services/cron
and /etc
by default. The .d
directories beneath /etc
are volatile: the contents will be discarded
upon system shutdown. The .d
directories beneath
/srv/settings/system-services/cron
are persistent. Both directory
subtrees are included in the system's preconfigured crontab
file.
To add a new package-associated cron
job, you should use a setup
script (described above) to copy your job into the appropriate .d
directory. Package setup scripts are run at boot; all setup scripts and
cron job scripts must be ash
-compatible: bash
is not available.
If you know what you're doing and why, you may alternatively use the
persistent .d
directories beneath /srv/settings/system-services/cron
,
copying the job in from your package's install
script (or by including
it directly in the package's tar archive).
The default crontab configuration is as follows:
# Run 'always' cron jobs every minute (use sparingly)
* * * * * /boot/run-directories /etc/cron.always /srv/settings/system-services/cron/cron.always
# Run hourly cron jobs at 30 minutes after the hour:
30 * * * * /boot/run-directories /etc/cron.hourly /srv/settings/system-services/cron/cron.hourly
# Run daily cron jobs at 12:30 every day:
30 12 * * * /boot/run-directories /etc/cron.daily /srv/settings/system-services/cron/cron.daily
# Run weekly cron jobs at 13:00 on the first day of the week:
30 13 * * 0 /boot/run-directories /etc/cron.weekly /srv/settings/system-services/cron/cron.weekly
# Run monthly cron jobs at 13:30 on the first day of the month:
30 13 1 * * /boot/run-directories /etc/cron.monthly /srv/settings/system-services/cron/cron.monthly