{"id":23477792,"url":"https://github.com/michael-yuji/xc","last_synced_at":"2025-04-14T20:34:14.335Z","repository":{"id":178104523,"uuid":"661100539","full_name":"michael-yuji/xc","owner":"michael-yuji","description":"FreeBSD container engine","archived":false,"fork":false,"pushed_at":"2024-03-31T08:52:38.000Z","size":7439,"stargazers_count":91,"open_issues_count":5,"forks_count":10,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-03-28T08:51:15.332Z","etag":null,"topics":["container","freebsd"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michael-yuji.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-01T19:40:00.000Z","updated_at":"2025-02-26T13:12:53.000Z","dependencies_parsed_at":"2024-12-24T18:45:07.060Z","dependency_job_id":null,"html_url":"https://github.com/michael-yuji/xc","commit_stats":null,"previous_names":["michael-yuji/xc"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fxc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fxc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fxc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-yuji%2Fxc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michael-yuji","download_url":"https://codeload.github.com/michael-yuji/xc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248956604,"owners_count":21189378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","freebsd"],"created_at":"2024-12-24T18:33:42.219Z","updated_at":"2025-04-14T20:34:14.309Z","avatar_url":"https://github.com/michael-yuji.png","language":"Rust","readme":"# xc\n##### This README last updated on 31st March, 2024\n\nxc is a work-in-progress container engine for FreeBSD that is capable to run FreeBSD containers and Linux (Docker) containers. Unlike `podman`, this project is intend to be more FreeBSD focused and made adjustment to support and integrate with FreeBSD specific features, such as `Pf`, `ZFS`, `DTrace` and `Jail`(including nested jails/containers and VNET/Non-VNET networking).\n\nPlease scroll to [Quick Start](#quick-start) session for usage. To under start `xc` a bit more and how everything is put together, please jump to [In-depth documentation](#in-depth-documentation) session.\n\nA more detailed (but bit outdated) documentation can be found [here](https://hackmd.io/7BIT_khIRQyPAe4EdiigHg)\n\n# Quick Start\n\nThis session covers how to use [xc](https://github.com/michael-yuji/xc), the FreeBSD container engine.\n\n`xc` is not yet available as a port, so you'll have to build and install by yourself. Luckily, the process is easy.\n\n## Requirement:\n- FreeBSD 14 (amd64 or arm64)\n- ZFS\n- Enable pf\n\n## Build and install\nRun the following commands. If you prefer `doas` over `sudo`, feel free to use it.\n```shell\nsudo pkg install git cmake rust\ngit clone https://github.com/michael-yuji/xc.git\ncd xc \u0026\u0026 cargo build --release\nsudo cp target/release/xcd /usr/local/sbin\nsudo cp target/release/{ocitar, xc} /usr/local/bin\n```\n\n## Configuration\nBefore configuring `xc`. Give the following questions a thought:\n- which network interface should serve as the external interface for your containers\n- in which ZFS pool/dataset you wish the data lives in\n\nAssume the answer of your first question in `em0`, and for the second question `zroot/xc`, create a yaml file at `/usr/local/etc/xc.conf`.\n\n```yaml\n# for published ports, for example `-p 80:8080`, only packets reaching\n# the `ext_ifs` forwards to the container(s) by default\next_ifs: \n    - em0\n\n# dataset to store the container images, each image becomes a child dataset\nimage_dataset: zroot/xc/datasets\n\n# dataset contains the root of running containers\ncontainer_dataset: zroot/xc/run\n\n# dataset serving volumes\ndefault_volume_dataset: zroot/xc/volumes\n```\n\n### Make network accessible\n\nPart of the core value of `xc` is to bring operator no surprise, hence it is not going to configure networking/firewall setting for you automatically.\n\nInstead, `xc` creates entries, allocate and set ip addresses, insert forwarding rules to anchors you provides explicitly. Therefore, we need to add some rules to our pf configuartion to forward packets.\n\nFirst, ensure that the host can forward packets. To make the following command preserve across reboots, add `gateway_enable=\"YES\"` to `rc.conf`.\n\n`sysctl net.inet.ip.forwarding=1`\n\nNow, create following to `pf.conf`. We are assuming to use `em0` to serve internet traffic for our containers.\n\n```\next_if=\"em0\"\nnat on $ext_if from \u003cxc:network:default\u003e to any -\u003e ($ext_if)\nrdr-anchor xc-rdr\n```\n\nYou may have notice the pf table `\u003cxc:network:default\u003e`. We are going to create an xc network named `default` later. Whenever a container request an address from this network, `xc` insert the address to this table such that the `nat` rule will work.\n\nSimilarly, `xc` insert its port forwarding rules to `xc-rdr`. loading this anchor causes the forwarding rules created by `xc` to work.\n\n### Creating network interface\n\n```shell\nifconfig bridge create name xc0\nifconfig xc0 172.16.0.254/24 up\n```\n\nAs mentioned before, `xc` never invade your network without your explicit setup, instead you tell `xc` where you want the containers' connectivities should go. We are going to create the `default` network later, and all containers using the `default` network will either create an alias on this interface (if it's a non-VNET container), or create a `epair` interface and add as a member to this bridge.\n\n## Starting up\n\nIn a different terminal, or in a tmux session, start `xcd` as root.\n`sudo xcd`\n\n### Creating our first network\nAs mentioned in the previous session, we are going to create our first network for our containers. Let's call it `default`.\n\n`xc create network --alias xc0 --bridge xc0 --default-router 172.16.0.254 default 172.16.0.0/24`\n\nThis tells xc to create a network that\n- named `default`\n- with address pool of `172.16.0.0/24`, `xc` can automatically allocate address from this pool if an explicit address is not specified\n- when create a non-VNET jail, create the IP alias on `xc0`\n- when create a VNET jail, bridge the `epair` interface to `xc0`\n\n### Create our first FreeBSD container\n\nFirst pull the container image\n```\nxc pull freebsdxc/freebsd:13.2\n```\nNow run the container. A network-less container is useless, so let's make it a VNET jail (`--vnet`) and attach to the network we created earlier, `default`:\n```\nxc run -it --vnet --network default -- /bin/sh\n```\n\nNow you have your very first container to play with.\n\n### Using Linux containers from DockerHub\n\n`xc` can run Linux containers via FreeBSD Linuxulator.\n\nFirst you need to configure your host to support that, that includes loading the required kernel modules and a sysctl to make the kernel run unknown ELF binary as Linux binaries (go binaries does that).\n\nLoad the following kernel modules: `kldload linux64 linprocfs linsysfs`\n\nYou may want to run `kldload linux` as well to run i386 Linux containers.\n\nModify the sysctl: `kern.elf64.fallback_brand=3`\n\n#### Try!\n\nPull the Linux mariadb 10.9 image from dockerhub:\n```shell\nxc pull library/mariadb:10.9\n```\n\nRun it:\n```shell\nxc run -e MARIADB_ROOT_PASSWORD=password library/mariadb:10.9\n```\n\n# In-Depth documentation\n🚧 under construction and refinement 🚧 \n\n## Configuration\n`xc` now take yaml configuration. The scheme (`struct XcConfig`) for the configuration file can be found at `xcd/src/config/mod.rs`. By default, `xcd` looks for the configuration at `/usr/local/etc/xc.config`\n\n## Architecture\n\nThe core of `xc` is `xcd`, the daemon handles basically everything. `xc`, the client program, submit requests to the daemon via UNIX socket, typically at `/var/run/xc.sock`. Unlike similar container technology such as `docker`, `xcd` does not accept HTTP requests but instead accepts `JSON` encoded requests, sometimes with file descriptors. \n\nEvery request `xcd` receives contains a method name and the corresponding payload. There are macros available to generate new methods to extend the features of `xc`. See `$src/xcd/src/ipc.rs` for examples.\n\nThe macro to define a new method also creates client-side helper functions `pub fn do_$method(..)` and can be used in the `xc` client program.\n\nThe global state of the daemon is called `Context`, and is defined in `$src/xcd/src/context.rs`.\n\n### Containers\n\nThe global state (Context) owns a number of `Site`s. A `Site` is essentially an abstraction of \"a place a container lives in\". Think `Context` is a landlord, a `Site` is a portion of land the landlord rents out.\n\nThe purpose of this abstraction is to separate the duty of cleaning up a container. System-wise resources are made to clean up at the `Site` level, for example, destroying ZFS datasets, releasing IP addresses, etc, things that the tenant (container) shouldn't, and couldn't care about. This allows the global resources to always cleanup no matter what happened in the container to cause an exit (Jail cannot be created, precondition failure, executable crashed, cannot run the executable, etc...).\n\nThis is also planned to support FreeBSD containers that require multiple hosts to function in the future. More specifically, `Root-on-NFS` Jails, whose root filesystem may be exported by a different host than the host running the processes. In these cases, each host owns a site that references/relates to **one** container.\n\nOn the other hand. Once a site is created, the daemon process fork and run a kqueue backed run loop in the child process. This run-loop is responsible for spawning and reaping processes in the Jail, as well as collecting matrices. The site communicates with the run-loop via a UNIX socket pair, which sometimes also forwards file descriptors received from `xc` client to the run-loop. For example, in the case of `xc exec` without pty, the `stdout` and `stderr` file descriptors of the `xc` client process are first sent to the `xcd` daemon, which is later forwarded to the run-loop to use as the `stdout` and `stderr` of the new process.\n\nReaping is done by tracing the PIDs via `NOTE_TRACK` of `EVFILT_PROC` of `kqueue`. This allows us to reap processes without having an `init` in the Jail nor using `procctl`. The benefit of **not** using an `init` is to allow us only to track selections of process sub-trees that are directly related to the container lifetime. By doing this, we can prevent some long-running processes irrelevant to the container's lifetime (such as profiling/analytics) from stopping the container from exiting.\n\nBy default, unlike in `Docker`, `xc` waits for **all** descendants of the main process to exit before killing the container, instead of just the main process. In other words, processes such as `nginx` that immediately daemonize itself can run un-modified without special flags or `init`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-yuji%2Fxc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichael-yuji%2Fxc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-yuji%2Fxc/lists"}