Skip to content
Open
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 CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(RURIMA_CORE_SOURCES
src/ruri/src/rootless.c
src/ruri/src/mount.c
src/ruri/src/k2v.c
src/ruri/src/k2v3.c
src/ruri/src/elf-magic.c
src/ruri/src/config.c
src/ruri/src/cgroup.c
Expand Down
123 changes: 99 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
* This program has no Super Cow Powers.
```
This project does not follow OCI standard and can only be a `PARTIAL` replacement of docker, this project is still under development.
For Android users, You might need to root your phone before using rurima, some container might not work properly with proot.
# Presets:
We are working on some presets for using rurima to build your own projects, you can find them in the [presets](presets) directory.
The first preset is for running debian vm with avf on MTK devices, and we will add more presets in the future, PRs are welcome!
For Android users, You might need to root your phone before using rurima, some container might not work properly with proot.
# About:
So, what is rurima?
The enhanced version of ruri.
[ruri](https://github.com/Moe-hacker/ruri) only focus on running container, but rurima can also provide the function of getting rootfs image and backup/restore.
And it will be a more powerful container manager in the fulture.
With the `docker` and `lxc` subcommand of rurima, you can search & get & unpack images from dockerhub or LXC mirror easily.
# Features:
- Get rootfs images from dockerhub or LXC mirror.
- Automatic parse docker image config and convert to ruri cmdline.
Expand All @@ -35,32 +38,104 @@ The first preset is for running debian vm with avf on MTK devices, and we will a
- Static binary for multiple architectures.
- Built-in OTA(upgrade) feature.

In a word, rurima is a lightweight container implementation, it tries to get the most features of docker with the least dependencies, even when your kernel does not support cgroups or namespaces.
In a word, rurima is a lightweight container implementation, it tries to get the most features of docker with the least dependencies, even when your kernel does not support cgroups or namespaces.
# Demo:

<details>
<summary>Click to expand</summary>

```text
~ $ sudo rurima pull openlistteam/openlist ./openlist
Pulling 20158f18ba671f0b as layer-0
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-0
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling ec81343d31bcd4b6 as layer-1
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-1
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling 889dce16043c6e0b as layer-2
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-2
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling 26e754cd7c62b57e as layer-3
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-3
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling 4f4fb700ef54461c as layer-4
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-4
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling bd69fdf7a20439e0 as layer-5
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-5
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling ec5dfd7cdbbd5a97 as layer-6
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-6
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling 53c5100b64211b73 as layer-7
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-7
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Pulling 4f4fb700ef54461c as layer-8
[///////////////////////////////////////////////////////////////////////////////] 100.00%
Extracting layer-8
[///////////////////////////////////////////////////////////////////////////////] 100.00%

Config:
Workdir:
/opt/openlist/
Env:
PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
UMASK = 022
RUN_ARIA2 = false
Command:
/entrypoint.sh
Entrypoint:
NULL
Run with ruri:

rurima r -w -W /opt/openlist/ -e "PATH" "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -e "UMASK" "022" -e "RUN_ARIA2" "false" /data/data/com.termux/files/home/openlist /entrypoint.sh

~ $ sudo rurima r -w -W /opt/openlist/ -e "PATH" "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" -e "UMASK" "022" -e "RUN_ARIA2" "false" /data/data/com.termux/files/home/openlist /entrypoint.sh
INFO[2026-05-28 15:08:49] reading config file: /opt/openlist/data/config.json
INFO[2026-05-28 15:08:49] config file not exists, creating default config file
INFO[2026-05-28 15:08:49] load config from env with prefix:
INFO[2026-05-28 15:08:49] total memory: 15371MB, available: 4204MB
INFO[2026-05-28 15:08:49] min free memory: 1024MB
INFO[2026-05-28 15:08:49] max block limit: 64MB
INFO[2026-05-28 15:08:49] auto memory limit: 4MB
INFO[2026-05-28 15:08:49] init logrus...
Successfully created the admin user and the initial password is: LfHyicxp
start HTTP server @ 0.0.0.0:5244
```

</details>

- Sudo is required on Android phones.
- Enable `--privileged` option for ruri (`sudo rurima r --privileged [other options]`) might fix some compatibility issues, but it is not recommended for security reasons.

# What's new:
- We have a unified `pull` command to get images from dockerhub or LXC mirror now.
- Some other OCI compatible registry like ghcr.io could work with `-f/--fallback` option enabled now.
- We will automatically force enable fallback mode for ghcr.io now.
# Terms of Use:
See [TERMS_OF_USE.md](TERMS_OF_USE.md)
# Full usage doc:
For a full usage documentation,
See [USAGE.md](doc/USAGE.md).
# FAQ:
See [FAQ.md](doc/FAQ.md).
See [FAQ.md](doc/FAQ.md).
# Backward compatibility:
We promise that rurima has backward compatibility of documented parts since v0.9.x, all unstable parts will be explicitly marked as WIP or unstable, and ruri has already been backward compatible. Users can always keep `rurima ota` to get the latest build.
# Send us your feedback!
Your use case, your suggestions, anyway, we would love to hear from you!
[Discussions](https://github.com/RuriOSS/rurima/discussions/16)
And, don't forget to `rurima ota` to get the latest build!
# What's new:
- We have a unified `pull` command to get images from dockerhub or LXC mirror now.
- Some other OCI compatible registry like ghcr.io could work with `-f/--fallback` option enabled now.
- We will automatically force enable fallback mode for ghcr.io now.
# Backward compatibility:
We promise that rurima has backward compatibility of documented parts since v0.9.x, all unstable parts will be explicitly marked as WIP or unstable, and ruri has already been backward compatible. Users can always keep `rurima ota` to get the latest build.
For any issue, please notify us, and we will fix it ASAP.
# About:
So, what is rurima?
The enhanced version of ruri.
[ruri](https://github.com/Moe-hacker/ruri) only focus on running container, but rurima can also provide the function of getting rootfs image and backup/restore.
And it will be a more powerful container manager in the fulture.
With the `docker` and `lxc` subcommand of rurima, you can search & get & unpack images from dockerhub or LXC mirror easily.
# Presets:
We are working on some presets for using rurima to build your own projects, you can find them in the [presets](presets) directory.
The first preset is for running debian vm with avf on MTK devices, and we will add more presets in the future, PRs are welcome!
# Download:
You can get rurima binary (staticly linked) for arm64, armv7, armhf, riscv64, i386, loong64, s390x, ppc64le and x86_64 from the release page.
Or run the follwing command to get rurima to ./rurima and ./rurima-dbg(debug version):
Expand All @@ -84,11 +159,6 @@ For Alpine based system, run:
```
apk add wget curl jq coreutils file proot tar xz gzip
```
# About suid or caps:
Rurima does not allow to set any suid/sgid (with root) or capability on it, it will check it in main() and error() if detected these unsafe settings.
So, please always use sudo instead.
# Reporting bugs:
Please use the debug version(rurima-dbg) in release to get debug logs, and please tell me the command you run to cause the unexpected behavior you think!
# Dependent:
rurima needs tar, xz, gzip, file, you can find these static binary for aarch64, armv7, x86_64, i386 or riscv64 in:
[tar-static](https://github.com/Moe-sushi/tar-static)
Expand All @@ -112,6 +182,11 @@ So that you download:
https://mirrors.tuna.tsinghua.edu.cn/alpine/edge/testing/aarch64/proot-static-5.4.0-r1.apk
```
and finally, tar -xvf *.apk to unpack it. So you got proot.static, rename it to proot and put it in your $PATH.
# About suid or caps:
Rurima does not allow to set any suid/sgid (with root) or capability on it, it will check it in main() and error() if detected these unsafe settings.
So, please always use sudo instead.
# Reporting bugs:
Please use the debug version(rurima-dbg) in release to get debug logs, and please tell me the command you run to cause the unexpected behavior you think!
# TODO:

Manage ruri containers and configs.
Expand Down
1 change: 1 addition & 0 deletions build.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ int main(int argc, char **argv)
check_and_add_lib("-lpthread", false);
build();
remove_test_dot_c();
printf("\n\nThis program has Super Neko Powers! >w<\n");
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions doc/USAGE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Undocumented part:
The `load`, `run`, `sfx` and `netns` subcommand is WIP, it should not be used by users.
# $PATH injection:
rurima will automatically add /path/to/rurima/ to the top of $PATH.
So you can just put required binaries like `tar/curl/jq/file` under the same dir of rurima, or do some wrapper script hacking.
# Image source:
rurima currently supports both lxc-mirror and dockerhub as container image source.
# Unified image puller:
Expand Down
13 changes: 10 additions & 3 deletions src/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,15 @@ int rurima_backup_dir(char *_Nonnull file, char *_Nonnull dir)
rurima_fork_rexec(rexec_args);
if (!du_found()) {
rurima_warning("{yellow}du not found, progress will not be shown.\n");
int exstat = tar_backup__(file, dir);
return exstat;
pid_t pid = fork();
if (pid > 0) {
int status;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
} else {
int exstat = tar_backup__(file, dir);
exit(exstat);
}
}
cprintf("{base}Getting total size to backup\n");
off_t totalsize = rurima_get_dir_file_size(dir);
Expand All @@ -351,7 +358,7 @@ int rurima_backup_dir(char *_Nonnull file, char *_Nonnull dir)
usleep(100);
}
show_progress(1.0);
return status;
return WEXITSTATUS(status);
} else {
int exstat = tar_backup__(file, dir);
exit(exstat);
Expand Down
4 changes: 2 additions & 2 deletions src/include/rurima.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ struct RURIMA_DOCKER {
cfprintf(stderr, format, ##__VA_ARGS__); \
cfprintf(stderr, "{base}%s{clear}\n", " .^. .^."); \
cfprintf(stderr, "{base}%s{clear}\n", " /⋀\\_ノ_/⋀\\"); \
cfprintf(stderr, "{base}%s{clear}\n", " /ノソノ\\ノソ丶)|"); \
cfprintf(stderr, "{base}%s{clear}\n", " /ノソノ\\ノソ丶メ"); \
cfprintf(stderr, "{base}%s{clear}\n", " ルリリ > x )リ"); \
cfprintf(stderr, "{base}%s{clear}\n", "ノノ㇏ ^ ノ|ノ"); \
cfprintf(stderr, "{base}%s{clear}\n", "ノノ㇏ ^ ノノ"); \
cfprintf(stderr, "{base}%s{clear}\n", " ⠁⠁"); \
cfprintf(stderr, "{base}%s{clear}\n", "RURIMA ERROR MESSAGE"); \
cfprintf(stderr, "{base}%s{clear}\n", "Hint:"); \
Expand Down
2 changes: 1 addition & 1 deletion src/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void rurima_show_version_info(void)
cprintf("{base}%s%s\n", "Build date ......................: ", __TIMESTAMP__);
cprintf("{base}\nThere is NO WARRANTY, to the extent permitted by law\n");
cprintf("{base}Docker is a registered trademark of Docker, Inc\nThis program has no relationship with it\n");
cprintf("{base}\nThis program has Super Neko Powers!!!\n");
cprintf("{base}\nThis program has Super Neko Powers! >w<\n");
cprintf("{clear}\n");
}
// For `rurima -V`.
Expand Down
2 changes: 1 addition & 1 deletion src/ruri
Submodule ruri updated from e612c4 to b7b31e
2 changes: 1 addition & 1 deletion src/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ void end_loading_animation(void)
{
if (loading_animation_pid > 0) {
kill(loading_animation_pid, SIGINT);
loading_animation_pid = 0;
}
waitpid(loading_animation_pid, NULL, 0);
fflush(stdout);
loading_animation_pid = 0;
}
void loading_animation(char *msg)
{
Expand Down
4 changes: 2 additions & 2 deletions src/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ static void panic(int sig)
cfprintf(stderr, "{base}");
cfprintf(stderr, "{base}%s\n", " .^. .^.");
cfprintf(stderr, "{base}%s\n", " /⋀\\_ノ_/⋀\\");
cfprintf(stderr, "{base}%s\n", " /ノソノ\\ノソ丶)|");
cfprintf(stderr, "{base}%s\n", " /ノソノ\\ノソ丶メ");
cfprintf(stderr, "{base}%s\n", " ルリリ > x )リ");
cfprintf(stderr, "{base}%s\n", "ノノ㇏ ^ ノ|ノ");
cfprintf(stderr, "{base}%s\n", "ノノ㇏ ^ ノノ");
cfprintf(stderr, "{base}%s\n", " ⠁⠁");
cfprintf(stderr, "{base}%s\n", "RURIMA ERROR MESSAGE");
cfprintf(stderr, "{base}Seems that it's time to abort.\n");
Expand Down
7 changes: 4 additions & 3 deletions src/subcommand.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static void docker_pull_try_mirrors(const char *_Nonnull image, const char *_Non
rexec_argv[0] = NULL;
for (int i = 0; try_mirrorlist[i] != NULL; i++) {
cprintf("{base}Trying mirror: {cyan}%s\n", try_mirrorlist[i]);
rexec_argv[0] = NULL;
rurima_add_argv(&rexec_argv, "docker");
rurima_add_argv(&rexec_argv, "pull");
rurima_add_argv(&rexec_argv, "-i");
Expand Down Expand Up @@ -812,14 +813,14 @@ void rurima_load_rootfs(int argc, char **argv)
char manifest_path[PATH_MAX];
sprintf(manifest_path, "%s/manifest.json", tmp_dir);
FILE *manifest_file = fopen(manifest_path, "r");
if (!manifest_file) {
rurima_error("{red}Failed to open manifest.json!\n");
}
struct stat st;
if (fstat(fileno(manifest_file), &st) != 0) {
rurima_error("{red}Failed to stat manifest.json!\n");
}
char *manifest_content = malloc(st.st_size + 1);
if (!manifest_file) {
rurima_error("{red}Failed to open manifest.json!\n");
}
fread(manifest_content, 1, st.st_size, manifest_file);
manifest_content[st.st_size] = 0;
fclose(manifest_file);
Expand Down
Loading