diff --git a/.github/workflows/oci-distribution.yml b/.github/workflows/oci-distribution.yml new file mode 100644 index 0000000..a1adfc7 --- /dev/null +++ b/.github/workflows/oci-distribution.yml @@ -0,0 +1,47 @@ +name: OCI distribution +on: + workflow_dispatch: + schedule: + - cron: "0 10 * * *" +permissions: + contents: read + packages: write + id-token: write +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + component: + - kratactl + - kratad + - kratanet + name: OCI build ${{ matrix.component }} on ${{ matrix.platform }} + steps: + - uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 + with: + egress-policy: audit + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: recursive + - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + - uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 + - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/build-push-action@15560696de535e4014efeff63c48f16952e52dd1 # v6.2.0 + id: push-step + with: + file: ./images/Dockerfile.${{ matrix.component }} + platforms: linux/amd64,linux/aarch64 + tags: ghcr.io/edera-dev/${{ matrix.component }}:nightly + push: true + - name: Sign the image + env: + DIGEST: ${{ steps.push-step.outputs.digest }} + TAGS: ghcr.io/edera-dev/${{ matrix.component }}:nightly + COSIGN_EXPERIMENTAL: "true" + run: cosign sign --yes "${TAGS}@${DIGEST}" diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 77ad74e..dac4081 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -17,7 +17,7 @@ jobs: - uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 with: egress-policy: audit - - uses: actions/create-github-app-token@c8f55efbd427e7465d6da1106e7979bc8aaee856 # v1.10.1 + - uses: actions/create-github-app-token@ad38cffc07bac6e3857755914c4c88bfd2db4da4 # v1.10.2 id: generate-token with: app-id: "${{ secrets.EDERA_CULTIVATION_APP_ID }}" diff --git a/Cargo.lock b/Cargo.lock index a8fad26..24f59ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,26 +249,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.5.0", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.57", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -365,15 +345,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -411,17 +382,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da987586004ae7c43b7df5e3f7693775068522e1086f8d9b2d74c778a0f43313" -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "4.5.7" @@ -1027,12 +987,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "h2" version = "0.3.26" @@ -1526,6 +1480,13 @@ dependencies = [ "tokio", ] +[[package]] +name = "krata-loopdev" +version = "0.0.11" +dependencies = [ + "libc", +] + [[package]] name = "krata-network" version = "0.0.11" @@ -1587,6 +1548,7 @@ dependencies = [ "ipnetwork", "krata", "krata-advmac", + "krata-loopdev", "krata-oci", "krata-xenclient", "krata-xenevtchn", @@ -1594,7 +1556,6 @@ dependencies = [ "krata-xenplatform", "krata-xenstore", "log", - "loopdev-3", "serde_json", "tokio", "uuid", @@ -1708,28 +1669,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets 0.52.4", -] - [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -1752,17 +1697,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "loopdev-3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a97d7a5124296ee9124a815acdc3dc4a91f577b72812b3f1f99bb959b46e8d" -dependencies = [ - "bindgen", - "errno", - "libc", -] - [[package]] name = "lru" version = "0.12.3" @@ -1807,12 +1741,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1952,16 +1880,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "ntapi" version = "0.4.1" @@ -2706,9 +2624,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "itoa", "ryu", @@ -2773,12 +2691,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook" version = "0.3.17" @@ -3404,9 +3316,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea73390fe27785838dcbf75b91b1d84799e28f1ce71e6f372a5dc2200c80de5" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom", ] diff --git a/Cargo.toml b/Cargo.toml index 35a0f30..1e9d96b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ redb = "2.1.1" regex = "1.10.5" rtnetlink = "0.14.1" scopeguard = "1.2.0" -serde_json = "1.0.117" +serde_json = "1.0.118" serde_yaml = "0.9" sha256 = "1.5.0" signal-hook = "0.3.17" @@ -123,7 +123,7 @@ version = "0.11.0" features = ["tls"] [workspace.dependencies.uuid] -version = "1.9.0" +version = "1.9.1" features = ["v4"] [profile.release] diff --git a/crates/loopdev/Cargo.toml b/crates/loopdev/Cargo.toml new file mode 100644 index 0000000..3458606 --- /dev/null +++ b/crates/loopdev/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "krata-loopdev" +description = "Loop device handling library for krata" +license.workspace = true +version.workspace = true +homepage.workspace = true +repository.workspace = true +edition = "2021" +resolver = "2" + +[lib] +name = "krataloopdev" + +[dependencies] +libc.workspace = true diff --git a/crates/loopdev/src/lib.rs b/crates/loopdev/src/lib.rs new file mode 100644 index 0000000..c642b07 --- /dev/null +++ b/crates/loopdev/src/lib.rs @@ -0,0 +1,354 @@ +use libc::{c_int, ioctl}; +use std::{ + fs::{File, OpenOptions}, + io, + os::fd::{AsRawFd, IntoRawFd, RawFd}, + os::unix::fs::MetadataExt, + path::{Path, PathBuf}, +}; + +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] +type IoctlRequest = libc::c_ulong; +#[cfg(any(target_os = "android", target_env = "musl"))] +type IoctlRequest = libc::c_int; + +const LOOP_CONTROL: &str = "/dev/loop-control"; +const LOOP_PREFIX: &str = "/dev/loop"; + +/// Loop control interface IOCTLs. +const LOOP_CTL_GET_FREE: IoctlRequest = 0x4C82; + +/// Loop device flags. +const LO_FLAGS_READ_ONLY: u32 = 1; +const LO_FLAGS_AUTOCLEAR: u32 = 4; +const LO_FLAGS_PARTSCAN: u32 = 8; +const LO_FLAGS_DIRECT_IO: u32 = 16; + +/// Loop device IOCTLs. +const LOOP_SET_FD: IoctlRequest = 0x4C00; +const LOOP_CLR_FD: IoctlRequest = 0x4C01; +const LOOP_SET_STATUS64: IoctlRequest = 0x4C04; +const LOOP_SET_CAPACITY: IoctlRequest = 0x4C07; +const LOOP_SET_DIRECT_IO: IoctlRequest = 0x4C08; + +/// Interface which wraps a handle to the loop control device. +#[derive(Debug)] +pub struct LoopControl { + dev_file: File, +} + +/// Translate ioctl results to errors if appropriate. +fn translate_error(ret: i32) -> io::Result { + if ret < 0 { + Err(io::Error::last_os_error()) + } else { + Ok(ret) + } +} + +impl LoopControl { + /// Open the loop control device. + /// + /// # Errors + /// + /// Any errors from physically opening the loop control device are + /// bubbled up. + pub fn open() -> io::Result { + Ok(Self { + dev_file: OpenOptions::new() + .read(true) + .write(true) + .open(LOOP_CONTROL)?, + }) + } + + /// Requests the next available loop device from the kernel and opens it. + /// + /// # Examples + /// + /// ```no_run + /// use krataloopdev::LoopControl; + /// let lc = LoopControl::open().unwrap(); + /// let ld = lc.next_free().unwrap(); + /// println!("{}", ld.path().unwrap().display()); + /// ``` + /// + /// # Errors + /// + /// Any errors from opening the loop device are bubbled up. + pub fn next_free(&self) -> io::Result { + let dev_num = translate_error(unsafe { + ioctl( + self.dev_file.as_raw_fd() as c_int, + LOOP_CTL_GET_FREE as IoctlRequest, + ) + })?; + LoopDevice::open(format!("{}{}", LOOP_PREFIX, dev_num)) + } +} + +/// Interface to a loop device itself, e.g. `/dev/loop0`. +#[derive(Debug)] +pub struct LoopDevice { + device: File, +} + +impl AsRawFd for LoopDevice { + fn as_raw_fd(&self) -> RawFd { + self.device.as_raw_fd() + } +} + +impl IntoRawFd for LoopDevice { + fn into_raw_fd(self) -> RawFd { + self.device.into_raw_fd() + } +} + +impl LoopDevice { + /// Opens a loop device. + /// + /// # Errors + /// + /// Any errors from opening the underlying physical loop device are bubbled up. + pub fn open>(dev: P) -> io::Result { + Ok(Self { + device: OpenOptions::new().read(true).write(true).open(dev)?, + }) + } + + /// Attach a loop device to a file with the given options. + pub fn with(&self) -> AttachOptions<'_> { + AttachOptions { + device: self, + info: LoopInfo64::default(), + } + } + + /// Enables or disables Direct I/O mode. + pub fn set_direct_io(&self, direct_io: bool) -> io::Result<()> { + translate_error(unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_SET_DIRECT_IO as IoctlRequest, + if direct_io { 1 } else { 0 }, + ) + })?; + Ok(()) + } + + /// Attach the loop device to a fully-mapped file. + pub fn attach_file>(&self, backing_file: P) -> io::Result<()> { + let info = LoopInfo64 { + ..Default::default() + }; + + Self::attach_with_loop_info(self, backing_file, info) + } + + /// Attach the loop device to a file with `LoopInfo64`. + fn attach_with_loop_info( + &self, + backing_file: impl AsRef, + info: LoopInfo64, + ) -> io::Result<()> { + let write_access = (info.lo_flags & LO_FLAGS_READ_ONLY) == 0; + let bf = OpenOptions::new() + .read(true) + .write(write_access) + .open(backing_file)?; + self.attach_fd_with_loop_info(bf, info) + } + + /// Attach the loop device to a file descriptor with `LoopInfo64`. + fn attach_fd_with_loop_info(&self, bf: impl AsRawFd, info: LoopInfo64) -> io::Result<()> { + translate_error(unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_SET_FD as IoctlRequest, + bf.as_raw_fd() as c_int, + ) + })?; + + let result = unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_SET_STATUS64 as IoctlRequest, + &info, + ) + }; + + match translate_error(result) { + Err(err) => { + let _detach_err = self.detach(); + Err(err) + } + Ok(_) => Ok(()), + } + } + + /// Get the path for the loop device. + pub fn path(&self) -> Option { + let mut p = PathBuf::from("/proc/self/fd"); + p.push(self.device.as_raw_fd().to_string()); + std::fs::read_link(&p).ok() + } + + /// Detach a loop device. + pub fn detach(&self) -> io::Result<()> { + translate_error(unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_CLR_FD as IoctlRequest, + 0, + ) + })?; + Ok(()) + } + + /// Update a loop device's capacity. + pub fn set_capacity(&self) -> io::Result<()> { + translate_error(unsafe { + ioctl( + self.device.as_raw_fd() as c_int, + LOOP_SET_CAPACITY as IoctlRequest, + 0, + ) + })?; + Ok(()) + } + + /// Return the major device node number. + pub fn major(&self) -> io::Result { + self.device + .metadata() + .map(|m| unsafe { libc::major(m.rdev()) }) + .map(|m| m as u32) + } + + /// Return the minor device node number. + pub fn minor(&self) -> io::Result { + self.device + .metadata() + .map(|m| unsafe { libc::minor(m.rdev()) }) + .map(|m| m as u32) + } +} + +#[allow(dead_code)] +#[derive(Clone)] +pub struct LoopInfo64 { + lo_device: u64, + lo_inode: u64, + lo_rdevice: u64, + lo_offset: u64, + lo_sizelimit: u64, + lo_number: u32, + lo_encrypt_type: u32, + lo_encrypt_key_size: u32, + lo_flags: u32, + lo_file_name: [u8; 64], + lo_crypt_name: [u8; 64], + lo_encrypt_key: [u8; 32], + lo_init: [u64; 2], +} + +impl Default for LoopInfo64 { + fn default() -> Self { + Self { + lo_device: 0, + lo_inode: 0, + lo_rdevice: 0, + lo_offset: 0, + lo_sizelimit: 0, + lo_number: 0, + lo_encrypt_type: 0, + lo_encrypt_key_size: 0, + lo_flags: 0, + lo_file_name: [0; 64], + lo_crypt_name: [0; 64], + lo_encrypt_key: [0; 32], + lo_init: [0, 2], + } + } +} + +#[must_use] +pub struct AttachOptions<'d> { + device: &'d LoopDevice, + info: LoopInfo64, +} + +impl AttachOptions<'_> { + pub fn offset(mut self, offset: u64) -> Self { + self.info.lo_offset = offset; + self + } + + pub fn size_limit(mut self, size_limit: u64) -> Self { + self.info.lo_sizelimit = size_limit; + self + } + + pub fn read_only(mut self, read_only: bool) -> Self { + if read_only { + self.info.lo_flags |= LO_FLAGS_READ_ONLY; + } else { + self.info.lo_flags &= !LO_FLAGS_READ_ONLY; + } + self + } + + pub fn autoclear(mut self, autoclear: bool) -> Self { + if autoclear { + self.info.lo_flags |= LO_FLAGS_AUTOCLEAR; + } else { + self.info.lo_flags &= !LO_FLAGS_AUTOCLEAR; + } + self + } + + pub fn part_scan(mut self, part_scan: bool) -> Self { + if part_scan { + self.info.lo_flags |= LO_FLAGS_PARTSCAN; + } else { + self.info.lo_flags &= !LO_FLAGS_PARTSCAN; + } + self + } + + pub fn set_direct_io(mut self, direct_io: bool) -> Self { + if direct_io { + self.info.lo_flags |= LO_FLAGS_DIRECT_IO; + } else { + self.info.lo_flags &= !LO_FLAGS_DIRECT_IO; + } + self + } + + pub fn direct_io(&self) -> bool { + if (self.info.lo_flags & LO_FLAGS_DIRECT_IO) == LO_FLAGS_DIRECT_IO { + true + } else { + false + } + } + + pub fn attach(&self, backing_file: impl AsRef) -> io::Result<()> { + self.device + .attach_with_loop_info(backing_file, self.info.clone())?; + if self.direct_io() { + self.device.set_direct_io(self.direct_io())?; + } + Ok(()) + } + + pub fn attach_fd(&self, backing_file_fd: impl AsRawFd) -> io::Result<()> { + self.device + .attach_fd_with_loop_info(backing_file_fd, self.info.clone())?; + if self.direct_io() { + self.device.set_direct_io(self.direct_io())?; + } + Ok(()) + } +} diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 3f8f5d1..404ce7b 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -16,10 +16,10 @@ krata = { path = "../krata", version = "^0.0.11" } krata-advmac = { workspace = true } krata-oci = { path = "../oci", version = "^0.0.11" } log = { workspace = true } -loopdev-3 = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } uuid = { workspace = true } +krata-loopdev = { path = "../loopdev", version = "^0.0.11" } krata-xenclient = { path = "../xen/xenclient", version = "^0.0.11" } krata-xenevtchn = { path = "../xen/xenevtchn", version = "^0.0.11" } krata-xengnt = { path = "../xen/xengnt", version = "^0.0.11" } diff --git a/crates/runtime/src/autoloop.rs b/crates/runtime/src/autoloop.rs index 85f1fce..c12b360 100644 --- a/crates/runtime/src/autoloop.rs +++ b/crates/runtime/src/autoloop.rs @@ -1,8 +1,8 @@ use std::{sync::Arc, time::Duration}; use anyhow::{anyhow, Result}; +use krataloopdev::{LoopControl, LoopDevice}; use log::debug; -use loopdev::{LoopControl, LoopDevice}; use tokio::time::sleep; use xenclient::BlockDeviceRef; diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 385965f..99a2065 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -3,8 +3,8 @@ use std::{fs, net::Ipv4Addr, path::PathBuf, str::FromStr, sync::Arc}; use anyhow::{anyhow, Result}; use ip::IpVendor; use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; +use krataloopdev::LoopControl; use log::error; -use loopdev::LoopControl; use tokio::sync::Semaphore; use uuid::Uuid; use xenclient::XenClient; diff --git a/images/Dockerfile.kratactl b/images/Dockerfile.kratactl new file mode 100644 index 0000000..cb944ba --- /dev/null +++ b/images/Dockerfile.kratactl @@ -0,0 +1,12 @@ +FROM rust:1.79-alpine AS build +RUN apk update && apk add protoc protobuf-dev build-base && rm -rf /var/cache/apk/* +ENV TARGET_LIBC=musl TARGET_VENDOR=unknown + +WORKDIR /usr/src/app +COPY . . +RUN ./hack/build/cargo.sh build --release --bin kratactl +RUN mv ./target/$(./hack/build/target.sh)/release/kratactl /usr/sbin + +FROM cgr.dev/chainguard/static AS final +ENTRYPOINT ["/usr/sbin/kratactl"] +COPY --from=build /usr/sbin/kratactl /usr/sbin/kratactl diff --git a/images/Dockerfile.kratad b/images/Dockerfile.kratad new file mode 100644 index 0000000..66fa0b6 --- /dev/null +++ b/images/Dockerfile.kratad @@ -0,0 +1,13 @@ +FROM rust:1.79-alpine AS build +RUN apk update && apk add protoc protobuf-dev build-base && rm -rf /var/cache/apk/* +ENV TARGET_LIBC=musl TARGET_VENDOR=unknown + +WORKDIR /usr/src/app +COPY . . +RUN ./hack/build/cargo.sh build --release --bin kratad +RUN mv ./target/$(./hack/build/target.sh)/release/kratad /usr/sbin + +FROM cgr.dev/chainguard/static AS final +ENTRYPOINT ["/usr/sbin/kratad"] +COPY --from=build /usr/sbin/kratad /usr/sbin/kratad +COPY ./resources/systemd/kratad.service /usr/lib/systemd/system/kratad.service diff --git a/images/Dockerfile.kratanet b/images/Dockerfile.kratanet new file mode 100644 index 0000000..f3827f8 --- /dev/null +++ b/images/Dockerfile.kratanet @@ -0,0 +1,13 @@ +FROM rust:1.79-alpine AS build +RUN apk update && apk add protoc protobuf-dev build-base && rm -rf /var/cache/apk/* +ENV TARGET_LIBC=musl TARGET_VENDOR=unknown + +WORKDIR /usr/src/app +COPY . . +RUN ./hack/build/cargo.sh build --release --bin kratanet +RUN mv ./target/$(./hack/build/target.sh)/release/kratanet /usr/sbin + +FROM cgr.dev/chainguard/static AS final +ENTRYPOINT ["/usr/sbin/kratanet"] +COPY --from=build /usr/sbin/kratanet /usr/sbin/kratanet +COPY ./resources/systemd/kratanet.service /usr/lib/systemd/system/kratanet.service