Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
- 'VERSION'
dockerfile:
- 'Dockerfile'
- 'Dockerfile.freebsd'
c:
- 'Makefile'
- 'main.c'
Expand Down
66 changes: 65 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,68 @@ jobs:
-a "ref=${{github.sha}}" \
-a "author=Nubificus LTD"

build-freebsd:
# Cross-compiled on a Linux amd64 runner (see Dockerfile.freebsd); the
# resulting image is stamped os=freebsd and amended into the manifest list
# below. Required: a FreeBSD build failure blocks the pipeline.
runs-on: ${{ format('{0}-{1}', join(fromJSON(inputs.runner), '-'), 'amd64') }}
permissions:
id-token: write # to complete the identity challenge with sigstore/fulcio when running outside of PRs
env:
IMAGE_NAME: ${{ inputs.registry }}/${{ github.repository }}
steps:
- name: Checkout the repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Set short SHA
run: echo "SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

- name: Log into registry ${{ inputs.registry }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
with:
registry: ${{ inputs.registry }}
username: ${{ secrets.harbor_user }}
password: ${{ secrets.harbor_secret }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=freebsd-amd64-

- name: Build and push urunit FreeBSD image
id: build-and-push
uses: docker/build-push-action@9e436ba9f2d7bcd1d038c8e55d039d37896ddc5d # master
with:
context: .
file: "Dockerfile.freebsd"
platforms: freebsd/amd64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
provenance: false

- name: Install cosign
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # main

- name: Sign the published Docker image
env:
COSIGN_EXPERIMENTAL: "true"
DIGEST: ${{steps.build-and-push.outputs.digest}}
run: |
cosign sign --yes ${{ env.IMAGE_NAME }}@$DIGEST \
-a "repo=${{github.repository}}" \
-a "workflow=${{github.workflow}}" \
-a "ref=${{github.sha}}" \
-a "author=Nubificus LTD"

manifest:
needs: [build-all]
needs: [build-all, build-freebsd]
runs-on: base-dind-2204-amd64
permissions:
id-token: write # to complete the identity challenge with sigstore/fulcio when running outside of PRs
Expand Down Expand Up @@ -140,6 +200,10 @@ jobs:
amend_command+=" --amend ${{ env.IMAGE_NAME }}:$arch-${{ env.SHA_SHORT }}"
done

# Include the FreeBSD image (build-freebsd is a required dependency,
# so if we got here it was built and pushed).
amend_command+=" --amend ${{ env.IMAGE_NAME }}:freebsd-amd64-${{ env.SHA_SHORT }}"

echo "-------------------- Amend command constructed -------------------"
echo "$amend_command"

Expand Down
38 changes: 38 additions & 0 deletions Dockerfile.freebsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Builds the FreeBSD static urunit and packages it into a scratch image.
#
# The build runs on a Linux builder and cross-compiles for FreeBSD with clang +
# lld against a sysroot extracted from the FreeBSD base distribution. The final
# scratch stage only copies the binary, so nothing FreeBSD is ever executed at
# build time. Stamp the image OS with buildx, e.g.:
#
# docker buildx build --platform freebsd/amd64 -f Dockerfile.freebsd .
#
# which sets os=freebsd in the resulting image config.

FROM --platform=$BUILDPLATFORM alpine AS builder

ARG FREEBSD_VERSION=14.3-RELEASE
ARG TARGET_TRIPLE=x86_64-unknown-freebsd14.3

WORKDIR /urunit

RUN apk add --no-cache clang lld make curl tar xz

# FreeBSD sysroot: headers plus the (static) libraries and startup objects from
# the base distribution. Only the parts a sysroot needs are extracted.
RUN mkdir -p /sysroot && \
curl -fsSL "https://download.freebsd.org/releases/amd64/amd64/${FREEBSD_VERSION}/base.txz" \
| tar -xJf - -C /sysroot ./lib ./usr/lib ./usr/include

COPY Makefile .
COPY src src

# TARGET_OS must be explicit: the Makefile would otherwise infer the OS from the
# Linux builder's uname. Everything the cross toolchain needs rides on CC.
RUN make TARGET_OS=FreeBSD \
CC="clang --target=${TARGET_TRIPLE} --sysroot=/sysroot -fuse-ld=lld" \
static

FROM scratch
COPY --from=builder /urunit/dist/urunit_static /urunit
ENTRYPOINT ["/urunit"]
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ endif
ifeq ($(TARGET_OS),Linux)
URUNIT_SRC += ${SOURCE_DIR}/linux.c
endif
ifeq ($(TARGET_OS),FreeBSD)
URUNIT_SRC += ${SOURCE_DIR}/freebsd.c
endif

# Main Building rules
#
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ following information:

- The list of the environment variables to set for the application
- The configuration for the process execution environment.
- The application command to execute, when `urunit` is started without a
command line (optional).
- The list of mounts of block devices. Each block device is defined by its
serial id and it will get mounted in the defined mountpoint.
- The network configuration (IP address, gateway and netmask) for guests
that can not get it from the kernel command line (optional).

The file can be specified to `urunit` setting the `URUNIT_CONFIG`
environment variable with the path to the configuration file.
Expand All @@ -86,14 +90,32 @@ UCS
UID: <uid_for_the_application>
GID: <gid_for_the_application>
WD: <working_directory>
ARC: <number_of_application_arguments>
ARV: <application_argument>
...
UCE
UBS
ID: <serial_id>
MP: <mountpoint>
...
UBE
UNS
IP: <ipv4_address>
GW: <gateway>
MSK: <netmask>
UNE
```

Inside the `UCS` section, the application command is optional: `ARC` holds the
number of arguments and is followed by exactly that many `ARV` lines, one per
argument, each taken verbatim. It is used when `urunit` is started without a
command line, in which case the command from the configuration is executed.

The `UNS` section is optional and provides the network configuration for
guests that can not get it from the kernel command line: `IP` is the IPv4
address, `GW` the gateway and `MSK` the netmask. An empty value (e.g. `IP:`)
leaves the field unset.

## Installation

Using one of the following methods, we can install `urunit` either in a
Expand Down
24 changes: 18 additions & 6 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@
#define DEBUG_PRINTF(fmt, ...) \
do { if (SHOW_DEBUG) fprintf(stderr, "[DEBUG] " fmt, __VA_ARGS__); } while (0)

#define DEBUG_PRINT(fmt, ...) \
#define DEBUG_PRINT(fmt) \
do { if (SHOW_DEBUG) fprintf(stderr, "[DEBUG] " fmt); } while (0)

struct block_config {
char *id;
char *mountpoint;
};

struct net_config {
char *ip;
char *gateway;
char *mask;
};

int ensure_dir(const char *path);
int mkdir_all(const char *path, mode_t mode, char *first_dir);
int rm_empty_dirs(const char *dir, const char *top_dir);
Expand All @@ -49,14 +55,20 @@ int is_block_fs(const char *fs_type);
int is_network_fs(const char *fs_type);
int is_cloud_storage_fs(const char *fs_type);

// Platform specific functions
int setup_console(void);
int remount_root_rw(void);
char *get_boot_var(const char *name);
char *read_raw_device(int fd, size_t *size);
int configure_network(struct net_config *net);
int read_block_dev_serial(const char *device_name, char *serial, const size_t size);
int find_vblock_device_by_order(const uint32_t n, char *device_path);
int find_vblock_device_by_serial(const char *target_serial, char *device_path);
int mount_special_fs();
int mount_special_fs(void);
int mount_block_vols(struct block_config **vols);
int set_default_route();
void unmount_external();
int set_subreaper();
void request_reboot();
int set_default_route(void);
void unmount_external(void);
int set_subreaper(void);
void request_reboot(void);

#endif // COMMON_H
Loading
Loading