├── .build_id ├── .editorconfig ├── .github ├── actions │ └── determine-test-jobs │ │ └── action.yml └── workflows │ ├── ci.yml │ ├── image-scripts.yml │ └── rubocop.yml ├── .gitignore ├── .overcommit.yml ├── .rubocop.yml ├── .rubocop_todo.yml ├── .ruby-version ├── .version ├── Gemfile ├── LICENSE.txt ├── Makefile ├── README.md ├── artwork ├── boot.png ├── boot.svg └── logo.svg ├── converter ├── .gitignore ├── Gemfile ├── README.md ├── Rakefile ├── bin │ └── vpsadminos-convert ├── lib │ ├── vpsadminos-converter.rb │ └── vpsadminos-converter │ │ ├── auto_start.rb │ │ ├── cg_params.rb │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ └── vz6 │ │ │ ├── base.rb │ │ │ ├── export.rb │ │ │ └── migrate.rb │ │ ├── container.rb │ │ ├── devices.rb │ │ ├── exporter.rb │ │ ├── group.rb │ │ ├── net_interface.rb │ │ ├── net_interface │ │ ├── base.rb │ │ ├── bridge.rb │ │ └── routed.rb │ │ ├── user.rb │ │ ├── version.rb │ │ ├── vz6.rb │ │ └── vz6 │ │ ├── config.rb │ │ ├── config_item.rb │ │ ├── container.rb │ │ ├── migrator.rb │ │ └── migrator │ │ ├── base.rb │ │ ├── ploop.rb │ │ ├── simfs.rb │ │ ├── state.rb │ │ └── zfs.rb ├── man │ └── man8 │ │ └── vpsadminos-convert.8.md ├── shell.nix └── vpsadminos-converter.gemspec ├── ctptywrapper ├── go.mod ├── go.sum ├── main.go └── shell.nix ├── ctstartmenu ├── generations.go ├── go.mod ├── go.sum ├── guix.go ├── main.go ├── menu.go ├── nixos.go └── shell.nix ├── docs ├── container-images │ ├── creating.md │ ├── repositories.md │ └── usage.md ├── containers │ ├── administration.md │ ├── auto-starting.md │ ├── datasets.md │ ├── declarative.md │ ├── devices.md │ ├── export-import.md │ ├── resources.md │ ├── send-receive.md │ ├── start-menu.md │ └── user-namespaces.md ├── extra.css ├── img │ ├── osctl-ct-top.png │ └── start-menu.png ├── index.md ├── migration-paths │ ├── converter.md │ └── openvz-legacy.md ├── networking │ ├── veth-bridge.md │ └── veth-routed.md ├── os │ ├── cgroups.md │ ├── configuration.md │ ├── deployment.md │ ├── installation.md │ ├── kernel-parameters.md │ ├── pools.md │ ├── runlevels.md │ ├── shell-history.md │ ├── testing.md │ └── updates.md ├── osctld │ ├── cgroups.md │ ├── development.md │ ├── distributions.md │ └── interfaces.md ├── services │ ├── docker.md │ └── snappy.md ├── specifications │ ├── container-image.md │ ├── distributions.md │ └── image-repository.md └── user-guide │ ├── containers.md │ ├── introduction.md │ ├── mounts.md │ ├── networking.md │ ├── resources.md │ └── setup.md ├── flake.nix ├── image-scripts ├── .editorconfig ├── LICENSE ├── README.md ├── bin │ ├── config │ ├── runner │ └── test ├── builders │ ├── almalinux-8 │ │ ├── config.sh │ │ └── setup.sh │ ├── almalinux-9 │ │ ├── config.sh │ │ └── setup.sh │ ├── debian-guix │ │ ├── config.sh │ │ └── setup.sh │ ├── devuan │ │ ├── config.sh │ │ └── setup.sh │ ├── fedora │ │ ├── config.sh │ │ └── setup.sh │ ├── nixos │ │ ├── config.sh │ │ └── setup.sh │ ├── opensuse-leap │ │ ├── config.sh │ │ └── setup.sh │ ├── opensuse-tumbleweed │ │ ├── config.sh │ │ └── setup.sh │ └── ubuntu │ │ ├── config.sh │ │ └── setup.sh ├── images │ ├── almalinux-10 │ │ ├── build.sh │ │ └── config.sh │ ├── almalinux-8 │ │ ├── build.sh │ │ └── config.sh │ ├── almalinux-9 │ │ ├── build.sh │ │ └── config.sh │ ├── alpine-3.20 │ ├── alpine-3.21 │ ├── alpine │ │ ├── abstract │ │ ├── build.sh │ │ ├── cgroups-mount.initd │ │ ├── config.sh │ │ └── fetch-keys.sh │ ├── arch │ │ ├── build.sh │ │ └── config.sh │ ├── centos-10-stream │ │ ├── build.sh │ │ └── config.sh │ ├── centos-9-stream │ │ ├── build.sh │ │ └── config.sh │ ├── chimera │ │ ├── build.sh │ │ └── config.sh │ ├── debian-10 │ │ ├── build.sh │ │ └── config.sh │ ├── debian-11 │ │ ├── build.sh │ │ └── config.sh │ ├── debian-12 │ │ ├── build.sh │ │ └── config.sh │ ├── debian-testing │ │ ├── build.sh │ │ └── config.sh │ ├── debian-unstable │ │ ├── build.sh │ │ └── config.sh │ ├── devuan-4 │ │ ├── build.sh │ │ ├── cgroups-mount.initscript │ │ └── config.sh │ ├── devuan-5 │ │ ├── build.sh │ │ ├── cgroups-mount.initscript │ │ └── config.sh │ ├── fedora-37 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-38 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-39 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-40 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-41 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-42 │ │ ├── build.sh │ │ └── config.sh │ ├── fedora-rawhide │ │ ├── build.sh │ │ └── config.sh │ ├── gentoo-musl │ │ ├── build.sh │ │ └── config.sh │ ├── gentoo-openrc │ │ ├── build.sh │ │ └── config.sh │ ├── gentoo-systemd │ │ ├── build.sh │ │ └── config.sh │ ├── guix │ │ ├── .dir-locals.el │ │ ├── build.sh │ │ ├── config.sh │ │ ├── sbin-init.scm │ │ ├── system.scm │ │ └── vpsadminos.scm │ ├── nixos-24.11-impermanence │ │ ├── build.sh │ │ └── config.sh │ ├── nixos-24.11 │ │ ├── build.sh │ │ └── config.sh │ ├── nixos-25.05-impermanence │ │ ├── build.sh │ │ └── config.sh │ ├── nixos-25.05 │ │ ├── build.sh │ │ └── config.sh │ ├── nixos-unstable-impermanence │ │ ├── build.sh │ │ └── config.sh │ ├── nixos-unstable │ │ ├── build.sh │ │ └── config.sh │ ├── opensuse-leap-15.5 │ │ ├── build.sh │ │ └── config.sh │ ├── opensuse-leap-15.6 │ │ ├── build.sh │ │ └── config.sh │ ├── opensuse-tumbleweed │ │ ├── build.sh │ │ └── config.sh │ ├── rocky-8 │ │ ├── build.sh │ │ └── config.sh │ ├── rocky-9 │ │ ├── build.sh │ │ └── config.sh │ ├── slackware-15.0 │ │ ├── build.sh │ │ ├── cgroups.sh │ │ └── config.sh │ ├── slackware-current │ │ ├── build.sh │ │ ├── cgroups.sh │ │ └── config.sh │ ├── ubuntu-16.04 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-18.04 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-20.04 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-22.04 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-24.04 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-24.10 │ │ ├── build.sh │ │ └── config.sh │ ├── ubuntu-25.04 │ │ ├── build.sh │ │ └── config.sh │ ├── void-glibc │ │ ├── build.sh │ │ └── config.sh │ ├── void-musl │ │ ├── build.sh │ │ └── config.sh │ └── void │ │ ├── abstract │ │ └── cgroups.sh ├── include │ ├── alpine.sh │ ├── chimera.sh │ ├── common.sh │ ├── debian.sh │ ├── devuan.sh │ ├── gentoo.sh │ ├── lib.sh │ ├── nixos.sh │ ├── opensuse.sh │ ├── redhat-family.sh │ └── void.sh ├── shell-test.nix └── tests │ ├── dns_resolver.sh │ ├── hostname.sh │ ├── packages.sh │ ├── passwd_started.sh │ ├── passwd_stopped.sh │ ├── ssh_key.sh │ ├── ssh_password.sh │ ├── start.sh │ ├── stop.sh │ ├── systemctl.sh │ ├── veth_bridge.sh │ └── veth_routed.sh ├── libosctl ├── .gitignore ├── Gemfile ├── Rakefile ├── ext │ └── libosctl │ │ ├── extconf.rb │ │ └── native.c ├── lib │ ├── libosctl.rb │ └── libosctl │ │ ├── cgroup.rb │ │ ├── cgroup │ │ └── path_reader.rb │ │ ├── cli │ │ ├── command.rb │ │ ├── completion │ │ │ └── bash.rb │ │ ├── output_formatter.rb │ │ ├── parameter_selector.rb │ │ └── presentable.rb │ │ ├── config_file.rb │ │ ├── cpu_mask.rb │ │ ├── cpu_topology.rb │ │ ├── exceptions.rb │ │ ├── exporter │ │ ├── base.rb │ │ ├── tar.rb │ │ └── zfs.rb │ │ ├── hostname.rb │ │ ├── id_map.rb │ │ ├── index.rb │ │ ├── kernel_keyring.rb │ │ ├── loadavg.rb │ │ ├── loadavg_reader.rb │ │ ├── logger.rb │ │ ├── meminfo.rb │ │ ├── mutex.rb │ │ ├── netif_stats.rb │ │ ├── os_process.rb │ │ ├── pid_finder.rb │ │ ├── process_list.rb │ │ ├── queue.rb │ │ ├── string_escape.rb │ │ ├── sys.rb │ │ ├── sys_conf.rb │ │ ├── system_command_result.rb │ │ ├── uptime.rb │ │ ├── utils │ │ ├── exception.rb │ │ ├── file.rb │ │ ├── humanize.rb │ │ ├── log.rb │ │ ├── migration.rb │ │ └── system.rb │ │ ├── version.rb │ │ └── zfs │ │ ├── dataset.rb │ │ ├── dataset_cache.rb │ │ ├── dataset_tree.rb │ │ ├── iostat.rb │ │ ├── objset_stats.rb │ │ ├── objset_stats │ │ ├── objset.rb │ │ ├── parser.rb │ │ ├── pool_tree.rb │ │ └── tree.rb │ │ ├── property_reader.rb │ │ ├── property_state.rb │ │ ├── snapshot.rb │ │ ├── stream.rb │ │ ├── zpool_status.rb │ │ └── zpool_transaction_groups.rb ├── libosctl.gemspec ├── shell.nix └── templates │ └── completion │ └── bash.erb ├── mkdocs.yml ├── os ├── Makefile ├── configs │ ├── containers │ │ ├── features.nix │ │ ├── simple.nix │ │ └── webserver.nix │ ├── devel.nix │ ├── image-repository.nix │ ├── iso.nix │ ├── local.nix.sample │ ├── partition.nix │ └── qemu.nix ├── default.nix ├── lib │ ├── make-squashfs.nix │ ├── nixos-container │ │ ├── configuration.nix │ │ ├── impermanence-24.05.nix │ │ ├── impermanence.nix │ │ ├── vpsadminos-22.11.nix │ │ ├── vpsadminos-23.05.nix │ │ ├── vpsadminos-23.11.nix │ │ ├── vpsadminos-24.05.nix │ │ ├── vpsadminos-24.11.nix │ │ └── vpsadminos.nix │ └── systemd.nix ├── livepatches │ ├── availablePatches.nix │ ├── bp-6.10.10-cumulative.patch │ ├── bp-6.11.8-cumulative.patch │ └── bp-6.8.8-2-cumulative.patch ├── manual │ ├── default.nix │ ├── man-configuration.xml │ ├── man-pages.xml │ └── manual.xml ├── modules │ ├── config │ │ ├── defaults.nix │ │ ├── kernel.nix │ │ ├── runit.nix │ │ ├── swap.nix │ │ ├── system-path.nix │ │ └── tunables.nix │ ├── installer │ │ └── cd-dvd │ │ │ ├── channel.nix │ │ │ └── iso-image.nix │ ├── misc │ │ ├── crashdump.nix │ │ ├── label.nix │ │ ├── manual.nix │ │ ├── os-lib.nix │ │ └── version.nix │ ├── module-list.nix │ ├── nixos-compat.nix │ ├── nixos-modules.nix │ ├── os-modules.nix │ ├── osctl │ │ ├── containers.nix │ │ ├── containers │ │ │ ├── image.nix │ │ │ └── nixos.nix │ │ ├── garbage-collector.nix │ │ ├── groups.nix │ │ ├── id-ranges.nix │ │ ├── osctl-exporter.nix │ │ ├── osctl-exportfs.nix │ │ ├── osctld.nix │ │ ├── pools.nix │ │ ├── repositories.nix │ │ ├── shared.nix │ │ ├── standard-devices.nix │ │ ├── test-shell.nix │ │ └── users.nix │ ├── programs │ │ ├── bash.nix │ │ └── htop.nix │ ├── rename.nix │ ├── security │ │ ├── apparmor.nix │ │ └── wrappers.nix │ ├── services │ │ ├── backup │ │ │ └── znapzend.nix │ │ ├── hardware │ │ │ ├── eudev.nix │ │ │ └── irqbalance.nix │ │ ├── livepatches │ │ │ └── default.nix │ │ ├── logging │ │ │ ├── logrotate.nix │ │ │ └── rsyslog.nix │ │ ├── mail │ │ │ └── opensmtpd.nix │ │ ├── misc │ │ │ ├── build-vpsadminos-container-image-repository │ │ │ │ ├── nixos.nix │ │ │ │ ├── options.nix │ │ │ │ ├── shared.nix │ │ │ │ └── vpsadminos.nix │ │ │ └── nix-daemon.nix │ │ ├── monitoring │ │ │ ├── apcupsd.nix │ │ │ ├── goresheat.nix │ │ │ ├── munin.nix │ │ │ └── prometheus │ │ │ │ ├── exporters.nix │ │ │ │ ├── exporters │ │ │ │ ├── ipmi.nix │ │ │ │ ├── ksvcmon.nix │ │ │ │ ├── node.nix │ │ │ │ └── osctl.nix │ │ │ │ └── osbench │ │ │ │ ├── default.nix │ │ │ │ └── runner.rb │ │ ├── network-filesystems │ │ │ └── nfs.nix │ │ ├── networking │ │ │ ├── bird.nix │ │ │ ├── chronyd.nix │ │ │ ├── firewall-iptables.nix │ │ │ ├── lxcbr-dnsmasq.nix │ │ │ ├── nftables.nix │ │ │ ├── rpcbind.nix │ │ │ └── sshd.nix │ │ ├── osctl │ │ │ └── image-repository │ │ │ │ ├── build.rb │ │ │ │ ├── default.nix │ │ │ │ └── gc.rb │ │ ├── scheduling │ │ │ └── cron.nix │ │ ├── security │ │ │ └── haveged.nix │ │ └── ttys │ │ │ └── agetty.nix │ ├── system │ │ ├── activation │ │ │ ├── secrets.nix │ │ │ ├── switch-to-configuration.rb │ │ │ └── top-level.nix │ │ └── boot │ │ │ ├── initrd-network.nix │ │ │ ├── loader │ │ │ └── grub │ │ │ │ ├── grub.nix │ │ │ │ ├── install-grub.pl │ │ │ │ ├── ipxe.nix │ │ │ │ └── memtest.nix │ │ │ ├── qemu.nix │ │ │ ├── restrict-proc-sysfs │ │ │ ├── config.txt │ │ │ ├── default.nix │ │ │ ├── restrict-dirs.nix │ │ │ └── restrict-dirs.rb │ │ │ ├── runit │ │ │ ├── default.nix │ │ │ ├── halt.8.adoc │ │ │ ├── halt.rb │ │ │ └── helpers.sh │ │ │ ├── stage-1-init.sh │ │ │ ├── stage-1.nix │ │ │ ├── stage-2-init.sh │ │ │ └── stage-2.nix │ ├── tasks │ │ ├── cpu-freq.nix │ │ ├── filesystems │ │ │ └── zfs │ │ │ │ ├── check.rb │ │ │ │ ├── create.rb │ │ │ │ ├── default.nix │ │ │ │ ├── mount.rb │ │ │ │ └── pool-service.nix │ │ └── network-interfaces.nix │ └── tools │ │ ├── get-version-suffix │ │ ├── nix-fallback-paths.nix │ │ ├── os-enter.sh │ │ ├── os-generate-config.pl │ │ ├── os-install.sh │ │ ├── os-rebuild.sh │ │ ├── os-version.sh │ │ └── tools.nix ├── overlays │ ├── default.nix │ ├── minify.nix │ ├── osctl.nix │ ├── packages.nix │ └── ruby.nix └── packages │ ├── apparmor │ ├── default.nix │ └── fix-rc.apparmor.functions.sh │ ├── bird2 │ └── disable-kif-warnings-osrtr0.patch │ ├── ctstartmenu │ └── default.nix │ ├── devcgprog │ └── default.nix │ ├── goresheat │ └── default.nix │ ├── irq_heatmap │ └── default.nix │ ├── kpatch-build │ └── default.nix │ ├── ksvcmon │ └── default.nix │ ├── linux │ ├── availableKernels.nix │ ├── common-config.nix │ ├── default.nix │ ├── generate-config.pl │ ├── generic.nix │ ├── manual-config.nix │ ├── randstruct-provide-seed-5.19.patch │ └── randstruct-provide-seed.patch │ ├── lxc │ └── default.nix │ ├── makedumpfile │ └── default.nix │ ├── os-bundler-app │ └── default.nix │ ├── osbench │ └── default.nix │ ├── osctl-env-exec │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctl-exporter │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctl-exportfs │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctl-image │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctl-repo │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctl │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osctld │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osup │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── osvm │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── ruby │ └── export-timer-functions.patch │ ├── runit │ ├── kexec-support.patch │ └── maxservices-100k.patch │ ├── scrubctl │ └── default.nix │ ├── svctl │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ └── gemset.nix │ ├── test-runner │ ├── Gemfile │ ├── Gemfile.lock │ ├── default.nix │ ├── entry.nix │ └── gemset.nix │ ├── vdevlog │ ├── default.nix │ ├── vdevlog.8.adoc │ └── vdevlog.rb │ └── zfs │ └── default.nix ├── osctl-exporter ├── .gitignore ├── Gemfile ├── Rakefile ├── config.ru ├── lib │ ├── osctl │ │ ├── exporter.rb │ │ └── exporter │ │ │ ├── collector.rb │ │ │ ├── collectors.rb │ │ │ ├── collectors │ │ │ ├── base.rb │ │ │ ├── container.rb │ │ │ ├── cpu_scheduler.rb │ │ │ ├── exportfs.rb │ │ │ ├── health_check.rb │ │ │ ├── kernel_keyring.rb │ │ │ ├── osctld.rb │ │ │ ├── pool.rb │ │ │ ├── sysctl.rb │ │ │ ├── zpool_list.rb │ │ │ ├── zpool_status.rb │ │ │ └── zpool_txgs.rb │ │ │ ├── formats │ │ │ └── json.rb │ │ │ ├── multi_registry.rb │ │ │ ├── osctld_client.rb │ │ │ ├── registry.rb │ │ │ └── version.rb │ └── prometheus_ext │ │ ├── client │ │ └── registry.rb │ │ └── middleware │ │ └── exporter.rb ├── osctl-exporter.gemspec └── shell.nix ├── osctl-exportfs ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── osctl-exportfs ├── lib │ └── osctl │ │ ├── exportfs.rb │ │ └── exportfs │ │ ├── cgroup.rb │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ ├── export.rb │ │ └── server.rb │ │ ├── config.rb │ │ ├── config │ │ ├── exports.rb │ │ ├── nfsd.rb │ │ └── top_level.rb │ │ ├── erb_template.rb │ │ ├── export.rb │ │ ├── operations │ │ ├── base.rb │ │ ├── export │ │ │ ├── add.rb │ │ │ └── remove.rb │ │ ├── exportfs │ │ │ └── generate.rb │ │ ├── runit │ │ │ └── generate.rb │ │ └── server │ │ │ ├── attach.rb │ │ │ ├── cgroup.rb │ │ │ ├── configure.rb │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ ├── exec.rb │ │ │ ├── list.rb │ │ │ ├── runsv.rb │ │ │ └── spawn.rb │ │ ├── runstate.rb │ │ ├── server.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── osctl-exportfs.8.md ├── osctl-exportfs.gemspec ├── shell.nix └── templates │ ├── runit │ ├── 1.erb │ ├── 2.erb │ └── 3.erb │ ├── runsv.erb │ └── runsvdir │ ├── nfsd.erb │ ├── rpcbind.erb │ └── statd.erb ├── osctl-image ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── osctl-image ├── lib │ └── osctl │ │ ├── image.rb │ │ └── image │ │ ├── builder.rb │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ ├── containers.rb │ │ └── image.rb │ │ ├── container_config.rb │ │ ├── exceptions.rb │ │ ├── image.rb │ │ ├── image_list.rb │ │ ├── ip_allocator.rb │ │ ├── operations │ │ ├── base.rb │ │ ├── builder │ │ │ ├── controlled_exec.rb │ │ │ ├── controlled_runscript.rb │ │ │ ├── create.rb │ │ │ ├── get_root_ugid.rb │ │ │ ├── runscript_from_string.rb │ │ │ ├── use_or_create.rb │ │ │ └── wait_for_network.rb │ │ ├── config │ │ │ ├── parse_attrs.rb │ │ │ └── parse_list.rb │ │ ├── execution │ │ │ └── parallel.rb │ │ ├── file │ │ │ └── compare.rb │ │ ├── image │ │ │ ├── build.rb │ │ │ ├── deploy.rb │ │ │ ├── export.rb │ │ │ ├── fix_file_capabilities.rb │ │ │ └── instantiate.rb │ │ ├── nix │ │ │ └── run_in_shell.rb │ │ ├── repository │ │ │ ├── add_image.rb │ │ │ ├── create.rb │ │ │ └── get_image_path.rb │ │ └── test │ │ │ ├── image.rb │ │ │ └── run.rb │ │ ├── osctld_client.rb │ │ ├── test.rb │ │ ├── test_list.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── osctl-image.8.md ├── osctl-image.gemspec └── shell.nix ├── osctl-repo ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── osctl-repo ├── lib │ └── osctl │ │ ├── repo.rb │ │ └── repo │ │ ├── base │ │ └── image.rb │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ └── repo.rb │ │ ├── constants.rb │ │ ├── downloader │ │ ├── base.rb │ │ ├── cached.rb │ │ └── direct.rb │ │ ├── exceptions.rb │ │ ├── local │ │ ├── index.rb │ │ └── repository.rb │ │ ├── locator.rb │ │ ├── remote │ │ ├── index.rb │ │ ├── repository.rb │ │ └── template.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── osctl-repo.8.md ├── osctl-repo.gemspec └── shell.nix ├── osctl ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ ├── ct │ ├── group │ ├── healthcheck │ ├── id-range │ ├── osctl │ ├── pool │ ├── repo │ └── user ├── lib │ ├── osctl.rb │ └── osctl │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── assets.rb │ │ ├── attributes.rb │ │ ├── bisect.rb │ │ ├── cgroup_params.rb │ │ ├── command.rb │ │ ├── container.rb │ │ ├── cpu_scheduler.rb │ │ ├── debug.rb │ │ ├── devices.rb │ │ ├── event.rb │ │ ├── garbage_collector.rb │ │ ├── gen_completion.rb │ │ ├── group.rb │ │ ├── history.rb │ │ ├── id_range.rb │ │ ├── kernel_keyring.rb │ │ ├── net_interface.rb │ │ ├── pid_finder.rb │ │ ├── pool.rb │ │ ├── ps │ │ │ ├── columns.rb │ │ │ ├── filter.rb │ │ │ └── main.rb │ │ ├── receive.rb │ │ ├── repository.rb │ │ ├── self.rb │ │ ├── send.rb │ │ ├── top │ │ │ ├── arcstats.rb │ │ │ ├── container.rb │ │ │ ├── host.rb │ │ │ ├── json_exporter.rb │ │ │ ├── main.rb │ │ │ ├── measurement.rb │ │ │ ├── model.rb │ │ │ ├── monitor.rb │ │ │ ├── tui.rb │ │ │ ├── tui │ │ │ │ ├── help.rb │ │ │ │ ├── key.rb │ │ │ │ ├── main.rb │ │ │ │ ├── model_thread.rb │ │ │ │ ├── process_thread.rb │ │ │ │ └── screen.rb │ │ │ └── view.rb │ │ ├── trash_bin.rb │ │ ├── tree.rb │ │ ├── user.rb │ │ └── zfs_properties.rb │ │ ├── client.rb │ │ ├── console.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── osctl.8.md ├── osctl.gemspec └── shell.nix ├── osctld ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ ├── osctld │ ├── osctld-ct-exec │ ├── osctld-ct-runner │ ├── osctld-ct-start │ └── osctld-ct-wrapper ├── configs │ └── lxc │ │ ├── alpine │ │ └── common.conf │ │ ├── arch │ │ └── common.conf │ │ ├── chimera │ │ └── common.conf │ │ ├── common.conf │ │ ├── debian │ │ └── common.conf │ │ ├── gentoo │ │ └── common.conf │ │ ├── nesting.conf │ │ ├── slackware │ │ └── common.conf │ │ └── void │ │ └── common.conf ├── ext │ └── osctld │ │ ├── extconf.rb │ │ └── native.c ├── hooks │ ├── ct-autodev │ ├── ct-on-start │ ├── ct-post-mount │ ├── ct-post-stop │ ├── ct-pre-mount │ ├── ct-pre-start │ ├── send-receive │ ├── veth-down │ └── veth-up ├── lib │ ├── osctld.rb │ └── osctld │ │ ├── apparmor.rb │ │ ├── assets.rb │ │ ├── assets │ │ ├── base.rb │ │ ├── base_file.rb │ │ ├── cgroup_device_list.rb │ │ ├── cgroup_program.rb │ │ ├── dataset.rb │ │ ├── definition.rb │ │ ├── directory.rb │ │ ├── entry.rb │ │ ├── file.rb │ │ ├── symlink.rb │ │ ├── unix_socket.rb │ │ └── validator.rb │ │ ├── attributes.rb │ │ ├── auto_start │ │ ├── config.rb │ │ ├── plan.rb │ │ ├── reboot.rb │ │ └── state.rb │ │ ├── auto_stop │ │ └── plan.rb │ │ ├── bpf_fs.rb │ │ ├── cgroup.rb │ │ ├── cgroup │ │ ├── container_params.rb │ │ ├── param.rb │ │ └── params.rb │ │ ├── cli.rb │ │ ├── cli │ │ ├── daemon.rb │ │ ├── exec.rb │ │ ├── runner.rb │ │ └── supervisor.rb │ │ ├── command.rb │ │ ├── commands │ │ ├── base.rb │ │ ├── container │ │ │ ├── assets.rb │ │ │ ├── attach.rb │ │ │ ├── boot.rb │ │ │ ├── cat.rb │ │ │ ├── cgparam_apply.rb │ │ │ ├── cgparam_list.rb │ │ │ ├── cgparam_replace.rb │ │ │ ├── cgparam_set.rb │ │ │ ├── cgparam_unset.rb │ │ │ ├── chgrp.rb │ │ │ ├── chown.rb │ │ │ ├── config_reload.rb │ │ │ ├── config_replace.rb │ │ │ ├── console.rb │ │ │ ├── copy.rb │ │ │ ├── create.rb │ │ │ ├── create_empty.rb │ │ │ ├── delete.rb │ │ │ ├── device_add.rb │ │ │ ├── device_chmod.rb │ │ │ ├── device_delete.rb │ │ │ ├── device_inherit.rb │ │ │ ├── device_list.rb │ │ │ ├── device_promote.rb │ │ │ ├── device_replace.rb │ │ │ ├── device_set_inherit.rb │ │ │ ├── device_unset_inherit.rb │ │ │ ├── exec.rb │ │ │ ├── export.rb │ │ │ ├── freeze.rb │ │ │ ├── import.rb │ │ │ ├── list.rb │ │ │ ├── map_mode.rb │ │ │ ├── mount.rb │ │ │ ├── mount_activate.rb │ │ │ ├── mount_clear.rb │ │ │ ├── mount_create.rb │ │ │ ├── mount_dataset.rb │ │ │ ├── mount_deactivate.rb │ │ │ ├── mount_delete.rb │ │ │ ├── mount_list.rb │ │ │ ├── mount_register.rb │ │ │ ├── move.rb │ │ │ ├── passwd.rb │ │ │ ├── prlimit_list.rb │ │ │ ├── prlimit_set.rb │ │ │ ├── prlimit_unset.rb │ │ │ ├── reconfigure.rb │ │ │ ├── recover_cleanup.rb │ │ │ ├── recover_state.rb │ │ │ ├── reinstall.rb │ │ │ ├── restart.rb │ │ │ ├── runscript.rb │ │ │ ├── send_cancel.rb │ │ │ ├── send_cleanup.rb │ │ │ ├── send_config.rb │ │ │ ├── send_now.rb │ │ │ ├── send_rootfs.rb │ │ │ ├── send_state.rb │ │ │ ├── send_sync.rb │ │ │ ├── set.rb │ │ │ ├── set_image_config.rb │ │ │ ├── show.rb │ │ │ ├── start.rb │ │ │ ├── stop.rb │ │ │ ├── su.rb │ │ │ ├── unfreeze.rb │ │ │ ├── unset.rb │ │ │ └── wall.rb │ │ ├── cpu_scheduler │ │ │ ├── disable.rb │ │ │ ├── enable.rb │ │ │ ├── package_disable.rb │ │ │ ├── package_enable.rb │ │ │ ├── package_list.rb │ │ │ ├── status.rb │ │ │ └── upkeep.rb │ │ ├── dataset │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ └── list.rb │ │ ├── debug │ │ │ ├── lock_registry.rb │ │ │ ├── thread_list.rb │ │ │ └── ugid_registry.rb │ │ ├── event │ │ │ └── subscribe.rb │ │ ├── garbage_collector │ │ │ └── prune.rb │ │ ├── group │ │ │ ├── assets.rb │ │ │ ├── cgparam_apply.rb │ │ │ ├── cgparam_list.rb │ │ │ ├── cgparam_replace.rb │ │ │ ├── cgparam_set.rb │ │ │ ├── cgparam_unset.rb │ │ │ ├── cgsubsystems.rb │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ ├── device_add.rb │ │ │ ├── device_chmod.rb │ │ │ ├── device_delete.rb │ │ │ ├── device_inherit.rb │ │ │ ├── device_list.rb │ │ │ ├── device_promote.rb │ │ │ ├── device_replace.rb │ │ │ ├── device_set_inherit.rb │ │ │ ├── device_unset_inherit.rb │ │ │ ├── list.rb │ │ │ ├── set.rb │ │ │ ├── show.rb │ │ │ └── unset.rb │ │ ├── history │ │ │ └── list.rb │ │ ├── id_range │ │ │ ├── allocate.rb │ │ │ ├── assets.rb │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ ├── free.rb │ │ │ ├── list.rb │ │ │ ├── set.rb │ │ │ ├── show.rb │ │ │ ├── table_list.rb │ │ │ ├── table_show.rb │ │ │ └── unset.rb │ │ ├── logged.rb │ │ ├── net_interface │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ ├── ip_add.rb │ │ │ ├── ip_del.rb │ │ │ ├── ip_list.rb │ │ │ ├── list.rb │ │ │ ├── rename.rb │ │ │ ├── route_add.rb │ │ │ ├── route_del.rb │ │ │ ├── route_list.rb │ │ │ ├── set.rb │ │ │ └── show.rb │ │ ├── pool │ │ │ ├── abort_export.rb │ │ │ ├── assets.rb │ │ │ ├── auto_start_cancel.rb │ │ │ ├── auto_start_queue.rb │ │ │ ├── auto_start_trigger.rb │ │ │ ├── export.rb │ │ │ ├── import.rb │ │ │ ├── install.rb │ │ │ ├── list.rb │ │ │ ├── set.rb │ │ │ ├── show.rb │ │ │ ├── uninstall.rb │ │ │ └── unset.rb │ │ ├── receive │ │ │ ├── authkey_add.rb │ │ │ ├── authkey_delete.rb │ │ │ └── authkey_list.rb │ │ ├── repository │ │ │ ├── add.rb │ │ │ ├── assets.rb │ │ │ ├── delete.rb │ │ │ ├── disable.rb │ │ │ ├── enable.rb │ │ │ ├── image_list.rb │ │ │ ├── image_prune.rb │ │ │ ├── list.rb │ │ │ ├── set.rb │ │ │ ├── show.rb │ │ │ └── unset.rb │ │ ├── self │ │ │ ├── abort_shutdown.rb │ │ │ ├── activate.rb │ │ │ ├── assets.rb │ │ │ ├── health_check.rb │ │ │ ├── ping.rb │ │ │ ├── shutdown.rb │ │ │ └── status.rb │ │ ├── send │ │ │ ├── key_gen.rb │ │ │ └── key_path.rb │ │ ├── trash_bin │ │ │ ├── dataset_add.rb │ │ │ └── prune.rb │ │ └── user │ │ │ ├── assets.rb │ │ │ ├── create.rb │ │ │ ├── delete.rb │ │ │ ├── idmap_list.rb │ │ │ ├── list.rb │ │ │ ├── lxc_usernet.rb │ │ │ ├── register.rb │ │ │ ├── set.rb │ │ │ ├── setup.rb │ │ │ ├── show.rb │ │ │ ├── subugids.rb │ │ │ ├── unregister.rb │ │ │ └── unset.rb │ │ ├── config.rb │ │ ├── console.rb │ │ ├── console │ │ ├── console.rb │ │ ├── container.rb │ │ └── tty.rb │ │ ├── container.rb │ │ ├── container │ │ ├── adaptor.rb │ │ ├── adaptors │ │ │ ├── base.rb │ │ │ └── cgroup.rb │ │ ├── builder.rb │ │ ├── dataset_builder.rb │ │ ├── hints.rb │ │ ├── hooks.rb │ │ ├── impermanence.rb │ │ ├── importer.rb │ │ ├── lxc_config.rb │ │ ├── raw_configs.rb │ │ ├── recovery.rb │ │ ├── run_configuration.rb │ │ ├── run_id.rb │ │ └── start_menu.rb │ │ ├── container_control │ │ ├── command.rb │ │ ├── commands │ │ │ ├── exec.rb │ │ │ ├── freeze.rb │ │ │ ├── get_hostname.rb │ │ │ ├── mount.rb │ │ │ ├── reboot.rb │ │ │ ├── runscript.rb │ │ │ ├── state.rb │ │ │ ├── stop.rb │ │ │ ├── stop_by_halt.rb │ │ │ ├── stop_runit.rb │ │ │ ├── syscmd.rb │ │ │ ├── unfreeze.rb │ │ │ ├── unmount.rb │ │ │ ├── veth_name.rb │ │ │ ├── wall.rb │ │ │ ├── with_mountns.rb │ │ │ └── with_rootfs.rb │ │ ├── frontend.rb │ │ ├── result.rb │ │ ├── runner.rb │ │ └── utils │ │ │ ├── runscript.rb │ │ │ └── wall.rb │ │ ├── continuous_executor.rb │ │ ├── cpu_scheduler.rb │ │ ├── daemon.rb │ │ ├── db │ │ ├── containers.rb │ │ ├── groups.rb │ │ ├── id_ranges.rb │ │ ├── list.rb │ │ ├── object_id.rb │ │ ├── pooled_list.rb │ │ ├── pools.rb │ │ ├── repositories.rb │ │ └── users.rb │ │ ├── devices │ │ ├── change_set.rb │ │ ├── configurator.rb │ │ ├── device.rb │ │ ├── lock.rb │ │ ├── manager.rb │ │ ├── mode.rb │ │ ├── owner.rb │ │ ├── v1 │ │ │ ├── container_configurator.rb │ │ │ ├── container_manager.rb │ │ │ ├── group_configurator.rb │ │ │ └── group_manager.rb │ │ └── v2 │ │ │ ├── bpf_link.rb │ │ │ ├── bpf_program.rb │ │ │ ├── bpf_program_cache.rb │ │ │ ├── configurator.rb │ │ │ ├── container_configurator.rb │ │ │ ├── container_manager.rb │ │ │ ├── group_configurator.rb │ │ │ └── group_manager.rb │ │ ├── dist_config.rb │ │ ├── dist_config │ │ ├── configurator.rb │ │ ├── distributions │ │ │ ├── almalinux.rb │ │ │ ├── alpine.rb │ │ │ ├── arch.rb │ │ │ ├── base.rb │ │ │ ├── centos.rb │ │ │ ├── chimera.rb │ │ │ ├── debian.rb │ │ │ ├── devuan.rb │ │ │ ├── fedora.rb │ │ │ ├── gentoo.rb │ │ │ ├── guix.rb │ │ │ ├── nixos.rb │ │ │ ├── opensuse.rb │ │ │ ├── other.rb │ │ │ ├── redhat.rb │ │ │ ├── rocky.rb │ │ │ ├── slackware.rb │ │ │ ├── ubuntu.rb │ │ │ └── void.rb │ │ ├── helpers │ │ │ ├── common.rb │ │ │ └── redhat.rb │ │ └── network │ │ │ ├── base.rb │ │ │ ├── ifupdown.rb │ │ │ ├── netctl.rb │ │ │ ├── netifrc.rb │ │ │ ├── network_manager.rb │ │ │ ├── redhat_initscripts.rb │ │ │ ├── redhat_network_manager.rb │ │ │ ├── suse_sysconfig.rb │ │ │ └── systemd_networkd.rb │ │ ├── erb_template.rb │ │ ├── erb_template_cache.rb │ │ ├── etc_hosts.rb │ │ ├── eventd.rb │ │ ├── eventd │ │ ├── event.rb │ │ ├── manager.rb │ │ └── worker.rb │ │ ├── exceptions.rb │ │ ├── execution_plan.rb │ │ ├── garbage_collector.rb │ │ ├── generic │ │ ├── client_handler.rb │ │ └── server.rb │ │ ├── group.rb │ │ ├── hint_updater.rb │ │ ├── history.rb │ │ ├── hook.rb │ │ ├── hook │ │ ├── base.rb │ │ ├── manager.rb │ │ └── script.rb │ │ ├── id_map.rb │ │ ├── id_range.rb │ │ ├── id_range │ │ └── allocation_table.rb │ │ ├── kernel_params.rb │ │ ├── lock_registry.rb │ │ ├── lockable.rb │ │ ├── lxc.rb │ │ ├── manipulable.rb │ │ ├── monitor.rb │ │ ├── monitor │ │ ├── master.rb │ │ └── process.rb │ │ ├── mount │ │ ├── entry.rb │ │ ├── manager.rb │ │ └── shared_dir.rb │ │ ├── net_config.rb │ │ ├── net_interface.rb │ │ ├── net_interface │ │ ├── base.rb │ │ ├── bridge.rb │ │ ├── manager.rb │ │ ├── routed.rb │ │ └── veth.rb │ │ ├── osctl_repo.rb │ │ ├── pool.rb │ │ ├── pool │ │ └── hooks.rb │ │ ├── prlimits.rb │ │ ├── prlimits │ │ ├── manager.rb │ │ └── prlimit.rb │ │ ├── progress_tracker.rb │ │ ├── promise.rb │ │ ├── repository.rb │ │ ├── repository │ │ └── image.rb │ │ ├── routing │ │ ├── route.rb │ │ └── table.rb │ │ ├── run_state.rb │ │ ├── run_state │ │ └── start_config.rb │ │ ├── send_receive.rb │ │ ├── send_receive │ │ ├── command.rb │ │ ├── commands │ │ │ ├── base.rb │ │ │ ├── receive_base.rb │ │ │ ├── receive_cancel.rb │ │ │ ├── receive_incremental.rb │ │ │ ├── receive_skel.rb │ │ │ └── receive_transfer.rb │ │ ├── key_chain.rb │ │ ├── log.rb │ │ ├── server.rb │ │ └── tokens.rb │ │ ├── switch_user.rb │ │ ├── system_limits.rb │ │ ├── system_users.rb │ │ ├── thread_reaper.rb │ │ ├── trash_bin.rb │ │ ├── ugid_registry.rb │ │ ├── user.rb │ │ ├── user_control.rb │ │ ├── user_control │ │ ├── command.rb │ │ ├── commands │ │ │ ├── base.rb │ │ │ ├── ct_autodev.rb │ │ │ ├── ct_on_start.rb │ │ │ ├── ct_post_mount.rb │ │ │ ├── ct_post_stop.rb │ │ │ ├── ct_pre_mount.rb │ │ │ ├── ct_pre_start.rb │ │ │ ├── ct_wrapper_start.rb │ │ │ ├── veth_down.rb │ │ │ └── veth_up.rb │ │ └── supervisor.rb │ │ ├── utils │ │ ├── assets.rb │ │ ├── cgroup_params.rb │ │ ├── container.rb │ │ ├── devices.rb │ │ ├── ip.rb │ │ ├── receive.rb │ │ └── switch_user.rb │ │ ├── utmp_reader.rb │ │ └── version.rb ├── osctld.gemspec ├── shell.nix ├── templates │ ├── apparmor │ │ ├── features │ │ │ └── nesting.erb │ │ └── profile.erb │ ├── ct │ │ ├── bashrc.erb │ │ ├── config.erb │ │ ├── lxcfs_runsv.erb │ │ └── net_interface │ │ │ ├── bridge.erb │ │ │ └── routed.erb │ └── dist_config │ │ └── network │ │ ├── guix │ │ ├── bridge.erb │ │ └── routed.erb │ │ ├── ifupdown │ │ ├── bridge.erb │ │ ├── interfaces.erb │ │ └── routed.erb │ │ ├── netctl │ │ ├── bridge.erb │ │ └── routed.erb │ │ ├── netifrc │ │ ├── bridge.erb │ │ └── routed.erb │ │ ├── network_manager │ │ ├── bridge.erb │ │ ├── nm_conf.erb │ │ ├── routed.erb │ │ └── udev_rules.erb │ │ ├── nixos │ │ ├── bridge.erb │ │ └── routed.erb │ │ ├── redhat_initscripts │ │ ├── bridge │ │ │ └── ifcfg.erb │ │ └── routed │ │ │ ├── ifcfg.erb │ │ │ ├── route_v4.erb │ │ │ └── route_v6.erb │ │ ├── redhat_network_manager │ │ ├── bridge │ │ │ └── ifcfg.erb │ │ ├── nm_conf.erb │ │ ├── routed │ │ │ ├── ifcfg.erb │ │ │ ├── route_v4.erb │ │ │ └── route_v6.erb │ │ └── udev_rules.erb │ │ ├── slackware │ │ ├── bridge.erb │ │ └── routed.erb │ │ ├── suse_sysconfig │ │ ├── bridge │ │ │ ├── ifcfg.erb │ │ │ └── ifroute.erb │ │ └── routed │ │ │ ├── ifcfg.erb │ │ │ └── ifroute.erb │ │ ├── systemd_networkd │ │ ├── bridge.erb │ │ └── routed.erb │ │ └── void │ │ ├── bridge.erb │ │ ├── hostname.erb │ │ └── routed.erb └── yard │ └── lockable.rb ├── osup ├── .gitignore ├── .rubocop.yml ├── Gemfile ├── Makefile ├── README.md ├── Rakefile ├── bin │ └── osup ├── lib │ ├── osup.rb │ └── osup │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ ├── main.rb │ │ └── runner.rb │ │ ├── exceptions.rb │ │ ├── migration.rb │ │ ├── migration_list.rb │ │ ├── migrator.rb │ │ ├── pool_migrations.rb │ │ ├── system_state.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── osup.8.md ├── migrations │ ├── .template │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20180711154030-add-netif-routes │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20180825200854-set-ct-dataset-canmount-noauto │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20190408134218-remove-user-datasets │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20190408152558-remove-user-ugid │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20190624220030-rename-migrations-to-send-receive │ │ ├── common.rb │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ ├── 20190814085557-add-dev-kmsg │ │ ├── common.rb │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb │ └── 20220406162532-fix-container-nofile-prlimit │ │ ├── down.rb │ │ ├── spec.yml │ │ └── up.rb ├── osup.gemspec └── shell.nix ├── osvm ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── osvm ├── lib │ ├── osvm.rb │ └── osvm │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ └── command.rb │ │ ├── exceptions.rb │ │ ├── machine.rb │ │ ├── machine_config.rb │ │ ├── machine_log.rb │ │ ├── shared_dir.rb │ │ └── version.rb ├── man │ └── man1 │ │ └── osvm.1.md ├── osvm.gemspec └── shell.nix ├── shell.nix ├── svctl ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── svctl ├── lib │ ├── svctl.rb │ └── svctl │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ └── command.rb │ │ ├── item_file.rb │ │ ├── service.rb │ │ └── version.rb ├── man │ └── man8 │ │ └── svctl.8.md ├── shell.nix └── svctl.gemspec ├── test-runner.sh ├── test-runner ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── test-runner ├── lib │ ├── test-runner.rb │ └── test-runner │ │ ├── cli.rb │ │ ├── cli │ │ ├── app.rb │ │ ├── command.rb │ │ ├── label_filters.rb │ │ └── tag_filters.rb │ │ ├── executor.rb │ │ ├── test.rb │ │ ├── test_config.rb │ │ ├── test_evaluator.rb │ │ ├── test_list.rb │ │ ├── test_result.rb │ │ ├── test_script.rb │ │ ├── test_script_list.rb │ │ ├── test_script_result.rb │ │ └── version.rb ├── man │ └── man1 │ │ └── test-runner.1.md ├── shell.nix └── test-runner.gemspec ├── tests ├── all-tests.nix ├── configs │ ├── base.nix │ └── pool-tank.nix ├── distributions.nix ├── list-tests.nix ├── machines │ ├── empty.nix │ ├── tank.nix │ ├── with-empty.nix │ └── with-tank.nix ├── make-template.nix ├── make-test.nix └── suite │ ├── boot.nix │ ├── cgroups │ ├── devices-v1.nix │ ├── devices-v2.nix │ ├── mount-v1.nix │ ├── mount-v2.nix │ ├── system-v1.nix │ └── system-v2.nix │ ├── ctstartmenu │ └── setup.nix │ ├── defaults.nix │ ├── dist-config │ ├── netif-routed.nix │ ├── nonsystemd-rundir.nix │ ├── start-stop.nix │ ├── systemd-rundir-limits.nix │ └── systemd-rundir.nix │ ├── docker │ ├── almalinux-10.nix │ ├── almalinux-8.nix │ ├── almalinux-9.nix │ ├── alpine-latest.nix │ ├── arch-latest.nix │ ├── base.nix │ ├── debian-latest.nix │ ├── fedora-latest.nix │ ├── ubuntu-20.04.nix │ ├── ubuntu-22.04.nix │ └── ubuntu-24.04.nix │ ├── driver.nix │ ├── image-scripts │ └── test.nix │ ├── osctl-exportfs │ └── mount.nix │ ├── osctl │ ├── ct-cat.nix │ ├── ct-exec-base.nix │ ├── ct-exec-v1.nix │ ├── ct-exec-v2.nix │ ├── ct-map-mode.nix │ ├── ct-mounts.nix │ ├── ct-runscript-base.nix │ ├── ct-runscript-v1.nix │ ├── ct-runscript-v2.nix │ └── pool │ │ └── export-cleanup.nix │ ├── podman │ ├── base.nix │ ├── debian-latest.nix │ ├── fedora-latest.nix │ └── ubuntu-latest.nix │ ├── snap │ ├── base.nix │ ├── hello-base.nix │ ├── hello-fedora.nix │ ├── hello-ubuntu.nix │ ├── lxd-base.nix │ ├── lxd-fedora.nix │ └── lxd-ubuntu.nix │ ├── systemd │ ├── credentials.nix │ └── device-units.nix │ └── zfs │ ├── ugidmap.nix │ ├── ugidmap │ ├── acl-ct.sh │ ├── acl-host.sh │ ├── cleanup.sh │ ├── defaults.sh │ ├── mappings.sh │ ├── properties.sh │ ├── run.sh │ ├── send-recv.sh │ └── setup.sh │ └── xattr.nix └── tools ├── osctl-env-exec ├── .gitignore ├── Gemfile ├── Rakefile ├── bin │ └── osctl-env-exec └── osctl-env-exec.gemspec └── update_gem.sh /.build_id: -------------------------------------------------------------------------------- 1 | 25.05.0.build20250602201001 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | 8 | [*.{rb,erb,nix,xml,c}] 9 | indent_size = 2 10 | indent_style = space 11 | trim_trailing_whitespace = true 12 | 13 | [*.go] 14 | indent_size = 4 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | attic 2 | ctptywrapper/ctptywrapper 3 | ctstartmenu/ctstartmenu 4 | Gemfile.lock 5 | z_trash 6 | result* 7 | site 8 | .*.swp 9 | os/.osvm-qemu 10 | os/configs/local.nix 11 | osctld/tmp 12 | .gems 13 | shellhook.local.sh 14 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | PreCommit: 2 | RuboCop: 3 | enabled: true 4 | CommitMsg: 5 | CapitalizedSubject: 6 | enabled: false 7 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | Layout/LineLength: 2 | Enabled: false 3 | 4 | Lint/UnusedMethodArgument: 5 | Enabled: false 6 | 7 | Style/ClassVars: 8 | Enabled: false 9 | Style/OptionalBooleanParameter: 10 | Enabled: false 11 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.0 2 | -------------------------------------------------------------------------------- /.version: -------------------------------------------------------------------------------- 1 | 25.05 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :development do 4 | gem 'geminabox' 5 | gem 'overcommit' 6 | gem 'rubocop', '~> 1.75.0' 7 | gem 'rubocop-rake' 8 | # TODO: remove when geminabox is fixed, see https://github.com/geminabox/geminabox/pull/572 9 | gem 'rubygems-generate_index' 10 | end 11 | -------------------------------------------------------------------------------- /artwork/boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpsfreecz/vpsadminos/d7e5565152bcb16439e8e6ccb7d1be0d28fa1116/artwork/boot.png -------------------------------------------------------------------------------- /converter/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /converter/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /converter/bin/vpsadminos-convert: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'vpsadminos-converter/cli' 3 | VpsAdminOS::Converter::Cli.run 4 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'require_all' 3 | 4 | module VpsAdminOS 5 | module Converter 6 | module Vz6; end 7 | end 8 | end 9 | 10 | require_rel 'vpsadminos-converter/*.rb' 11 | require_rel 'vpsadminos-converter/net_interface' 12 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/auto_start.rb: -------------------------------------------------------------------------------- 1 | module VpsAdminOS::Converter 2 | class AutoStart 3 | attr_accessor :enabled, :priority, :delay 4 | 5 | def initialize 6 | @enabled = false 7 | @priority = 10 8 | @delay = 5 9 | end 10 | 11 | def dump 12 | return nil unless enabled 13 | 14 | { 15 | 'priority' => priority, 16 | 'delay' => delay 17 | } 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/cli.rb: -------------------------------------------------------------------------------- 1 | require 'vpsadminos-converter' 2 | 3 | module VpsAdminOS::Converter 4 | module Cli 5 | module Vz6; end 6 | 7 | def self.run 8 | App.run 9 | end 10 | end 11 | end 12 | 13 | require_rel 'cli' 14 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/cli/command.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module VpsAdminOS::Converter 4 | class Cli::Command < OsCtl::Lib::Cli::Command 5 | def self.run(klass, method) 6 | proc do |global_opts, opts, args| 7 | cmd = klass.new(global_opts, opts, args) 8 | cmd.method(method).call 9 | end 10 | end 11 | 12 | def initialize(global_opts, opts, args) 13 | super 14 | 15 | if gopts['log-file'] 16 | OsCtl::Lib::Logger.setup(:io, io: File.open(gopts['log-file'], 'a')) 17 | else 18 | OsCtl::Lib::Logger.setup(:none) 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/group.rb: -------------------------------------------------------------------------------- 1 | module VpsAdminOS::Converter 2 | class Group 3 | def self.default 4 | new('default', 'default') 5 | end 6 | 7 | attr_accessor :name, :path 8 | 9 | def initialize(name, path) 10 | @name = name 11 | @path = path 12 | @cgparams = [] 13 | end 14 | 15 | def dump_config 16 | { 17 | 'path' => path, 18 | 'cgparams' => [] # TODO 19 | } 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/net_interface.rb: -------------------------------------------------------------------------------- 1 | module VpsAdminOS::Converter 2 | module NetInterface 3 | def self.register(type, klass) 4 | @types ||= {} 5 | @types[type] = klass 6 | end 7 | 8 | def self.for(type) 9 | @types[type] 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/net_interface/bridge.rb: -------------------------------------------------------------------------------- 1 | require 'vpsadminos-converter/net_interface/base' 2 | 3 | module VpsAdminOS::Converter 4 | class NetInterface::Bridge < NetInterface::Base 5 | type :bridge 6 | 7 | attr_accessor :link 8 | 9 | def dump 10 | super.merge('link' => link) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/net_interface/routed.rb: -------------------------------------------------------------------------------- 1 | require 'vpsadminos-converter/net_interface/base' 2 | 3 | module VpsAdminOS::Converter 4 | class NetInterface::Routed < NetInterface::Base 5 | type :routed 6 | 7 | attr_accessor :routes 8 | 9 | def dump 10 | super.merge( 11 | 'routes' => routes.to_h do |ip_v, addrs| 12 | ["v#{ip_v}", addrs.map(&:to_string)] 13 | end 14 | ) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/user.rb: -------------------------------------------------------------------------------- 1 | module VpsAdminOS::Converter 2 | class User 3 | def self.default 4 | map = ['0:666000:65536'] 5 | new('default', 1000, map, map) 6 | end 7 | 8 | attr_accessor :name, :ugid, :uid_map, :gid_map 9 | 10 | def initialize(name, ugid, uid_map, gid_map) 11 | @name = name 12 | @ugid = ugid 13 | @uid_map = uid_map 14 | @gid_map = gid_map 15 | end 16 | 17 | def dump_config 18 | { 19 | 'ugid' => ugid, 20 | 'uid_map' => uid_map, 21 | 'gid_map' => gid_map 22 | } 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/version.rb: -------------------------------------------------------------------------------- 1 | module VpsAdminOS 2 | module Converter 3 | VERSION = '25.05.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /converter/lib/vpsadminos-converter/vz6.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | 3 | module VpsAdminOS::Converter 4 | module Vz6; end 5 | end 6 | 7 | require_rel 'vz6' 8 | -------------------------------------------------------------------------------- /ctptywrapper/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vpsfreecz/vpsadminos/ctptywrapper 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/creack/pty v1.1.17 // indirect 7 | github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377 // indirect 8 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /ctptywrapper/go.sum: -------------------------------------------------------------------------------- 1 | github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= 2 | github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 3 | github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377 h1:gT+RM6gdTIAzMT7HUvmT5mL8SyG8Wx7iS3+L0V34Km4= 4 | github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377/go.mod h1:v6o7m/E9bfvm79dE1iFiF+3T7zLBnrjYjkWMa1J+Hv0= 5 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= 6 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 7 | -------------------------------------------------------------------------------- /ctptywrapper/shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | pkgs = import {}; 3 | stdenv = pkgs.stdenv; 4 | 5 | in stdenv.mkDerivation rec { 6 | name = "ctstartmenu"; 7 | 8 | buildInputs = with pkgs;[ 9 | git 10 | go 11 | gotools 12 | ]; 13 | } 14 | -------------------------------------------------------------------------------- /ctstartmenu/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vpsfreecz/vpsadminos/ctstartmenu 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/creack/pty v1.1.18 7 | github.com/gdamore/tcell/v2 v2.6.0 8 | github.com/rivo/tview v0.0.0-20230826224341-9754ab44dc1c 9 | golang.org/x/sys v0.11.0 10 | ) 11 | 12 | require ( 13 | github.com/gdamore/encoding v1.0.0 // indirect 14 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 15 | github.com/mattn/go-runewidth v0.0.15 // indirect 16 | github.com/rivo/uniseg v0.4.4 // indirect 17 | golang.org/x/term v0.11.0 // indirect 18 | golang.org/x/text v0.12.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /ctstartmenu/shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | pkgs = import {}; 3 | stdenv = pkgs.stdenv; 4 | 5 | in stdenv.mkDerivation rec { 6 | name = "ctstartmenu"; 7 | 8 | buildInputs = with pkgs;[ 9 | git 10 | go 11 | gotools 12 | ]; 13 | } 14 | -------------------------------------------------------------------------------- /docs/extra.css: -------------------------------------------------------------------------------- 1 | pre { 2 | overflow: auto; 3 | } 4 | 5 | pre, pre code { 6 | font-size: 90%; 7 | white-space: pre; 8 | } 9 | -------------------------------------------------------------------------------- /docs/img/osctl-ct-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpsfreecz/vpsadminos/d7e5565152bcb16439e8e6ccb7d1be0d28fa1116/docs/img/osctl-ct-top.png -------------------------------------------------------------------------------- /docs/img/start-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpsfreecz/vpsadminos/d7e5565152bcb16439e8e6ccb7d1be0d28fa1116/docs/img/start-menu.png -------------------------------------------------------------------------------- /docs/migration-paths/converter.md: -------------------------------------------------------------------------------- 1 | # vpsAdminOS Converter 2 | Migration from other virtualization/containerization technologies consists 3 | of copying the container's root filesystem and adapting configuration. 4 | To simplify and automate this process, we have created a program called 5 | *vpsAdminOS Converter*. It contains useful functions for interfacing with 6 | vpsAdminOS, which can be utilized by technology-specific converters. 7 | 8 | The following converters are currently available: 9 | 10 | - [OpenVZ Legacy Converter](openvz-legacy.md) 11 | -------------------------------------------------------------------------------- /docs/os/updates.md: -------------------------------------------------------------------------------- 1 | # Updates 2 | 3 | It is possible to update running system remotely with `os-rebuild` tool (this tool is similar to `nixos-rebuild` 4 | and accepts most of its parameters). You can build `os-rebuild` from `vpsadminos/os` directory by running: 5 | 6 | ```bash 7 | make os-rebuild 8 | ``` 9 | 10 | which builds `config.system.build.os-rebuild` target. You can then use this tool to upgrade a `QEMU` instance with: 11 | 12 | ```bash 13 | NIX_SSHOPTS="-p2222 -i~/.ssh/correctKey" ./result/os-rebuild/bin/os-rebuild switch \ 14 | --build-host localhost \ 15 | --target-host root@127.0.0.1 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/services/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 2 | [Docker] is a popular tool for running application containers. Docker is 3 | supported on vpsAdminOS and works out-of-the-box. 4 | 5 | The latest Docker version can be installed by following the manual for your 6 | distribution, e.g. 7 | . 8 | 9 | [Docker]: https://www.docker.com 10 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "vpsAdminOS flake"; 3 | 4 | outputs = { self }: { 5 | nixosConfigurations.container = import ./os/lib/nixos-container/vpsadminos.nix; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /image-scripts/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | 8 | [*.sh] 9 | indent_size = 4 10 | indent_style = tab 11 | trim_trailing_whitespace = true 12 | 13 | [bin/*] 14 | indent_size = 4 15 | indent_style = tab 16 | trim_trailing_whitespace = true 17 | -------------------------------------------------------------------------------- /image-scripts/builders/almalinux-8/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=almalinux 2 | RELVER=8 3 | -------------------------------------------------------------------------------- /image-scripts/builders/almalinux-8/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | dnf -y update 3 | dnf -y install curl openssl patch wget 4 | -------------------------------------------------------------------------------- /image-scripts/builders/almalinux-9/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=almalinux 2 | RELVER=9 3 | -------------------------------------------------------------------------------- /image-scripts/builders/almalinux-9/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | dnf -y update 3 | dnf -y install curl openssl patch wget 4 | -------------------------------------------------------------------------------- /image-scripts/builders/debian-guix/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=debian 2 | RELVER=stable 3 | -------------------------------------------------------------------------------- /image-scripts/builders/debian-guix/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | apt-get update 3 | apt-get -y install guix 4 | . /etc/profile.d/guix.sh || true 5 | 6 | guix pull 7 | -------------------------------------------------------------------------------- /image-scripts/builders/devuan/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=devuan 2 | RELVER=5 3 | -------------------------------------------------------------------------------- /image-scripts/builders/devuan/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | apt-get update 3 | apt-get -y install curl debootstrap 4 | -------------------------------------------------------------------------------- /image-scripts/builders/fedora/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=fedora 2 | RELVER=41 3 | -------------------------------------------------------------------------------- /image-scripts/builders/fedora/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | dnf -y update 3 | dnf -y install curl debootstrap git minisign openssl patch wget zstd 4 | -------------------------------------------------------------------------------- /image-scripts/builders/nixos/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=nixos 2 | RELVER=unstable 3 | -------------------------------------------------------------------------------- /image-scripts/builders/nixos/setup.sh: -------------------------------------------------------------------------------- 1 | cat < /etc/nixos/configuration.nix 2 | { config, pkgs, ... }: 3 | { 4 | imports = [ 5 | 6 | ./vpsadminos.nix 7 | ]; 8 | 9 | environment.systemPackages = with pkgs; [ 10 | git 11 | gnumake 12 | ]; 13 | 14 | time.timeZone = "Europe/Amsterdam"; 15 | system.stateVersion = "21.05"; 16 | } 17 | EOF 18 | 19 | # Set NIX_PATH and other stuff 20 | . /etc/profile 21 | 22 | # Configure the system 23 | nixos-rebuild switch 24 | -------------------------------------------------------------------------------- /image-scripts/builders/opensuse-leap/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=opensuse 2 | RELVER=leap-15.5 3 | -------------------------------------------------------------------------------- /image-scripts/builders/opensuse-leap/setup.sh: -------------------------------------------------------------------------------- 1 | : 2 | -------------------------------------------------------------------------------- /image-scripts/builders/opensuse-tumbleweed/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=opensuse 2 | RELVER=latest-tumbleweed 3 | -------------------------------------------------------------------------------- /image-scripts/builders/opensuse-tumbleweed/setup.sh: -------------------------------------------------------------------------------- 1 | : 2 | -------------------------------------------------------------------------------- /image-scripts/builders/ubuntu/config.sh: -------------------------------------------------------------------------------- 1 | DISTNAME=ubuntu 2 | RELVER=24.04 3 | -------------------------------------------------------------------------------- /image-scripts/builders/ubuntu/setup.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | apt-get -y update 3 | apt-get -y install curl debootstrap patch wget 4 | -------------------------------------------------------------------------------- /image-scripts/images/almalinux-10/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=almalinux-9 2 | -------------------------------------------------------------------------------- /image-scripts/images/almalinux-8/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=almalinux-8 2 | -------------------------------------------------------------------------------- /image-scripts/images/almalinux-9/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=almalinux-9 2 | -------------------------------------------------------------------------------- /image-scripts/images/alpine-3.20: -------------------------------------------------------------------------------- 1 | alpine -------------------------------------------------------------------------------- /image-scripts/images/alpine-3.21: -------------------------------------------------------------------------------- 1 | alpine -------------------------------------------------------------------------------- /image-scripts/images/alpine/abstract: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpsfreecz/vpsadminos/d7e5565152bcb16439e8e6ccb7d1be0d28fa1116/image-scripts/images/alpine/abstract -------------------------------------------------------------------------------- /image-scripts/images/alpine/build.sh: -------------------------------------------------------------------------------- 1 | . "$IMAGEDIR"/config.sh 2 | . "$INCLUDE"/alpine.sh 3 | -------------------------------------------------------------------------------- /image-scripts/images/alpine/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | -------------------------------------------------------------------------------- /image-scripts/images/alpine/fetch-keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Used to update keys in $APK_KEYS_SHA256 3 | git clone --depth 1 git://git.alpinelinux.org/aports 4 | pushd aports/main/alpine-keys 5 | for key in $(ls *.pub) ; do 6 | echo -e "\t$(sha256sum $key)" 7 | done 8 | popd 9 | -------------------------------------------------------------------------------- /image-scripts/images/arch/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | RELVER=$(date +%Y%m%d) 3 | -------------------------------------------------------------------------------- /image-scripts/images/centos-10-stream/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=almalinux-9 2 | RELVER=10-stream-$(date +%Y%m%d) 3 | ARCH=x86_64 4 | -------------------------------------------------------------------------------- /image-scripts/images/centos-9-stream/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=almalinux-9 2 | RELVER=9-stream-$(date +%Y%m%d) 3 | ARCH=x86_64 4 | -------------------------------------------------------------------------------- /image-scripts/images/chimera/build.sh: -------------------------------------------------------------------------------- 1 | . "$IMAGEDIR/config.sh" 2 | . "$INCLUDE/chimera.sh" 3 | generate-chimera 4 | -------------------------------------------------------------------------------- /image-scripts/images/chimera/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | RELVER=$(date +%Y%m%d) 3 | -------------------------------------------------------------------------------- /image-scripts/images/debian-10/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | -------------------------------------------------------------------------------- /image-scripts/images/debian-11/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | -------------------------------------------------------------------------------- /image-scripts/images/debian-12/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | -------------------------------------------------------------------------------- /image-scripts/images/debian-testing/config.sh: -------------------------------------------------------------------------------- 1 | BUILDER=fedora 2 | RELVER=testing-$(date +%Y%m%d) 3 | -------------------------------------------------------------------------------- /image-scripts/images/debian-unstable/build.sh: -------------------------------------------------------------------------------- 1 | . "$IMAGEDIR/config.sh" 2 | RELNAME=unstable 3 | BASEURL=http://ftp.cz.debian.org/debian 4 | 5 | . "$INCLUDE/debian.sh" 6 | 7 | bootstrap 8 | 9 | configure-common 10 | configure-debian 11 | 12 | cat > "$INSTALL/etc/apt/sources.list" <> /etc/inittab <> /etc/inittab < {}; 4 | stdenv = pkgs.stdenv; 5 | 6 | in stdenv.mkDerivation rec { 7 | name = "vpsadminos-image-build-scripts"; 8 | 9 | buildInputs = with pkgs; [ 10 | netcat 11 | sshpass 12 | ]; 13 | 14 | # shellHook needs to be unset in case osctl-image is run from its own 15 | # nix-shell. osctl-image sets up ruby and bundler in its shellHook, it is 16 | # inherited by nested nix-shells and breaks them. 17 | shellHook = ""; 18 | } 19 | -------------------------------------------------------------------------------- /image-scripts/tests/passwd_started.sh: -------------------------------------------------------------------------------- 1 | osctl ct start $CTID || fail "unable to start container" 2 | 3 | # On NixOS, we have to wait a bit for the start menu to pass, because 4 | # we need the initial system activation to take place before the password 5 | # can be set. 6 | [ "$DISTNAME" == "nixos" ] && sleep 10 7 | [ "$DISTNAME" == "guix" ] && sleep 10 8 | 9 | osctl ct passwd $CTID root suCHS3crET || fail "unable to set password" 10 | -------------------------------------------------------------------------------- /image-scripts/tests/start.sh: -------------------------------------------------------------------------------- 1 | osctl ct start $CTID || fail "unable to start" 2 | -------------------------------------------------------------------------------- /image-scripts/tests/stop.sh: -------------------------------------------------------------------------------- 1 | osctl ct start $CTID || fail "unable to start container" 2 | 3 | # shepherd in guix is not reliable, it sometimes hangs on graceful shutdown 4 | if [ "$DISTNAME" == "guix" ] ; then 5 | exit 0 6 | fi 7 | 8 | # Give the system some time to complete boot 9 | if [ "$DISTNAME" == "debian" ] && [ "$RELVER" == "8" ] ; then 10 | sleep 30 11 | else 12 | sleep 10 13 | fi 14 | 15 | osctl ct stop --dont-kill $CTID || fail "unable to stop container" 16 | -------------------------------------------------------------------------------- /image-scripts/tests/systemctl.sh: -------------------------------------------------------------------------------- 1 | osctl ct start $CTID || fail "unable to start container" 2 | sleep 10 3 | 4 | if ! osctl ct exec $CTID type systemctl ; then 5 | echo "systemctl not found, ignoring" 6 | exit 0 7 | fi 8 | 9 | osctl ct exec $CTID systemctl is-system-running --wait && exit 0 10 | 11 | echo "system is not running, systemctl --failed:" 12 | osctl ct exec $CTID systemctl --failed 13 | exit 1 -------------------------------------------------------------------------------- /image-scripts/tests/veth_bridge.sh: -------------------------------------------------------------------------------- 1 | function test_network { 2 | # We assume that the bridge is setup in OS configuration using 3 | # 4 | # networking.lxcbr.enable = true; 5 | # 6 | local ip=$(osctl ct exec $CTID ip route get 192.168.1.1 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}') 7 | local rc=$? 8 | [ $rc != 0 ] && return $rc 9 | 10 | ping -c 1 $ip > /dev/null 2>&1 11 | } 12 | 13 | osctl ct netif new bridge --link lxcbr0 $CTID eth0 || fail "unable to add netif" 14 | osctl ct start $CTID || fail "unable to start container" 15 | 16 | for i in {1..60} ; do 17 | test_network && exit 0 18 | sleep 1 19 | done 20 | 21 | exit 1 22 | -------------------------------------------------------------------------------- /image-scripts/tests/veth_routed.sh: -------------------------------------------------------------------------------- 1 | IPADDR="$OSCTL_IMAGE_TEST_IPV4_ADDRESS" 2 | function test_network { 3 | ping -c 1 $IPADDR > /dev/null 2>&1 4 | } 5 | 6 | osctl ct netif new routed $CTID eth0 || fail "unable to add netif" 7 | osctl ct netif ip add $CTID eth0 $IPADDR/32 || fail "unable to add ip" 8 | osctl ct start $CTID || fail "unable to start" 9 | 10 | for i in {1..60} ; do 11 | test_network && exit 0 12 | sleep 1 13 | done 14 | 15 | exit 1 16 | -------------------------------------------------------------------------------- /libosctl/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | html_doc 4 | .yardoc 5 | ext/**/*.o 6 | ext/**/*.so 7 | ext/**/Makefile 8 | **/*.so 9 | -------------------------------------------------------------------------------- /libosctl/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | group :development do 5 | gem 'rake' 6 | gem 'rake-compiler' 7 | gem 'yard' 8 | end 9 | -------------------------------------------------------------------------------- /libosctl/Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rake/extensiontask' 3 | require 'yard' 4 | 5 | gemspec = Gem::Specification.load('libosctl.gemspec') 6 | 7 | Rake::ExtensionTask.new do |ext| 8 | ext.name = 'native' 9 | ext.source_pattern = '*.{c,h}' 10 | ext.ext_dir = 'ext/libosctl' 11 | ext.lib_dir = 'lib/libosctl' 12 | ext.gem_spec = gemspec 13 | end 14 | 15 | YARD::Rake::YardocTask.new do |t| 16 | t.files = ['lib/**/*.rb'] 17 | t.options = [ 18 | '--protected', 19 | "--output-dir=#{ENV['YARD_OUTPUT'] || 'html_doc'}" 20 | ] 21 | end 22 | -------------------------------------------------------------------------------- /libosctl/ext/libosctl/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | extension_name = 'libosctl/native' 4 | dir_config(extension_name) 5 | create_makefile(extension_name) 6 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | 3 | module OsCtl 4 | module Lib 5 | module Cli 6 | module Completion; end 7 | end 8 | 9 | module Exporter; end 10 | module Utils; end 11 | module Zfs; end 12 | end 13 | end 14 | 15 | require_rel 'libosctl/utils' 16 | require_rel 'libosctl' 17 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/cgroup.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | module CGroup 3 | FS = '/sys/fs/cgroup'.freeze 4 | 5 | # @return [1, 2] cgroup hierarchy version 6 | def self.version 7 | return @version if @version 8 | 9 | @version = if File.exist?(File.join(FS, 'cgroup.procs')) 10 | 2 11 | else 12 | 1 13 | end 14 | 15 | @version 16 | end 17 | 18 | def self.v1? 19 | version == 1 20 | end 21 | 22 | def self.v2? 23 | version == 2 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/config_file.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | 3 | module OsCtl::Lib 4 | module ConfigFile 5 | # Safely load YAML file 6 | # @param filename [String] 7 | def self.load_yaml_file(filename) 8 | File.open(filename, 'r:bom|utf-8') do |f| 9 | YAML.safe_load(f, filename:) 10 | end 11 | end 12 | 13 | # Safely load YAML from string 14 | # @param string [String] 15 | def self.load_yaml(string) 16 | YAML.safe_load(string) 17 | end 18 | 19 | # Create YAML from data 20 | # @return [String] 21 | def self.dump_yaml(data) 22 | YAML.dump(data) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/hostname.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | class Hostname 3 | attr_reader :local, :domain, :fqdn 4 | 5 | # @param fqdn [String] 6 | def initialize(fqdn) 7 | names = fqdn.split('.') 8 | @local = names.first 9 | @domain = names[1..].join('.') 10 | @fqdn = fqdn 11 | end 12 | 13 | alias to_s fqdn 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/pid_finder.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | # Locate containers by process IDs from the host 3 | class PidFinder 4 | Result = Struct.new(:pool, :ctid, :os_process) 5 | 6 | # @param pid [Integer] process ID from the host 7 | # @return [Result, nil] 8 | def find(pid) 9 | os_proc = OsProcess.new(pid) 10 | ctid = os_proc.ct_id 11 | 12 | if ctid.nil? 13 | Result.new(nil, :host, os_proc) 14 | else 15 | pool, id = ctid 16 | Result.new(pool, id, os_proc) 17 | end 18 | rescue Exceptions::OsProcessNotFound 19 | nil 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/utils/exception.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | module Utils::Exception 3 | # Return a new backtrace with removed `/nix/store/...` prefixes 4 | # @param backtrace [Array] 5 | # @return [Array] 6 | def denixstorify(backtrace) 7 | backtrace.map do |line| 8 | line.sub( 9 | %r{^/nix/store/[^/]+/lib/ruby/gems/\d+\.\d+\.\d+/gems/}, 10 | '' 11 | ) 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/utils/migration.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | module Utils::Send 3 | def send_ssh_cmd(key_chain, m_opts, cmd) 4 | ret = [ 5 | 'ssh', 6 | '-o', 'StrictHostKeyChecking=no', 7 | '-T', 8 | '-p', m_opts[:port].to_s 9 | ] 10 | 11 | ret.push('-i', key_chain.private_key_path) if key_chain 12 | 13 | ret.push( 14 | '-l', 'osctl-ct-receive', 15 | m_opts[:dst], 16 | *cmd 17 | ) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Lib 3 | VERSION = '25.05.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/zfs/dataset_cache.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | class Zfs::DatasetCache 3 | # @param datasets [Array] 4 | def initialize(datasets) 5 | @index = {} 6 | rebuild_index(datasets) 7 | end 8 | 9 | # @param name [String] 10 | # @return [Zfs::Dataset, nil] 11 | def [](name) 12 | @index[name] 13 | end 14 | 15 | protected 16 | 17 | def rebuild_index(datasets) 18 | @index.clear 19 | datasets.each { |ds| @index[ds.name] = ds } 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /libosctl/lib/libosctl/zfs/objset_stats.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Lib 2 | module Zfs::ObjsetStats 3 | def self.read_pools(pools) 4 | tree = Zfs::ObjsetStats::Tree.new 5 | pools.each { |pool| tree << read_pool(pool) } 6 | tree 7 | end 8 | 9 | def self.read_pool(pool) 10 | parser = Zfs::ObjsetStats::Parser.new 11 | parser.read(pool) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /os/configs/devel.nix: -------------------------------------------------------------------------------- 1 | { config, ... }: 2 | { 3 | boot.qemu.sharedFileSystems = [ 4 | { handle = "hostNixPath"; hostPath = "../.."; guestPath = "/mnt/nix-path"; } 5 | { handle = "hostOs"; hostPath = ".."; guestPath = "/mnt/vpsadminos"; } 6 | ]; 7 | 8 | nix.nixPath = [ 9 | "nixpkgs=/mnt/nix-path/nixpkgs" 10 | "nixpkgs-overlays=/mnt/vpsadminos/os/overlays" 11 | "vpsadminos=/mnt/vpsadminos" 12 | ]; 13 | } 14 | -------------------------------------------------------------------------------- /os/lib/systemd.nix: -------------------------------------------------------------------------------- 1 | { lib }: 2 | { 3 | # Extract command from systemd's ExecStart, i.e. remove known prefixes 4 | extractExecCommand = cmd: 5 | let 6 | prefixes = [ "@" "-" ":" "+" "!!" "!" ]; 7 | prefix = lib.findFirst (s: lib.hasPrefix s cmd) null prefixes; 8 | withoutPrefix = if prefix == null then cmd else (lib.removePrefix prefix cmd); 9 | in withoutPrefix; 10 | } 11 | -------------------------------------------------------------------------------- /os/manual/man-pages.xml: -------------------------------------------------------------------------------- 1 | 4 | vpsAdminOS Reference Pages 5 | 6 | vpsAdminOS contributors 7 | 2017–2019vpsAdminOS contributors 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /os/modules/misc/os-lib.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | { 3 | _module.args = { 4 | oslib = { 5 | systemd = import ../../lib/systemd.nix { inherit lib; }; 6 | }; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /os/modules/module-list.nix: -------------------------------------------------------------------------------- 1 | (import ./nixos-modules.nix) 2 | ++ 3 | (import ./os-modules.nix) 4 | -------------------------------------------------------------------------------- /os/modules/rename.nix: -------------------------------------------------------------------------------- 1 | # Lightweight version of 2 | { lib, pkgs, ... }: 3 | 4 | with lib; 5 | 6 | { 7 | imports = []; 8 | } 9 | -------------------------------------------------------------------------------- /os/modules/security/wrappers.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | { 3 | config = { 4 | system.activationScripts.wrappers = 5 | lib.stringAfter [ "specialfs" "users" ] config.systemd.services.suid-sgid-wrappers.script; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /os/modules/services/hardware/irqbalance.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | let 3 | inherit (lib) mkEnableOption mkIf; 4 | 5 | cfg = config.services.irqbalance; 6 | in 7 | { 8 | options = { 9 | services.irqbalance.enable = mkEnableOption "irqbalance daemon"; 10 | }; 11 | 12 | config = mkIf cfg.enable { 13 | environment.systemPackages = [ pkgs.irqbalance ]; 14 | 15 | runit.services.irqbalance = { 16 | run = '' 17 | mkdir -p /run/irqbalance 18 | exec ${pkgs.irqbalance}/bin/irqbalance -f 19 | ''; 20 | 21 | log.enable = true; 22 | log.sendTo = "127.0.0.1"; 23 | }; 24 | }; 25 | } -------------------------------------------------------------------------------- /os/modules/services/misc/build-vpsadminos-container-image-repository/vpsadminos.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | with lib; 3 | let 4 | cfg = config.services.build-vpsadminos-container-image-repository; 5 | 6 | shared = import ./shared.nix { inherit config pkgs lib; }; 7 | in { 8 | imports = [ 9 | ./options.nix 10 | ]; 11 | 12 | config = { 13 | environment.systemPackages = shared.createSystemPackages cfg; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/modules/services/monitoring/prometheus/exporters/ksvcmon.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, options }: 2 | 3 | with lib; 4 | 5 | let 6 | cfg = config.services.prometheus.exporters.ksvcmon; 7 | in { 8 | port = 9299; 9 | 10 | serviceRun = with cfg; concatStringsSep " " ([ 11 | "execExporter" 12 | "${pkgs.ksvcmon}/bin/ksvcmon" 13 | "-h ${listenAddress} -p ${toString port}" 14 | ] ++ extraFlags); 15 | } 16 | -------------------------------------------------------------------------------- /os/modules/system/boot/restrict-proc-sysfs/restrict-dirs.nix: -------------------------------------------------------------------------------- 1 | { ruby, replaceVarsWith, writeText }: 2 | replaceVarsWith { 3 | src = ./restrict-dirs.rb; 4 | isExecutable = true; 5 | replacements = { 6 | inherit ruby; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /os/modules/tools/nix-fallback-paths.nix: -------------------------------------------------------------------------------- 1 | { 2 | x86_64-linux = "/nix/store/0d60i73mcv8z1m8d2m74yfn84980gfsa-nix-2.0.4"; 3 | i686-linux = "/nix/store/6ssafj2s5a2g9x28yld7b70vwd6vw6lb-nix-2.0.4"; 4 | aarch64-linux = "/nix/store/3wwch7bp7n7xsl8apgy2a4b16yzyij1z-nix-2.0.4"; 5 | x86_64-darwin = "/nix/store/771l8i0mz4c8kry8cz3sz8rr3alalckg-nix-2.0.4"; 6 | } 7 | -------------------------------------------------------------------------------- /os/modules/tools/os-version.sh: -------------------------------------------------------------------------------- 1 | #! @shell@ 2 | 3 | case "$1" in 4 | -h|--help) 5 | exec man os-version 6 | exit 1 7 | ;; 8 | --hash|--revision) 9 | echo "@revision@" 10 | ;; 11 | *) 12 | echo "@version@ (@codeName@)" 13 | ;; 14 | esac 15 | -------------------------------------------------------------------------------- /os/overlays/default.nix: -------------------------------------------------------------------------------- 1 | [ 2 | (import ./minify.nix) 3 | (import ./osctl.nix) 4 | (import ./packages.nix) 5 | (import ./ruby.nix) 6 | ] 7 | -------------------------------------------------------------------------------- /os/overlays/minify.nix: -------------------------------------------------------------------------------- 1 | self: super: 2 | { 3 | lxc = super.lxc.override { systemd = null; }; 4 | gnupg = super.gnupg.override { guiSupport = false; pinentry = null; openldap = null; }; 5 | util-linux = super.util-linux.override { systemdSupport = false; systemd = null; }; 6 | dhcpcd = super.dhcpcd.override { udev = null; }; 7 | } 8 | -------------------------------------------------------------------------------- /os/packages/bird2/disable-kif-warnings-osrtr0.patch: -------------------------------------------------------------------------------- 1 | diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c 2 | index a232421..c29bb73 100644 3 | --- a/sysdep/linux/netlink.c 4 | +++ b/sysdep/linux/netlink.c 5 | @@ -809,6 +809,7 @@ nl_parse_addr(struct nlmsghdr *h, int scan) 6 | scope = ipa_classify(ifa.ip); 7 | if (scope < 0) 8 | { 9 | + if (strncmp(ifi->name, "osrtr0", sizeof(ifi->name)-1) == 0) {} else 10 | log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name); 11 | return; 12 | } 13 | -------------------------------------------------------------------------------- /os/packages/ctstartmenu/default.nix: -------------------------------------------------------------------------------- 1 | { lib, buildGoModule }: 2 | 3 | buildGoModule { 4 | pname = "ctstartmenu"; 5 | version = builtins.replaceStrings [ "\n" ] [ "" ] (builtins.readFile ../../../.version); 6 | 7 | src = ../../../ctstartmenu; 8 | 9 | vendorHash = "sha256-e4w0YHxa/ImM3DseWCugbuytn5TNY8MIO69Dl7B0vpc="; 10 | 11 | meta = with lib; { 12 | description = "Start menu for containers"; 13 | homepage = https://github.com/vpsfreecz/vpsadminos; 14 | license = licenses.mit; 15 | maintainers = []; 16 | platforms = platforms.unix; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /os/packages/irq_heatmap/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, getopt, fetchFromGitHub, ... }: 2 | pkgs.stdenv.mkDerivation rec { 3 | name = "irq_heatmap"; 4 | version = "1.3"; 5 | src = fetchFromGitHub { 6 | owner = "snajpa"; 7 | repo = "irq_heatmap"; 8 | rev = "044a6a97dc2d8b0d16211105b8e208136257f900"; 9 | sha256 = "sha256-2a2rmW9k5Ha+cEDXCHtU1QSAqL0w4EyVZbEUhXWyh2o="; 10 | }; 11 | buildInputs = with pkgs; [ 12 | gnumake numactl 13 | ]; 14 | buildPhase = '' 15 | make -j$NIX_BUILD_CORES 16 | ''; 17 | installPhase = '' 18 | mkdir -p $out/bin 19 | cp ${name} $out/bin/${name} 20 | ''; 21 | } 22 | -------------------------------------------------------------------------------- /os/packages/ksvcmon/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, getopt, fetchFromGitHub, ... }: 2 | pkgs.stdenv.mkDerivation rec { 3 | name = "ksvcmon"; 4 | src = fetchFromGitHub { 5 | owner = "snajpa"; 6 | repo = "ksvcmon"; 7 | rev = "3c6cc3077dca58f74162bf8148c5988d3c0c14f3"; 8 | sha256 = "sha256-HQRmXJ+JF8Ga1eMSlJpUgAuaZS3Gw3nwJPd7nev/8vk="; 9 | }; 10 | postPatch = '' 11 | ''; 12 | buildInputs = with pkgs; [ 13 | libmicrohttpd 14 | ]; 15 | buildPhase = '' 16 | make -j$NIX_BUILD_CORES 17 | ''; 18 | installPhase = '' 19 | mkdir -p $out/bin 20 | install -m 755 -t $out/bin ksvcmon 21 | ''; 22 | } 23 | -------------------------------------------------------------------------------- /os/packages/linux/randstruct-provide-seed-5.19.patch: -------------------------------------------------------------------------------- 1 | diff --git a/scripts/gen-randstruct-seed.sh b/scripts/gen-randstruct-seed.sh 2 | index 61017b36c464..7bb494dd2e18 100755 3 | --- a/scripts/gen-randstruct-seed.sh 4 | +++ b/scripts/gen-randstruct-seed.sh 5 | @@ -1,7 +1,7 @@ 6 | #!/bin/sh 7 | # SPDX-License-Identifier: GPL-2.0 8 | 9 | -SEED=$(od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n') 10 | +SEED="NIXOS_RANDSTRUCT_SEED" 11 | echo "$SEED" > "$1" 12 | HASH=$(echo -n "$SEED" | sha256sum | cut -d" " -f1) 13 | echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2" 14 | -------------------------------------------------------------------------------- /os/packages/osctl-env-exec/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osctl-env-exec', '24.11.0.build20250116134239' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osctl-env-exec/default.nix: -------------------------------------------------------------------------------- 1 | { lib, bundlerApp, defaultGemConfig }: 2 | 3 | bundlerApp { 4 | pname = "osctl-env-exec"; 5 | gemdir = ./.; 6 | exes = [ "osctl-env-exec" ]; 7 | gemConfig = lib.mergeAttrs defaultGemConfig { 8 | binman = attrs: { 9 | dontInstallManpages = true; 10 | }; 11 | }; 12 | 13 | meta = with lib; { 14 | description = ""; 15 | homepage = https://github.com/vpsfreecz/vpsadminos; 16 | license = licenses.mit; 17 | maintainers = []; 18 | platforms = platforms.unix; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /os/packages/osctl-exporter/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osctl-exporter', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osctl-exportfs/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osctl-exportfs', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osctl-image/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osctl-image', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osctl-image/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, bundlerApp }: 2 | 3 | bundlerApp { 4 | pname = "osctl-image"; 5 | gemdir = ./.; 6 | exes = [ "osctl-image" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/osctl-repo/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osctl-repo', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osctl-repo/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, bundlerApp }: 2 | 3 | bundlerApp { 4 | pname = "osctl-repo"; 5 | gemdir = ./.; 6 | exes = [ "osctl-repo" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/osctl/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'libosctl' 5 | gem 'osctl', '25.05.0.build20250602201001' 6 | end 7 | -------------------------------------------------------------------------------- /os/packages/osctl/default.nix: -------------------------------------------------------------------------------- 1 | { lib, osBundlerApp }: 2 | 3 | osBundlerApp { 4 | pname = "osctl"; 5 | gemdir = ./.; 6 | exes = [ "osctl" "ct" "group" "healthcheck" "id-range" "pool" "repo" "user" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/osctld/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'libosctl' 5 | gem 'netlinkrb' 6 | gem 'osctld', '25.05.0.build20250602201001' 7 | gem 'osctl-repo' 8 | gem 'osup' 9 | gem 'ruby-lxc' 10 | end 11 | -------------------------------------------------------------------------------- /os/packages/osctld/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, bundlerApp }: 2 | 3 | bundlerApp { 4 | pname = "osctld"; 5 | gemdir = ./.; 6 | exes = [ "osctld" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/osup/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osup', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osup/default.nix: -------------------------------------------------------------------------------- 1 | { lib, osBundlerApp }: 2 | 3 | osBundlerApp { 4 | pname = "osup"; 5 | gemdir = ./.; 6 | exes = [ "osup" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/osvm/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'osvm', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/osvm/default.nix: -------------------------------------------------------------------------------- 1 | { lib, bundlerApp }: 2 | 3 | bundlerApp { 4 | pname = "osvm"; 5 | gemdir = ./.; 6 | exes = [ "osvm" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/runit/maxservices-100k.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/runsvdir.c b/src/runsvdir.c 2 | index 28e66d5..308017a 100644 3 | --- a/src/runsvdir.c 4 | +++ b/src/runsvdir.c 5 | @@ -19,7 +19,7 @@ 6 | #define USAGE " [-P] dir" 7 | #define VERSION "$Id: 28cb04495cffccf27650de3cf2981942679781cd $" 8 | 9 | -#define MAXSERVICES 1000 10 | +#define MAXSERVICES 100000 11 | 12 | char *progname; 13 | char *svdir; -------------------------------------------------------------------------------- /os/packages/svctl/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'svctl', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/svctl/default.nix: -------------------------------------------------------------------------------- 1 | { lib, osBundlerApp }: 2 | 3 | osBundlerApp { 4 | pname = "svctl"; 5 | gemdir = ./.; 6 | exes = [ "svctl" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/test-runner/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | source 'https://rubygems.vpsfree.cz' do 4 | gem 'test-runner', '25.05.0.build20250602201001' 5 | end 6 | -------------------------------------------------------------------------------- /os/packages/test-runner/default.nix: -------------------------------------------------------------------------------- 1 | { lib, bundlerApp }: 2 | 3 | bundlerApp { 4 | pname = "test-runner"; 5 | gemdir = ./.; 6 | exes = [ "test-runner" ]; 7 | 8 | meta = with lib; { 9 | description = ""; 10 | homepage = https://github.com/vpsfreecz/vpsadminos; 11 | license = licenses.mit; 12 | maintainers = []; 13 | platforms = platforms.unix; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /os/packages/test-runner/entry.nix: -------------------------------------------------------------------------------- 1 | let 2 | pkgs = import { 3 | overlays = [ (import ../../overlays/ruby.nix) ]; 4 | }; 5 | in pkgs.callPackage ./default.nix {} 6 | -------------------------------------------------------------------------------- /os/packages/vdevlog/default.nix: -------------------------------------------------------------------------------- 1 | { ruby, runCommand, replaceVarsWith, asciidoctor }: 2 | let 3 | vdevlog = replaceVarsWith { 4 | name = "vdevlog"; 5 | src = ./vdevlog.rb; 6 | isExecutable = true; 7 | replacements = { 8 | inherit ruby; 9 | }; 10 | }; 11 | in runCommand "vdevlog" {} '' 12 | mkdir -p $out/bin 13 | ln -s ${vdevlog} $out/bin/vdevlog 14 | 15 | mkdir -p $out/share/man/man8 16 | ${asciidoctor}/bin/asciidoctor \ 17 | -b manpage \ 18 | -D $out/share/man/man8 \ 19 | ${./vdevlog.8.adoc} 20 | '' 21 | -------------------------------------------------------------------------------- /osctl-exporter/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | html_doc 4 | .yardoc 5 | -------------------------------------------------------------------------------- /osctl-exporter/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | source 'https://rubygems.vpsfree.cz' do 6 | gem 'libosctl' 7 | gem 'osctl' 8 | gem 'osctl-exportfs' 9 | end 10 | else 11 | gem 'libosctl', path: '../libosctl' 12 | gem 'osctl', path: '../osctl' 13 | gem 'osctl-exportfs', path: '../osctl-exportfs' 14 | end 15 | 16 | group :development do 17 | gem 'rackup' 18 | gem 'rake' 19 | gem 'yard' 20 | end 21 | -------------------------------------------------------------------------------- /osctl-exporter/Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'yard' 3 | 4 | YARD::Rake::YardocTask.new do |t| 5 | t.files = ['lib/**/*.rb'] 6 | t.options = [ 7 | '--protected', 8 | "--output-dir=#{ENV['YARD_OUTPUT'] || 'html_doc'}" 9 | ] 10 | end 11 | -------------------------------------------------------------------------------- /osctl-exporter/config.ru: -------------------------------------------------------------------------------- 1 | require 'rack' 2 | require 'prometheus/middleware/exporter' 3 | require 'libosctl' 4 | require 'osctl/exporter' 5 | 6 | Thread.abort_on_exception = true 7 | OsCtl::Lib::Logger.setup(:stdout) 8 | OsCtl::Exporter::Collector.start 9 | 10 | use Rack::Deflater 11 | use Prometheus::Middleware::Exporter, { registry: OsCtl::Exporter.registry } 12 | 13 | run do 14 | [200, { 'content-type' => 'text/html' }, ['OK']] 15 | end 16 | -------------------------------------------------------------------------------- /osctl-exporter/lib/osctl/exporter.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | require 'prometheus_ext/client/registry' 3 | 4 | module OsCtl 5 | module Exporter 6 | module Formats; end 7 | 8 | # @return [MultiRegistry] 9 | def self.registry 10 | @registry ||= MultiRegistry.new 11 | end 12 | end 13 | end 14 | 15 | require_rel 'exporter/*.rb' 16 | require_rel 'exporter/formats' 17 | require 'prometheus_ext/middleware/exporter' 18 | -------------------------------------------------------------------------------- /osctl-exporter/lib/osctl/exporter/collectors.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Exporter 2 | module Collectors; end 3 | end 4 | 5 | require_rel 'collectors/*.rb' 6 | -------------------------------------------------------------------------------- /osctl-exporter/lib/osctl/exporter/formats/json.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | module OsCtl::Exporter 4 | class Formats::Json 5 | MEDIA_TYPE = 'application/json'.freeze 6 | VERSION = '0.0.1'.freeze 7 | CONTENT_TYPE = "#{MEDIA_TYPE}; version=#{VERSION}".freeze 8 | 9 | def self.marshal(registry) 10 | registry.metrics.each_with_object({}) do |metric, ret| 11 | ret[metric.name] = metric.values.map do |label_set, value| 12 | { 13 | labels: label_set, 14 | value: 15 | } 16 | end 17 | end.to_json 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctl-exporter/lib/osctl/exporter/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Exporter 3 | VERSION = '25.05.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /osctl-exporter/lib/prometheus_ext/client/registry.rb: -------------------------------------------------------------------------------- 1 | require 'prometheus/client/registry' 2 | 3 | class Prometheus::Client::Registry 4 | def initialize_copy(_other) 5 | @metrics = @metrics.clone 6 | @mutex = Mutex.new 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /osctl-exporter/lib/prometheus_ext/middleware/exporter.rb: -------------------------------------------------------------------------------- 1 | require 'prometheus/middleware/exporter' 2 | 3 | class Prometheus::Middleware::Exporter 4 | orig_formats = Prometheus::Middleware::Exporter::FORMATS 5 | remove_const(:FORMATS) 6 | FORMATS = (orig_formats + [OsCtl::Exporter::Formats::Json]).freeze 7 | end 8 | -------------------------------------------------------------------------------- /osctl-exportfs/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osctl-exportfs/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | source 'https://rubygems.vpsfree.cz' do 6 | gem 'libosctl' 7 | end 8 | else 9 | gem 'libosctl', path: '../libosctl' 10 | end 11 | 12 | group :development do 13 | gem 'md2man' 14 | gem 'rake' 15 | gem 'yard' 16 | end 17 | -------------------------------------------------------------------------------- /osctl-exportfs/bin/osctl-exportfs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctl/exportfs/cli' 3 | OsCtl::ExportFS::Cli.run 4 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | 3 | module OsCtl 4 | module ExportFS 5 | module Operations 6 | module Export; end 7 | module Exportfs; end 8 | module Runit; end 9 | module Server; end 10 | end 11 | 12 | def self.root 13 | File.realpath(File.join(__dir__, '..', '..')) 14 | end 15 | 16 | def self.enabled? 17 | Dir.exist?(RunState::DIR) 18 | end 19 | end 20 | end 21 | 22 | require_rel 'exportfs/*.rb' 23 | require_rel 'exportfs/config' 24 | require_rel 'exportfs/operations' 25 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/exportfs' 2 | require 'require_all' 3 | 4 | module OsCtl::ExportFS 5 | module Cli 6 | def self.run 7 | App.run 8 | end 9 | end 10 | end 11 | 12 | require_rel 'cli' 13 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/cli/command.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsCtl::ExportFS::Cli 4 | class Command < OsCtl::Lib::Cli::Command 5 | def self.run(klass, method) 6 | proc do |global_opts, opts, args| 7 | cmd = klass.new(global_opts, opts, args) 8 | cmd.method(method).call 9 | end 10 | end 11 | 12 | def initialize(global_opts, opts, args) 13 | super 14 | OsCtl::Lib::Logger.setup(:stdout) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/config.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::ExportFS 2 | module Config 3 | # @param server [Server] 4 | # @return [Config::TopLevel] 5 | def self.open(server) 6 | TopLevel.new(server) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/operations/base.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::ExportFS 2 | class Operations::Base 3 | def self.run(*, &) 4 | op = new(*, &) 5 | op.execute 6 | end 7 | 8 | def execute 9 | raise NotImplementedError 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/operations/server/list.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/exportfs/operations/base' 2 | 3 | module OsCtl::ExportFS 4 | class Operations::Server::List < Operations::Base 5 | def execute 6 | ret = [] 7 | 8 | Dir.entries(RunState::SERVERS).each do |v| 9 | next if %w[. ..].include?(v) 10 | 11 | ret << OsCtl::ExportFS::Server.new(v) 12 | end 13 | 14 | ret 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctl-exportfs/lib/osctl/exportfs/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module ExportFS 3 | VERSION = '25.05.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runit/1.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export PATH="<%= ENV['PATH'] %>" 3 | mkdir -p /var/lib/nfs/rpc_pipefs 4 | mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs -o defaults || exit 1 5 | mount -t nfsd nfsd /proc/fs/nfsd || exit 1 6 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runit/2.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export PATH="<%= ENV['PATH'] %>" 3 | exec runsvdir /etc/runit/runsvdir 4 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runit/3.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exportfs -ua 3 | rpc.nfsd 0 4 | exportfs -f 5 | exit 0 6 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runsv.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exec osctl-exportfs server spawn <%= name %> 3 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runsvdir/rpcbind.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export PATH="<%= ENV['PATH'] %>" 3 | exec rpcbind -f 4 | -------------------------------------------------------------------------------- /osctl-exportfs/templates/runsvdir/statd.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export PATH="<%= ENV['PATH'] %>" 3 | 4 | until rpcinfo -s > /dev/null 2>&1 ; do 5 | echo "Waiting for rpcbind to start" 6 | sleep 1 7 | done 8 | 9 | mkdir -p "<%= server.nfs_state %>/"{sm,sm.bak} 10 | 11 | exec rpc.statd \ 12 | <%= config.statd_port ? "--port #{config.statd_port}" : '' %> \ 13 | <%= config.lockd_port ? "--nlm-port #{config.lockd_port}" : '' %> \ 14 | <%= config.lockd_port ? "--nlm-udp-port #{config.lockd_port}" : '' %> \ 15 | --foreground 16 | -------------------------------------------------------------------------------- /osctl-image/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osctl-image/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | source 'https://rubygems.vpsfree.cz' do 6 | gem 'libosctl' 7 | gem 'osctl' 8 | gem 'osctl-repo' 9 | end 10 | else 11 | gem 'libosctl', path: '../libosctl' 12 | gem 'osctl', path: '../osctl' 13 | gem 'osctl-repo', path: '../osctl-repo' 14 | end 15 | 16 | group :development do 17 | gem 'md2man' 18 | gem 'rake' 19 | gem 'yard' 20 | end 21 | -------------------------------------------------------------------------------- /osctl-image/bin/osctl-image: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctl/image/cli' 3 | OsCtl::Image::Cli.run 4 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | 3 | module OsCtl 4 | module Image 5 | module Operations 6 | module Builder; end 7 | module Config; end 8 | module Execution; end 9 | module File; end 10 | module Image; end 11 | module Nix; end 12 | module Repository; end 13 | module Test; end 14 | end 15 | end 16 | end 17 | 18 | require_rel 'image/*.rb' 19 | require_rel 'image/operations' 20 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/image' 2 | require 'require_all' 3 | 4 | module OsCtl::Image 5 | module Cli 6 | def self.run 7 | App.run 8 | end 9 | end 10 | end 11 | 12 | require_rel 'cli' 13 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/cli/command.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsCtl::Image::Cli 4 | class Command < OsCtl::Lib::Cli::Command 5 | def self.run(klass, method) 6 | proc do |global_opts, opts, args| 7 | cmd = klass.new(global_opts, opts, args) 8 | cmd.method(method).call 9 | end 10 | end 11 | 12 | def initialize(global_opts, opts, args) 13 | super 14 | OsCtl::Lib::Logger.setup(:stdout) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/exceptions.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Image 2 | class OperationError < StandardError; end 3 | end 4 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/image_list.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Image 2 | class ImageList < Array 3 | # @param base_dir [String] 4 | def initialize(base_dir) 5 | super() 6 | 7 | Operations::Config::ParseList.run(base_dir, :image).each do |name| 8 | self << Image.new(base_dir, name) 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/operations/base.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Image 2 | class Operations::Base 3 | def self.run(*, **) 4 | op = new(*, **) 5 | op.execute 6 | end 7 | 8 | def execute 9 | raise NotImplementedError 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/test.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Image 2 | class Test 3 | # @return [String] 4 | attr_reader :base_dir 5 | 6 | # @return [String] 7 | attr_reader :name 8 | 9 | # @param base_dir [String] 10 | # @param name [String] 11 | def initialize(base_dir, name) 12 | @base_dir = base_dir 13 | @name = name 14 | end 15 | 16 | def to_s 17 | name 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/test_list.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Image 2 | class TestList < Array 3 | # @param base_dir [String] 4 | def initialize(base_dir) 5 | super() 6 | 7 | Operations::Config::ParseList.run(base_dir, :test).each do |name| 8 | self << Test.new(base_dir, name) 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctl-image/lib/osctl/image/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Image 3 | VERSION = '25.05.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /osctl-repo/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osctl-repo/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /osctl-repo/bin/osctl-repo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctl/repo/cli' 3 | OsCtl::Repo::Cli.run 4 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'require_all' 3 | 4 | module OsCtl 5 | module Repo 6 | module Base; end 7 | 8 | # Classes for manipulation of the repository on the server-side 9 | module Local; end 10 | 11 | # Classes for working with a remote repository over HTTP 12 | module Remote; end 13 | 14 | module Downloader; end 15 | end 16 | end 17 | 18 | require_rel 'repo/*.rb' 19 | require_rel 'repo/base' 20 | require_rel 'repo/local' 21 | require_rel 'repo/remote' 22 | require_rel 'repo/downloader' 23 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/repo' 2 | 3 | module OsCtl::Repo 4 | module Cli 5 | def self.run 6 | App.run 7 | end 8 | end 9 | end 10 | 11 | require_rel 'cli' 12 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo/constants.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Repo 3 | EXIT_OK = 0 4 | EXIT_ERROR = 1 5 | EXIT_IMAGE_NOT_FOUND = 2 6 | EXIT_FORMAT_NOT_FOUND = 3 7 | EXIT_HTTP_ERROR = 4 8 | EXIT_NETWORK_ERROR = 5 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo/downloader/base.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | 3 | module OsCtl::Repo 4 | class Downloader::Base 5 | def initialize(repo) 6 | @repo = repo 7 | end 8 | 9 | protected 10 | 11 | attr_reader :repo 12 | 13 | def connect(&) 14 | uri = URI(repo.url) 15 | http = Net::HTTP.new(uri.host, uri.port) 16 | http.use_ssl = (uri.scheme == 'https') 17 | http.start(&) 18 | rescue SystemCallError => e 19 | raise NetworkError, e 20 | end 21 | 22 | def index_uri 23 | URI(repo.index_url) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo/locator.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Repo 3 | def self.root 4 | File.absolute_path(File.join(__dir__, '..', '..', '..')) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctl-repo/lib/osctl/repo/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | module Repo 3 | VERSION = '25.05.0'.freeze 4 | SCHEMA = 1 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /osctl/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osctl/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /osctl/bin/ct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/group: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/healthcheck: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/id-range: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/osctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctl/cli' 3 | OsCtl::Cli.run 4 | -------------------------------------------------------------------------------- /osctl/bin/pool: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/repo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/bin/user: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec('osctl', File.basename(__FILE__), *ARGV) 3 | -------------------------------------------------------------------------------- /osctl/lib/osctl.rb: -------------------------------------------------------------------------------- 1 | require 'require_all' 2 | 3 | module OsCtl 4 | module Utils; end 5 | end 6 | 7 | require_rel 'osctl/*.rb' 8 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osctl' 2 | 3 | module OsCtl 4 | module Cli 5 | module Completion; end 6 | module Ps; end 7 | module Top; end 8 | 9 | def self.run 10 | App.run 11 | end 12 | end 13 | end 14 | 15 | require_rel 'cli' 16 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/garbage_collector.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/cli/command' 2 | 3 | module OsCtl::Cli 4 | class GarbageCollector < Command 5 | def prune 6 | require_args!(optional: %w[pool], strict: false) 7 | 8 | cmd_opts = {} 9 | cmd_opts[:pools] = args if args.any? 10 | 11 | osctld_fmt(:garbage_collector_prune, cmd_opts:) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/top/json_exporter.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'json' 3 | require 'osctl/cli/top/view' 4 | 5 | module OsCtl::Cli 6 | class Top::JsonExporter < Top::View 7 | def start 8 | queue = OsCtl::Lib::Queue.new 9 | 10 | Signal.trap('USR1') do 11 | Thread.new { queue << nil } 12 | end 13 | 14 | loop do 15 | queue.pop(timeout: rate) 16 | queue.clear 17 | 18 | model.measure 19 | puts model.data.to_json 20 | $stdout.flush 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/top/main.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/cli/command' 2 | 3 | module OsCtl::Cli 4 | class Top::Main < Command 5 | def start 6 | model = Top::Model.new(enable_iostat: opts[:iostat]) 7 | model.setup 8 | 9 | kwargs = {} 10 | 11 | if gopts[:json] 12 | klass = Top::JsonExporter 13 | 14 | else 15 | klass = Top::Tui 16 | kwargs = { enable_procs: opts[:processes] } 17 | end 18 | 19 | view = klass.new(model, opts[:rate], **kwargs) 20 | view.start 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/top/tui/key.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Cli::Top 2 | # Key constants not included in curses 3 | module Tui::Key 4 | ENTER = 10 5 | 6 | ESCAPE = 27 7 | 8 | BACKSPACE = 127 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/top/tui/screen.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/cli/top/view' 2 | 3 | module OsCtl::Cli::Top 4 | class Tui < View 5 | class Screen 6 | def open 7 | raise NotImplementedError 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/top/view.rb: -------------------------------------------------------------------------------- 1 | module OsCtl::Cli 2 | class Top::View 3 | attr_reader :model, :rate 4 | 5 | def initialize(model, rate) 6 | @model = model 7 | @rate = rate 8 | end 9 | 10 | def start 11 | raise NotImplementedError 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /osctl/lib/osctl/cli/trash_bin.rb: -------------------------------------------------------------------------------- 1 | require 'osctl/cli/command' 2 | 3 | module OsCtl::Cli 4 | class TrashBin < Command 5 | def dataset_add 6 | require_args!('dataset') 7 | osctld_fmt(:trash_bin_dataset_add, cmd_opts: { dataset: args[0] }) 8 | end 9 | 10 | def prune 11 | require_args!(optional: %w[pool], strict: false) 12 | 13 | cmd_opts = {} 14 | cmd_opts[:pools] = args if args.any? 15 | 16 | osctld_fmt(:trash_bin_prune, cmd_opts:) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctl/lib/osctl/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtl 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /osctld/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | html_doc 4 | .yardoc 5 | ext/**/*.o 6 | ext/**/*.so 7 | ext/**/Makefile 8 | **/*.so 9 | -------------------------------------------------------------------------------- /osctld/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | source 'https://rubygems.vpsfree.cz' do 5 | gem 'netlinkrb' 6 | gem 'ruby-lxc' 7 | end 8 | 9 | if ENV.has_key?('OS_BUILD_ID') 10 | source 'https://rubygems.vpsfree.cz' do 11 | gem 'libosctl' 12 | gem 'osctl-repo' 13 | gem 'osup' 14 | end 15 | else 16 | gem 'libosctl', path: '../libosctl' 17 | gem 'memory_profiler' 18 | gem 'osctl-repo', path: '../osctl-repo' 19 | gem 'osup', path: '../osup' 20 | end 21 | 22 | group :development do 23 | gem 'rake' 24 | gem 'rake-compiler' 25 | gem 'yard' 26 | end 27 | -------------------------------------------------------------------------------- /osctld/Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rake/extensiontask' 3 | require 'yard' 4 | require_relative 'yard/lockable' 5 | 6 | gemspec = Gem::Specification.load('osctld.gemspec') 7 | 8 | Rake::ExtensionTask.new do |ext| 9 | ext.name = 'native' 10 | ext.source_pattern = '*.{c,h}' 11 | ext.ext_dir = 'ext/osctld' 12 | ext.lib_dir = 'lib/osctld' 13 | ext.gem_spec = gemspec 14 | end 15 | 16 | YARD::Rake::YardocTask.new do |t| 17 | t.files = ['ext/**/*.c', 'lib/**/*.rb'] 18 | t.options = [ 19 | '--protected', 20 | "--output-dir=#{ENV['YARD_OUTPUT'] || 'html_doc'}" 21 | ] 22 | end 23 | -------------------------------------------------------------------------------- /osctld/bin/osctld: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctld/cli' 3 | OsCtld::Cli::Supervisor.run 4 | -------------------------------------------------------------------------------- /osctld/bin/osctld-ct-exec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctld/cli' 3 | OsCtld::Cli::Exec.run 4 | -------------------------------------------------------------------------------- /osctld/bin/osctld-ct-runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osctld/cli' 3 | OsCtld::Cli::Runner.run 4 | -------------------------------------------------------------------------------- /osctld/bin/osctld-ct-start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'json' 3 | require 'socket' 4 | 5 | pool, ctid = ARGV 6 | 7 | s = UNIXSocket.new("/run/osctl/user-control/#{Process.uid}.sock") 8 | 9 | payload = { 10 | cmd: :ct_wrapper_start, 11 | opts: { 12 | id: ctid, 13 | pool:, 14 | pid: Process.pid 15 | } 16 | } 17 | 18 | s.send("#{payload.to_json}\n", 0) 19 | 20 | ret = JSON.parse(s.readline, symbolize_names: true) 21 | s.close 22 | 23 | if ret[:status] 24 | Process.exec(*ARGV[2..]) 25 | else 26 | warn "Error: #{ret[:message]}" 27 | exit(false) 28 | end 29 | -------------------------------------------------------------------------------- /osctld/configs/lxc/alpine/common.conf: -------------------------------------------------------------------------------- 1 | # Doesn't support consoles in /dev/lxc/. 2 | lxc.tty.dir = 3 | 4 | # Mount /run as tmpfs. 5 | lxc.mount.entry = run run tmpfs rw,nodev,relatime,mode=755 0 0 6 | 7 | # Mount /dev/shm as tmpfs; needed for building python and possibly other packages. 8 | lxc.mount.entry = shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0 9 | -------------------------------------------------------------------------------- /osctld/configs/lxc/arch/common.conf: -------------------------------------------------------------------------------- 1 | # Allow for 6 tty devices by default 2 | lxc.tty.max = 6 3 | 4 | # Set the halt/stop signals 5 | lxc.signal.halt=SIGRTMIN+4 6 | -------------------------------------------------------------------------------- /osctld/configs/lxc/chimera/common.conf: -------------------------------------------------------------------------------- 1 | # Doesn't support consoles in /dev/lxc/. 2 | lxc.tty.dir = 3 | 4 | # Mount /run as tmpfs. 5 | lxc.mount.entry = run run tmpfs rw,nodev,relatime,mode=755 0 0 6 | 7 | # Mount /dev/shm as tmpfs; needed for building python and possibly other packages. 8 | lxc.mount.entry = shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0 9 | -------------------------------------------------------------------------------- /osctld/configs/lxc/common.conf: -------------------------------------------------------------------------------- 1 | lxc.include = /etc/lxc/config/common.conf 2 | lxc.include = /etc/lxc/config/userns.conf 3 | 4 | lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0 5 | lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0 6 | lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0 7 | lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0 8 | -------------------------------------------------------------------------------- /osctld/configs/lxc/debian/common.conf: -------------------------------------------------------------------------------- 1 | # Doesn't support consoles in /dev/lxc/ 2 | lxc.tty.dir = 3 | -------------------------------------------------------------------------------- /osctld/configs/lxc/gentoo/common.conf: -------------------------------------------------------------------------------- 1 | # Doesn't support consoles in /dev/lxc/ 2 | lxc.tty.dir = 3 | 4 | # /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328) 5 | # and possibly other packages. 6 | lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir 7 | -------------------------------------------------------------------------------- /osctld/configs/lxc/nesting.conf: -------------------------------------------------------------------------------- 1 | lxc.mount.entry = proc dev/.lxc/proc proc create=dir,optional 0 0 2 | lxc.mount.entry = sys dev/.lxc/sys sysfs create=dir,optional 0 0 3 | -------------------------------------------------------------------------------- /osctld/configs/lxc/slackware/common.conf: -------------------------------------------------------------------------------- 1 | # Doesn't support consoles in /dev/lxc/ 2 | lxc.tty.dir = 3 | 4 | # mount /dev/shm as tmpfs 5 | lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir 6 | -------------------------------------------------------------------------------- /osctld/configs/lxc/void/common.conf: -------------------------------------------------------------------------------- 1 | # Allow for 6 tty devices by default 2 | lxc.tty.max = 6 3 | 4 | # Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd 5 | lxc.environment = VIRTUALIZATION=lxc 6 | 7 | # Set the halt/stop signals 8 | lxc.signal.halt = SIGCONT 9 | -------------------------------------------------------------------------------- /osctld/ext/osctld/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | extension_name = 'osctld/native' 4 | dir_config(extension_name) 5 | create_makefile(extension_name) 6 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module Assets 3 | def self.register(type, klass) 4 | @types ||= {} 5 | @types[type] = klass 6 | end 7 | 8 | def self.types 9 | return [] unless @types 10 | 11 | @types.keys 12 | end 13 | 14 | def self.for_type(t) 15 | return unless @types 16 | 17 | @types[t] 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets/directory.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/assets/base_file' 2 | 3 | module OsCtld 4 | class Assets::Directory < Assets::BaseFile 5 | register :directory 6 | 7 | protected 8 | 9 | def validate(run) 10 | begin 11 | add_error('not a directory') if exist? && !opts[:optional] && !stat.directory? 12 | rescue Errno::ENOENT 13 | add_error('does not exist') 14 | end 15 | 16 | super 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets/entry.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/assets/base' 2 | 3 | module OsCtld 4 | class Assets::Entry < Assets::Base 5 | register :entry 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets/file.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/assets/base' 2 | 3 | module OsCtld 4 | class Assets::File < Assets::BaseFile 5 | register :file 6 | 7 | protected 8 | 9 | def validate(run) 10 | begin 11 | add_error('not a file') if exist? && !opts[:optional] && !stat.file? 12 | rescue Errno::ENOENT 13 | add_error('does not exist') 14 | end 15 | 16 | super 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets/symlink.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/assets/base' 2 | 3 | module OsCtld 4 | class Assets::Symlink < Assets::BaseFile 5 | register :symlink 6 | 7 | protected 8 | 9 | def validate(run) 10 | begin 11 | add_error('not a symlink') if exist? && !opts[:optional] && !stat.symlink? 12 | rescue Errno::ENOENT 13 | add_error('does not exist') 14 | end 15 | 16 | super 17 | end 18 | 19 | def stat 20 | @stat ||= File.lstat(path) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osctld/lib/osctld/assets/unix_socket.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/assets/base' 2 | 3 | module OsCtld 4 | class Assets::UnixSocket < Assets::BaseFile 5 | register :socket 6 | 7 | protected 8 | 9 | def validate(run) 10 | begin 11 | add_error('not a socket') if exist? && !opts[:optional] && !stat.socket? 12 | rescue Errno::ENOENT 13 | add_error('does not exist') 14 | end 15 | 16 | super 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osctld' 2 | require 'require_all' 3 | 4 | module OsCtld 5 | module Cli; end 6 | end 7 | 8 | require_rel 'cli' 9 | -------------------------------------------------------------------------------- /osctld/lib/osctld/cli/daemon.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsCtld 4 | class Cli::Daemon 5 | def self.run(opts) 6 | Process.setproctitle('osctld: main') 7 | OsCtl::Lib::Logger.setup(opts.log, facility: opts.log_facility) 8 | d = OsCtld::Daemon.create(opts.config) 9 | stopping = false 10 | 11 | %w[INT TERM].each do |sig| 12 | Signal.trap(sig) do 13 | next if stopping 14 | 15 | stopping = true 16 | 17 | Thread.new do 18 | d.stop 19 | end.join 20 | end 21 | end 22 | 23 | d.setup 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Assets < Commands::Base 5 | handle :ct_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | ct = DB::Containers.find(opts[:id], opts[:pool]) 11 | return error('container not found') unless ct 12 | 13 | ok(list_and_validate_assets(ct)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/cgparam_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::CGParamList < Commands::Base 5 | handle :ct_cgparam_list 6 | include Utils::CGroupParams 7 | 8 | def execute 9 | ct = DB::Containers.find(opts[:id], opts[:pool]) 10 | return error('container not found') unless ct 11 | 12 | list(ct) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/cgparam_replace.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::CGParamReplace < Commands::Base 5 | handle :ct_cgparam_replace 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::CGroupParams 9 | 10 | def execute 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | return error('container not found') unless ct 13 | 14 | replace(ct) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/cgparam_set.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::CGParamSet < Commands::Logged 5 | handle :ct_cgparam_set 6 | include OsCtl::Lib::Utils::Log 7 | include Utils::CGroupParams 8 | 9 | def find 10 | ct = DB::Containers.find(opts[:id], opts[:pool]) 11 | ct || error!('container not found') 12 | end 13 | 14 | def execute(ct) 15 | set(ct, opts, apply: ct.running?) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/cgparam_unset.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::CGParamUnset < Commands::Logged 5 | handle :ct_cgparam_unset 6 | include Utils::CGroupParams 7 | 8 | def find 9 | ct = DB::Containers.find(opts[:id], opts[:pool]) 10 | ct || error!('container not found') 11 | end 12 | 13 | def execute(ct) 14 | unset(ct, opts, reset: true, keep_going: true) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_add.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceAdd < Commands::Logged 5 | handle :ct_device_add 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { add(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_chmod.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceChmod < Commands::Logged 5 | handle :ct_device_chmod 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { chmod(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceInherit < Commands::Logged 5 | handle :ct_device_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { inherit(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceList < Commands::Base 5 | handle :ct_device_list 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def execute 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | error!('container not found') unless ct 13 | 14 | ct.inclusively do 15 | list(ct, opts) 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_promote.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DevicePromote < Commands::Logged 5 | handle :ct_device_promote 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { promote(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_replace.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceReplace < Commands::Logged 5 | handle :ct_device_replace 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { replace(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_set_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceSetInherit < Commands::Logged 5 | handle :ct_device_set_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { set_inherit(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/device_unset_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::DeviceSetInherit < Commands::Logged 5 | handle :ct_device_unset_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | ct || error!('container not found') 13 | end 14 | 15 | def execute(ct) 16 | manipulate(ct) { unset_inherit(ct) } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/freeze.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Freeze < Commands::Base 5 | handle :ct_freeze 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | manipulate(ct) do 12 | if %i[freezing frozen stopped].include?(ct.state) 13 | next ok 14 | end 15 | 16 | ContainerControl::Commands::Freeze.run!(ct) 17 | ok 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/mount.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Mount < Commands::Base 5 | handle :ct_mount 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | error!('container not found') unless ct 10 | 11 | manipulate(ct) { ct.mount(force: true) } 12 | ok 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/mount_clear.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::MountClear < Commands::Logged 5 | handle :ct_mount_clear 6 | 7 | def find 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | ct || error!('container not found') 10 | end 11 | 12 | def execute(ct) 13 | manipulate(ct) do 14 | ct.mounts.clear 15 | ok 16 | end 17 | rescue UnmountError => e 18 | error("unable to unmount directory from the container: #{e.message}") 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/mount_delete.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::MountDelete < Commands::Logged 5 | handle :ct_mount_delete 6 | 7 | def find 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | ct || error!('container not found') 10 | end 11 | 12 | def execute(ct) 13 | manipulate(ct) do 14 | ct.mounts.delete_at(opts[:mountpoint]) 15 | ok 16 | end 17 | rescue UnmountError 18 | error('unable to unmount the directory from the container') 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/mount_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::MountList < Commands::Base 5 | handle :ct_mount_list 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | ct.inclusively do 12 | ok(ct.mounts.map(&:export)) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/prlimit_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::PrLimitList < Commands::Base 5 | handle :ct_prlimit_list 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | ret = {} 12 | 13 | ct.prlimits.each do |name, limit| 14 | next if opts[:limits] && !opts[:limits].include?(name) 15 | 16 | ret[name] = limit.export 17 | end 18 | 19 | ok(ret) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/prlimit_unset.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Container::PrLimitUnset < Commands::Logged 5 | handle :ct_prlimit_unset 6 | 7 | def find 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | ct || error!('container not found') 10 | end 11 | 12 | def execute(ct) 13 | ct.prlimits.unset(opts[:name]) 14 | ok 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/reconfigure.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Reconfigure < Commands::Base 5 | handle :ct_reconfigure 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | manipulate(ct) do 12 | ct.lxc_config.configure 13 | ok 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/recover_state.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::RecoverState < Commands::Base 5 | handle :ct_recover_state 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | manipulate(ct) do 12 | recovery = Container::Recovery.new(ct) 13 | recovery.recover_state 14 | ok 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/show.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Show < Commands::Base 5 | handle :ct_show 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include OsCtl::Lib::Utils::System 9 | include Utils::SwitchUser 10 | 11 | def execute 12 | ct = DB::Containers.find(opts[:id], opts[:pool]) 13 | ct || error!('container not found') 14 | 15 | data = ct.export 16 | data[:hostname_readout] = ct.read_hostname if opts[:read_hostname] 17 | 18 | ok(data) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/su.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Su < Commands::Base 5 | handle :ct_su 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::SwitchUser 9 | 10 | def execute 11 | ct = DB::Containers.find(opts[:id], opts[:pool]) 12 | return error('container not found') unless ct 13 | 14 | ok(ct_attach(ct, 'bash', '--rcfile', File.join(ct.lxc_dir, '.bashrc'))) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/container/unfreeze.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Container::Unfreeze < Commands::Base 5 | handle :ct_unfreeze 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | manipulate(ct) do 12 | if %i[thawed starting running stopping stopped].include?(ct.state) 13 | next ok 14 | end 15 | 16 | ContainerControl::Commands::Unfreeze.run!(ct) 17 | ok 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/disable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::Disable < Commands::Base 5 | handle :cpu_scheduler_disable 6 | 7 | def execute 8 | CpuScheduler.disable 9 | ok 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/enable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::Enable < Commands::Base 5 | handle :cpu_scheduler_enable 6 | 7 | def execute 8 | CpuScheduler.enable 9 | ok 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/package_disable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::PackageDisable < Commands::Base 5 | handle :cpu_scheduler_package_disable 6 | 7 | def execute 8 | if CpuScheduler.disable_package(opts[:package]) 9 | ok 10 | else 11 | error("package #{opts[:package].inspect} not found") 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/package_enable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::PackageEnable < Commands::Base 5 | handle :cpu_scheduler_package_enable 6 | 7 | def execute 8 | if CpuScheduler.enable_package(opts[:package]) 9 | ok 10 | else 11 | error("package #{opts[:package].inspect} not found") 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/package_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::PackageList < Commands::Base 5 | handle :cpu_scheduler_package_list 6 | 7 | def execute 8 | ok(CpuScheduler.export_packages) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/status.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::Status < Commands::Base 5 | handle :cpu_scheduler_status 6 | 7 | def execute 8 | ok(CpuScheduler.export_status) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/cpu_scheduler/upkeep.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::CpuScheduler::Upkeep < Commands::Base 5 | handle :cpu_scheduler_upkeep 6 | 7 | def execute 8 | CpuScheduler.upkeep 9 | ok 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/dataset/list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Dataset::List < Commands::Base 5 | handle :ct_dataset_list 6 | 7 | def execute 8 | ct = DB::Containers.find(opts[:id], opts[:pool]) 9 | return error('container not found') unless ct 10 | 11 | ct.inclusively do 12 | ok(ct.dataset.list(properties: opts[:properties]).map(&:export)) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/debug/lock_registry.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'osctld/commands/base' 3 | 4 | module OsCtld 5 | class Commands::Debug::LockRegistry < Commands::Base 6 | handle :debug_lock_registry 7 | 8 | include OsCtl::Lib::Utils::Exception 9 | 10 | def execute 11 | error!('lock registry is disabled') unless LockRegistry.enabled? 12 | 13 | ok(LockRegistry.export.each do |lock| 14 | lock[:backtrace] = denixstorify(lock[:backtrace]) 15 | end) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/debug/thread_list.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'osctld/commands/base' 3 | 4 | module OsCtld 5 | class Commands::Debug::ThreadList < Commands::Base 6 | handle :debug_thread_list 7 | 8 | include OsCtl::Lib::Utils::Exception 9 | 10 | def execute 11 | ok(ThreadReaper.export.map do |thread, manager| 12 | { 13 | thread: thread.to_s, 14 | manager: manager.to_s, 15 | backtrace: thread.backtrace && denixstorify(thread.backtrace) 16 | } 17 | end) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/debug/ugid_registry.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | require 'osctld/commands/base' 3 | 4 | module OsCtld 5 | class Commands::Debug::UGidkRegistry < Commands::Base 6 | handle :debug_ugid_registry 7 | 8 | include OsCtl::Lib::Utils::Exception 9 | 10 | def execute 11 | ok(UGidRegistry.export) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/garbage_collector/prune.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::GarbageCollector::Prune < Commands::Base 5 | handle :garbage_collector_prune 6 | 7 | def execute 8 | pools.each { |pool| pool.garbage_collector.prune } 9 | ok 10 | end 11 | 12 | protected 13 | 14 | def pools 15 | if opts[:pools] 16 | opts[:pools].map do |name| 17 | DB::Pools.find(name) || error!("pool #{name} not found") 18 | end 19 | 20 | else 21 | DB::Pools.get 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::Assets < Commands::Base 5 | handle :group_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | grp = DB::Groups.find(opts[:name], opts[:pool]) 11 | return error('group not found') unless grp 12 | 13 | ok(list_and_validate_assets(grp)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/cgparam_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::CGParamList < Commands::Base 5 | handle :group_cgparam_list 6 | include Utils::CGroupParams 7 | 8 | def execute 9 | grp = DB::Groups.find(opts[:name], opts[:pool]) 10 | return error('group not found') unless grp 11 | 12 | list(grp) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/cgparam_replace.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::CGParamReplace < Commands::Base 5 | handle :group_cgparam_replace 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::CGroupParams 9 | 10 | def execute 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | return error('group not found') unless grp 13 | 14 | replace(grp) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/cgparam_set.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::CGParamSet < Commands::Logged 5 | handle :group_cgparam_set 6 | include OsCtl::Lib::Utils::Log 7 | include Utils::CGroupParams 8 | 9 | def find 10 | grp = DB::Groups.find(opts[:name], opts[:pool]) 11 | grp || error!('group not found') 12 | end 13 | 14 | def execute(grp) 15 | set(grp, opts, apply: grp.any_container_running?) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/cgparam_unset.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::CGParamUnset < Commands::Logged 5 | handle :group_cgparam_unset 6 | include Utils::CGroupParams 7 | 8 | def find 9 | grp = DB::Groups.find(opts[:name], opts[:pool]) 10 | grp || error!('group not found') 11 | end 12 | 13 | def execute(grp) 14 | unset(grp, opts, reset: true, keep_going: true) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/cgsubsystems.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::CGSubsystems < Commands::Base 5 | handle :group_cgsubsystems 6 | 7 | def execute 8 | if CGroup.v2? 9 | error!('command group_cgsubsystems is for cgroupv1, but v2 in use') 10 | end 11 | 12 | ret = {} 13 | 14 | %w[cpu cpuacct memory pids].each do |v| 15 | ret[v] = CGroup.abs_cgroup_path(CGroup.real_subsystem(v)) 16 | end 17 | 18 | ok(ret) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_add.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceAdd < Commands::Logged 5 | handle :group_device_add 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | add(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_chmod.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceChmod < Commands::Logged 5 | handle :group_device_chmod 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | chmod(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceInherit < Commands::Logged 5 | handle :group_device_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | error!('the root group cannot inherit devices') if grp.root? 18 | 19 | inherit(grp) 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceList < Commands::Base 5 | handle :group_device_list 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def execute 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | error!('group not found') unless grp 13 | 14 | grp.inclusively do 15 | list(grp, opts) 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_promote.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DevicePromote < Commands::Logged 5 | handle :group_device_promote 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | promote(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_replace.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceReplace < Commands::Logged 5 | handle :group_device_replace 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | replace(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_set_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceSetInherit < Commands::Logged 5 | handle :group_device_set_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | set_inherit(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/device_unset_inherit.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Group::DeviceUnsetInherit < Commands::Logged 5 | handle :group_device_unset_inherit 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::Devices 9 | 10 | def find 11 | grp = DB::Groups.find(opts[:name], opts[:pool]) 12 | grp || error!('group not found') 13 | end 14 | 15 | def execute(grp) 16 | manipulate(grp) do 17 | unset_inherit(grp) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::List < Commands::Base 5 | handle :group_list 6 | 7 | def execute 8 | ret = [] 9 | 10 | DB::Groups.each_by_ids(opts[:names], opts[:pool]) do |grp| 11 | grp.inclusively do 12 | ret << grp.export.merge!(grp.attrs.export) 13 | end 14 | end 15 | 16 | ok(ret) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/group/show.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Group::Show < Commands::Base 5 | handle :group_show 6 | 7 | def execute 8 | grp = DB::Groups.find(opts[:name], opts[:pool]) 9 | return error('group not found') unless grp 10 | 11 | grp.inclusively do 12 | ok(grp.export.merge!(grp.attrs.export)) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::IdRange::Assets < Commands::Base 5 | handle :id_range_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | range = DB::IdRanges.find(opts[:name], opts[:pool]) 11 | error!('id range not found') unless range 12 | 13 | ok(list_and_validate_assets(range)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/delete.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::IdRange::Delete < Commands::Logged 5 | handle :id_range_delete 6 | 7 | def find 8 | DB::IdRanges.find(opts[:name], opts[:pool]) 9 | end 10 | 11 | def execute(range) 12 | manipulate(range) do 13 | unless range.can_delete? 14 | error!('unable to delete, ID range is in use') 15 | end 16 | 17 | File.unlink(range.config_path) 18 | DB::IdRanges.remove(range) 19 | end 20 | 21 | ok 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/free.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::IdRange::Free < Commands::Logged 5 | handle :id_range_free 6 | 7 | def find 8 | range = DB::IdRanges.find(opts[:name], opts[:pool]) 9 | range || error!('id range not found') 10 | end 11 | 12 | def execute(range) 13 | if opts[:block_index] 14 | range.free_at(opts[:block_index]) 15 | elsif opts[:owner] 16 | range.free_by(opts[:owner]) 17 | end 18 | 19 | ok 20 | rescue IdRange::AllocationError => e 21 | error(e.message) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::IdRange::List < Commands::Base 5 | handle :id_range_list 6 | 7 | def execute 8 | ret = [] 9 | 10 | DB::IdRanges.each_by_ids(opts[:names], opts[:pool]) do |range| 11 | ret << range.export 12 | end 13 | 14 | ok(ret) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/show.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::IdRange::Show < Commands::Base 5 | handle :id_range_show 6 | 7 | def execute 8 | range = DB::IdRanges.find(opts[:name], opts[:pool]) 9 | error!('id range not found') unless range 10 | 11 | ok(range.export) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/table_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::IdRange::TableList < Commands::Base 5 | handle :id_range_table_list 6 | 7 | def execute 8 | range = DB::IdRanges.find(opts[:name], opts[:pool]) 9 | error!('id range not found') unless range 10 | 11 | ret = 12 | case opts[:type] 13 | when nil, 'all' 14 | range.export_all 15 | 16 | when 'allocated' 17 | range.export_allocated 18 | 19 | when 'free' 20 | range.export_free 21 | end 22 | 23 | ok(ret) 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/id_range/table_show.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::IdRange::TableShow < Commands::Base 5 | handle :id_range_table_show 6 | 7 | def execute 8 | range = DB::IdRanges.find(opts[:name], opts[:pool]) 9 | error!('id range not found') unless range 10 | 11 | if opts[:block_index] < 0 || opts[:block_index] >= range.block_count 12 | error!('block_index out of range') 13 | end 14 | 15 | ok(range.export_at(opts[:block_index])) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/abort_export.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Pool::AbortExport < Commands::Base 5 | handle :pool_abort_export 6 | 7 | def execute 8 | pool = DB::Pools.find(opts[:name]) 9 | error!('pool not imported') unless pool 10 | 11 | pool.abort_export 12 | ok 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Pool::Assets < Commands::Base 5 | handle :pool_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | pool = DB::Pools.find(opts[:name]) 11 | return error('pool not found') unless pool 12 | 13 | ok(list_and_validate_assets(pool)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/auto_start_cancel.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Pool::AutoStartCancel < Commands::Base 5 | handle :pool_autostart_cancel 6 | 7 | def execute 8 | pool = DB::Pools.find(opts[:name]) 9 | error!('pool not found') unless pool 10 | 11 | manipulate(pool) do 12 | pool.autostart_plan.clear 13 | ok 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/auto_start_trigger.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Pool::AutoStartTrigger < Commands::Base 5 | handle :pool_autostart_trigger 6 | 7 | def execute 8 | pool = DB::Pools.find(opts[:name]) 9 | error!('pool not found') unless pool 10 | 11 | manipulate(pool) do 12 | begin 13 | pool.autostart(force: true) 14 | rescue HookFailed => e 15 | error!("pre-autostart hook failed: #{e.message}") 16 | end 17 | 18 | ok 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/uninstall.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Pool::Uninstall < Commands::Base 5 | handle :pool_uninstall 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include OsCtl::Lib::Utils::System 9 | 10 | def execute 11 | name = opts[:name] 12 | return error('export the pool first') if DB::Pools.contains?(name) 13 | 14 | zfs(:set, "#{Pool::PROPERTY_ACTIVE}=no", name) 15 | zfs(:inherit, Pool::PROPERTY_ACTIVE, name) 16 | zfs(:inherit, Pool::PROPERTY_DATASET, name) 17 | ok 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/pool/unset.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Pool::Unset < Commands::Logged 5 | handle :pool_unset 6 | 7 | def find 8 | pool = DB::Pools.find(opts[:name]) 9 | pool || error!('pool not found') 10 | end 11 | 12 | def execute(pool) 13 | manipulate(pool) do 14 | changes = {} 15 | 16 | changes[:options] = opts[:options].map(&:to_sym) if opts[:options] 17 | changes[:attrs] = opts[:attrs] if opts[:attrs] 18 | 19 | pool.unset(changes) 20 | ok 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/receive/authkey_list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Receive::AuthKeyList < Commands::Base 5 | handle :receive_authkey_list 6 | 7 | def execute 8 | pool = if opts[:pool] 9 | DB::Pools.find(opts[:pool]) 10 | 11 | else 12 | DB::Pools.get_or_default(nil) 13 | end 14 | 15 | error!('pool not found') unless pool 16 | 17 | ok(pool.send_receive_key_chain.export) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/repository/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Repository::Assets < Commands::Base 5 | handle :repo_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | repo = DB::Repositories.find(opts[:name], opts[:pool]) 11 | return error('repository not found') unless repo 12 | 13 | ok(list_and_validate_assets(repo)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/repository/disable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Repository::Disable < Commands::Logged 5 | handle :repo_disable 6 | 7 | def find 8 | DB::Repositories.find(opts[:name], opts[:pool]) 9 | end 10 | 11 | def execute(repo) 12 | manipulate(repo) do 13 | repo.disable 14 | ok 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/repository/enable.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/logged' 2 | 3 | module OsCtld 4 | class Commands::Repository::Enable < Commands::Logged 5 | handle :repo_enable 6 | 7 | def find 8 | DB::Repositories.find(opts[:name], opts[:pool]) 9 | end 10 | 11 | def execute(repo) 12 | manipulate(repo) do 13 | repo.enable 14 | ok 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/repository/list.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Repository::List < Commands::Base 5 | handle :repo_list 6 | 7 | def execute 8 | ret = [] 9 | 10 | DB::Repositories.each_by_ids(opts[:names], opts[:pool]) do |repo| 11 | ret << repo.export.merge!(repo.attrs.export) 12 | end 13 | 14 | ok(ret) 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/repository/show.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Repository::Show < Commands::Base 5 | handle :repo_show 6 | 7 | def execute 8 | repo = DB::Repositories.find(opts[:name], opts[:pool]) 9 | error!('repository not found') unless repo 10 | 11 | repo.inclusively do 12 | ok({ 13 | pool: repo.pool.name, 14 | name: repo.name, 15 | url: repo.url, 16 | enabled: repo.enabled? 17 | }.merge!(repo.attrs.export)) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/self/abort_shutdown.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Self::AbortShutdown < Commands::Base 5 | handle :self_abort_shutdown 6 | 7 | def execute 8 | Daemon.get.abort_shutdown 9 | ok 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/self/activate.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Self::Activate < Commands::Base 5 | handle :self_activate 6 | 7 | include OsCtl::Lib::Utils::Log 8 | include Utils::SwitchUser 9 | 10 | def execute 11 | if opts[:system] 12 | progress('Regenerating system files') 13 | call_cmd(Commands::User::SubUGIds) 14 | call_cmd(Commands::User::LxcUsernet) 15 | end 16 | 17 | ok 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/self/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Self::Assets < Commands::Base 5 | handle :self_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | ok(list_and_validate_assets(Daemon.get)) 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/self/ping.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Self::Ping < Commands::Base 5 | handle :self_ping 6 | 7 | def execute 8 | ok('pong') 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/self/status.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Self::Status < Commands::Base 5 | handle :self_status 6 | 7 | def execute 8 | d = Daemon.get 9 | 10 | ok({ 11 | started_at: d.started_at.to_i, 12 | initialized: d.initialized 13 | }) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/send/key_path.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::Send::KeyPath < Commands::Base 5 | handle :send_key_path 6 | 7 | def execute 8 | pool = if opts[:pool] 9 | DB::Pools.find(opts[:pool]) 10 | 11 | else 12 | DB::Pools.get_or_default(nil) 13 | end 14 | 15 | error!('pool not found') unless pool 16 | 17 | ok( 18 | private_key: pool.send_receive_key_chain.private_key_path, 19 | public_key: pool.send_receive_key_chain.public_key_path 20 | ) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/trash_bin/prune.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::TrashBin::Prune < Commands::Base 5 | handle :trash_bin_prune 6 | 7 | def execute 8 | pools.each { |pool| pool.trash_bin.prune } 9 | ok 10 | end 11 | 12 | protected 13 | 14 | def pools 15 | if opts[:pools] 16 | opts[:pools].map do |name| 17 | DB::Pools.find(name) || error!("pool #{name} not found") 18 | end 19 | 20 | else 21 | DB::Pools.get 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /osctld/lib/osctld/commands/user/assets.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class Commands::User::Assets < Commands::Base 5 | handle :user_assets 6 | 7 | include Utils::Assets 8 | 9 | def execute 10 | u = DB::Users.find(opts[:name], opts[:pool]) 11 | return error('user not found') unless u 12 | 13 | ok(list_and_validate_assets(u)) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/container/adaptor.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsCtld 4 | # Adapt container config to make it compatible with the current system 5 | module Container::Adaptor 6 | def self.register(name, klass) 7 | @adaptors ||= {} 8 | @adaptors[name] = klass 9 | end 10 | 11 | # @param ct [Container] 12 | # @param config [Hash] container config 13 | # @return [Hash] adapted config 14 | def self.adapt(ct, config) 15 | (@adaptors || {}).each_value do |klass| 16 | config = klass.new(ct, config).adapt 17 | end 18 | 19 | config 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/container/adaptors/base.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | class Container::Adaptor::Base 3 | def self.register(name) 4 | Container::Adaptor.register(name, self) 5 | end 6 | 7 | include OsCtl::Lib::Utils::Log 8 | 9 | # @param ct [Container] 10 | # @param config [Hash] container config 11 | def initialize(ct, config) 12 | @ct = ct 13 | @config = config 14 | end 15 | 16 | # @return [Hash] adapted config 17 | def adapt 18 | config 19 | end 20 | 21 | def log_type 22 | ct.log_type 23 | end 24 | 25 | protected 26 | 27 | attr_reader :ct, :config 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /osctld/lib/osctld/container_control/commands/freeze.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/container_control/command' 2 | require 'osctld/container_control/frontend' 3 | require 'osctld/container_control/runner' 4 | 5 | module OsCtld 6 | class ContainerControl::Commands::Freeze < ContainerControl::Command 7 | class Frontend < ContainerControl::Frontend 8 | # @return [true] 9 | def execute 10 | ret = exec_runner 11 | ret.ok? || ret 12 | end 13 | end 14 | 15 | class Runner < ContainerControl::Runner 16 | def execute 17 | lxc_ct.freeze 18 | ok 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/container_control/commands/unfreeze.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/container_control/command' 2 | require 'osctld/container_control/frontend' 3 | require 'osctld/container_control/runner' 4 | 5 | module OsCtld 6 | class ContainerControl::Commands::Unfreeze < ContainerControl::Command 7 | class Frontend < ContainerControl::Frontend 8 | # @return [true] 9 | def execute 10 | ret = exec_runner 11 | ret.ok? || ret 12 | end 13 | end 14 | 15 | class Runner < ContainerControl::Runner 16 | def execute 17 | lxc_ct.unfreeze 18 | ok 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/db/containers.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/db/pooled_list' 2 | 3 | module OsCtld::DB 4 | class Containers < PooledList; end 5 | end 6 | -------------------------------------------------------------------------------- /osctld/lib/osctld/db/id_ranges.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/db/pooled_list' 2 | 3 | module OsCtld 4 | class DB::IdRanges < DB::PooledList 5 | def self.setup(pool) 6 | range = IdRange.new(pool, 'default') 7 | add(range) 8 | rescue Errno::ENOENT 9 | start_id = 1_000_000 10 | block_size = 65_536 11 | 12 | Commands::IdRange::Create.run!( 13 | pool:, 14 | name: 'default', 15 | start_id:, 16 | block_size:, 17 | block_count: ((2**32) - start_id) / block_size 18 | ) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /osctld/lib/osctld/db/pools.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/db/list' 2 | 3 | module OsCtld 4 | class DB::Pools < DB::List 5 | class << self 6 | %i[get_or_default].each do |v| 7 | define_method(v) do |*args, &block| 8 | instance.send(v, *args, &block) 9 | end 10 | end 11 | end 12 | 13 | def get_or_default(name) 14 | sync do 15 | if name 16 | find(name) 17 | 18 | else 19 | objects.first 20 | end 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /osctld/lib/osctld/db/repositories.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/db/pooled_list' 2 | 3 | module OsCtld 4 | class DB::Repositories < DB::PooledList 5 | def self.setup(pool) 6 | repo = Repository.new(pool, 'default') 7 | add(repo) 8 | rescue Errno::ENOENT 9 | # Commands::Repository::Add.run!( 10 | # pool: pool, 11 | # name: 'default', 12 | # url: 'http://192.168.122.75/repo/' 13 | # ) 14 | 15 | Commands::Repository::Add.run( 16 | pool:, 17 | name: 'default', 18 | url: 'https://images.vpsadminos.org' 19 | ) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /osctld/lib/osctld/devices/owner.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | # Virtual interface with methods that a device owner must implement 3 | class Devices::Owner 4 | # @return [Devices::Manager] 5 | def devices; end 6 | 7 | # @return [Pool] 8 | def pool; end 9 | 10 | # @return [String] 11 | def ident; end 12 | 13 | def save_config; end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/devices/v2/group_configurator.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/devices/v2/configurator' 2 | 3 | module OsCtld 4 | class Devices::V2::GroupConfigurator < Devices::V2::Configurator 5 | def init(devices) 6 | CGroup.mkpath('devices', cgroup_path.split('/'), leaf: false) 7 | get_prog(devices) 8 | attach_prog(devices) 9 | end 10 | 11 | def reconfigure(devices) 12 | attach_prog(devices) 13 | end 14 | 15 | protected 16 | 17 | def cgroup_path 18 | owner.cgroup_path 19 | end 20 | 21 | def abs_cgroup_path 22 | owner.abs_cgroup_path('devices') 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/almalinux.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/redhat' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::AlmaLinux < DistConfig::Distributions::RedHat 5 | distribution :almalinux 6 | 7 | class Configurator < DistConfig::Distributions::RedHat::Configurator 8 | protected 9 | 10 | def network_class 11 | [ 12 | DistConfig::Network::NetworkManager, 13 | DistConfig::Network::RedHatNetworkManager 14 | ] 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/alpine.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/debian' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::Alpine < DistConfig::Distributions::Debian 5 | distribution :alpine 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/centos.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/redhat' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::CentOS < DistConfig::Distributions::RedHat 5 | distribution :centos 6 | 7 | class Configurator < DistConfig::Distributions::RedHat::Configurator 8 | protected 9 | 10 | def network_class 11 | [ 12 | DistConfig::Network::NetworkManager, 13 | DistConfig::Network::RedHatNetworkManager, 14 | DistConfig::Network::RedHatInitScripts 15 | ] 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/devuan.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/debian' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::Devuan < DistConfig::Distributions::Debian 5 | distribution :devuan 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/rocky.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/redhat' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::Rocky < DistConfig::Distributions::RedHat 5 | distribution :rocky 6 | 7 | class Configurator < DistConfig::Distributions::RedHat::Configurator 8 | protected 9 | 10 | def network_class 11 | [ 12 | DistConfig::Network::NetworkManager, 13 | DistConfig::Network::RedHatNetworkManager 14 | ] 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osctld/lib/osctld/dist_config/distributions/ubuntu.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/dist_config/distributions/debian' 2 | 3 | module OsCtld 4 | class DistConfig::Distributions::Ubuntu < DistConfig::Distributions::Debian 5 | distribution :ubuntu 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctld/lib/osctld/eventd.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module Eventd 3 | class << self 4 | def instance 5 | @instance ||= Eventd::Manager.new 6 | end 7 | 8 | %i[start stop shutdown subscribe unsubscribe report].each do |m| 9 | define_method(m) do |*args, **kwargs, &block| 10 | instance.method(m).call(*args, **kwargs, &block) 11 | end 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osctld/lib/osctld/eventd/event.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | class Eventd::Event 3 | attr_reader :type, :opts 4 | 5 | def initialize(type, opts) 6 | @type = type 7 | @opts = opts 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /osctld/lib/osctld/monitor.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module Monitor 3 | STATES = %i[ 4 | stopped 5 | starting 6 | running 7 | stopping 8 | aborting 9 | freezing 10 | frozen 11 | thawed 12 | ].freeze 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /osctld/lib/osctld/net_interface.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module NetInterface 3 | def self.register(type, klass) 4 | @types ||= {} 5 | @types[type] = klass 6 | end 7 | 8 | def self.for(type) 9 | @types[type] 10 | end 11 | 12 | def self.setup 13 | @types.each_value(&:setup) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /osctld/lib/osctld/prlimits.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module PrLimits 3 | # @param resource [String] 4 | # @return [Integer] 5 | def self.resource_to_const(resource) 6 | PrLimits.const_get(resource.upcase) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /osctld/lib/osctld/progress_tracker.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | class ProgressTracker 3 | def initialize(progress: 0, total: 0) 4 | @progress = progress 5 | @total = total 6 | @mutex = Mutex.new 7 | end 8 | 9 | def add_total(total) 10 | @mutex.synchronize { @total += total } 11 | end 12 | 13 | # @param message [String] 14 | # @param increment_by [Integer, nil] 15 | def progress_line(message, increment_by: 1) 16 | @mutex.synchronize do 17 | @progress += increment_by if increment_by 18 | 19 | "[#{@progress}/#{@total}] #{message}" 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osctld/lib/osctld/send_receive/command.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/command' 2 | 3 | module OsCtld 4 | class SendReceive::Command < Command; end 5 | end 6 | -------------------------------------------------------------------------------- /osctld/lib/osctld/send_receive/commands/base.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class SendReceive::Commands::Base < OsCtld::Commands::Base 5 | def self.handle(name) 6 | SendReceive::Command.register(name, self) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /osctld/lib/osctld/user_control.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module UserControl 3 | def self.stop 4 | Supervisor.stop_all 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /osctld/lib/osctld/user_control/command.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/command' 2 | 3 | module OsCtld 4 | class UserControl::Command < Command; end 5 | end 6 | -------------------------------------------------------------------------------- /osctld/lib/osctld/user_control/commands/base.rb: -------------------------------------------------------------------------------- 1 | require 'osctld/commands/base' 2 | 3 | module OsCtld 4 | class UserControl::Commands::Base < OsCtld::Commands::Base 5 | def self.handle(name) 6 | UserControl::Command.register(name, self) 7 | end 8 | 9 | def self.run(user, opts = {}) 10 | c = new(user, opts) 11 | c.execute 12 | end 13 | 14 | attr_reader :user 15 | 16 | def initialize(user, opts) # rubocop:disable Lint/MissingSuper 17 | @user = user 18 | @opts = opts 19 | end 20 | 21 | protected 22 | 23 | def owns_ct?(ct) 24 | ct.user == user 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /osctld/lib/osctld/utils/assets.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | module Utils::Assets 3 | # @param entity [#assets] 4 | def list_and_validate_assets(entity) 5 | validator = Assets::Validator.new(entity.assets) 6 | validator.validate.map do |asset| 7 | { 8 | type: asset.type, 9 | path: asset.path, 10 | opts: asset.opts, 11 | state: asset.state, 12 | errors: asset.errors 13 | } 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /osctld/lib/osctld/version.rb: -------------------------------------------------------------------------------- 1 | module OsCtld 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /osctld/templates/apparmor/features/nesting.erb: -------------------------------------------------------------------------------- 1 | mount -> /usr/lib/*/lxc/{**,}, 2 | mount -> /usr/lib/lxc/{**,}, 3 | mount options=bind /dev/pts/ptmx/ -> /dev/ptmx/, 4 | mount options=bind /dev/pts/** -> /dev/**, 5 | # allow pre-mount hooks to stage mounts under /var/lib/lxc// 6 | mount -> /var/lib/lxc/{**,}, 7 | 8 | deny /dev/.lxc/proc/** rw, 9 | deny /dev/.lxc/sys/** rw, 10 | -------------------------------------------------------------------------------- /osctld/templates/ct/lxcfs_runsv.erb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | <% if cpuset -%> 3 | mkdir -p "<%= cgroup_dir %>" 4 | <% if CGroup.v2? -%> 5 | echo +cpuset > "<%= cgroup_root %>/cgroup.subtree_control" 6 | <% end -%> 7 | echo $$ > "<%= cgroup_dir %>/cgroup.procs" 8 | echo <%= cpuset %> > "<%= cgroup_dir %>/cpuset.cpus" 9 | 10 | <% end -%> 11 | mkdir -p "<%= mountpoint %>" 12 | umount "<%= mountpoint %>" 2> /dev/null 13 | exec <%= executable %> <%= options.join(' ') %> "<%= mountpoint %>" 14 | -------------------------------------------------------------------------------- /osctld/templates/ct/net_interface/bridge.erb: -------------------------------------------------------------------------------- 1 | lxc.net.<%= index %>.type = veth 2 | lxc.net.<%= index %>.name = <%= name %> 3 | lxc.net.<%= index %>.link = <%= link %> 4 | lxc.net.<%= index %>.flags = up 5 | <% if hwaddr -%> 6 | lxc.net.<%= index %>.hwaddr = <%= hwaddr %> 7 | <% end -%> 8 | <% if tx_queues > 1 -%> 9 | lxc.net.<%= index %>.veth.n_txqueues = <%= tx_queues %> 10 | <% end -%> 11 | <% if rx_queues > 1 -%> 12 | lxc.net.<%= index %>.veth.n_rxqueues = <%= rx_queues %> 13 | <% end -%> 14 | lxc.net.<%= index %>.script.up = <%= hook_veth_up %> 15 | lxc.net.<%= index %>.script.down = <%= hook_veth_down %> 16 | -------------------------------------------------------------------------------- /osctld/templates/ct/net_interface/routed.erb: -------------------------------------------------------------------------------- 1 | lxc.net.<%= index %>.type = veth 2 | lxc.net.<%= index %>.name = <%= name %> 3 | lxc.net.<%= index %>.flags = up 4 | <% if hwaddr -%> 5 | lxc.net.<%= index %>.hwaddr = <%= hwaddr %> 6 | <% end -%> 7 | <% if tx_queues > 1 -%> 8 | lxc.net.<%= index %>.veth.n_txqueues = <%= tx_queues %> 9 | <% end -%> 10 | <% if rx_queues > 1 -%> 11 | lxc.net.<%= index %>.veth.n_rxqueues = <%= rx_queues %> 12 | <% end -%> 13 | lxc.net.<%= index %>.script.up = <%= hook_veth_up %> 14 | lxc.net.<%= index %>.script.down = <%= hook_veth_down %> 15 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/guix/bridge.erb: -------------------------------------------------------------------------------- 1 | export PATH="/run/current-system/profile/bin:/run/current-system/profile/sbin:$PATH" 2 | 3 | <% [4, 6].each do |v| -%> 4 | 5 | <% netif.ips(v).each do |addr| -%> 6 | ip -<%= v %> addr <%= op %> <%= addr.to_string %> dev <%= netif.name %> &> /dev/null || true 7 | <% end -%> 8 | 9 | <% if !netif.dhcp && netif.has_gateway?(v) -%> 10 | ip -<%= v %> route <%= op %> default via <%= netif.gateway(v) %> dev <%= netif.name %> <%= op == "del" ? '|| true' : '' %> 11 | <% end -%> 12 | 13 | <% end -%> 14 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/netifrc/bridge.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS. Do not edit this file, all 2 | # changes will be lost. 3 | 4 | <% if netif.dhcp -%> 5 | config_<%= netif.name %>="dhcp" 6 | <% else -%> 7 | config_<%= netif.name %>=" 8 | <% netif.active_ip_versions.each do |v| -%> 9 | <%= netif.ips(v).map(&:to_string).join("\n") %> 10 | <% end -%> 11 | " 12 | 13 | routes_<%= netif.name %>=" 14 | <% netif.active_ip_versions.each do |v| -%> 15 | <% if netif.has_gateway?(v) %>default via <%= netif.gateway(v) %> dev <%= netif.name %><% end %> 16 | <% end -%> 17 | " 18 | <% end -%> 19 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/network_manager/bridge.erb: -------------------------------------------------------------------------------- 1 | [connection] 2 | id=<%= netif.name %> 3 | type=ethernet 4 | interface-name=<%= netif.name %> 5 | 6 | <% netif.active_ip_versions.each do |v| -%> 7 | [ipv<%= v %>] 8 | method=<%= netif.dhcp ? 'auto' : 'manual' %> 9 | <% netif.ips(v).each_with_index do |ip, i| -%> 10 | address<%= i+1 %>=<%= ip.to_string %> 11 | <% end -%> 12 | <% if !netif.dhcp && netif.has_gateway?(v) -%> 13 | gateway=<%= netif.gateway(v) %> 14 | <% end -%> 15 | <% end -%> 16 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/network_manager/nm_conf.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS every time the container 2 | # starts. Do not edit this file, your changes will be lost! 3 | # 4 | # To stop osctld from manipulating this file, run 5 | # 6 | # chmod u-w /etc/NetworkManager/conf.d/osctl.conf 7 | # 8 | 9 | <% netifs.each do |netif| -%> 10 | [device] 11 | match-device=interface-name:<%= netif.name %> 12 | managed=1 13 | 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/network_manager/routed.erb: -------------------------------------------------------------------------------- 1 | [connection] 2 | id=<%= netif.name %> 3 | type=ethernet 4 | interface-name=<%= netif.name %> 5 | 6 | <% netif.active_ip_versions.each do |v| -%> 7 | [ipv<%= v %>] 8 | method=manual 9 | <% netif.ips(v).each_with_index do |ip, i| -%> 10 | address<%= i+1 %>=<%= ip.to_string %> 11 | <% end -%> 12 | routes=<%= netif.default_via(v).to_string %> 13 | gateway=<%= netif.default_via(v) %> 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/network_manager/udev_rules.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS every time the container 2 | # starts. Do not edit this file, your changes will be lost! 3 | # 4 | # To stop osctld from manipulating this file, run 5 | # 6 | # chmod u-w /etc/udev/rules.d/86-osctl.rules 7 | # 8 | 9 | <% netifs.each do |netif| -%> 10 | ENV{ID_NET_DRIVER}=="veth", ENV{INTERFACE}=="<%= netif.name %>", ENV{NM_UNMANAGED}="0" 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/nixos/bridge.erb: -------------------------------------------------------------------------------- 1 | <% [4, 6].each do |v| -%> 2 | 3 | <% netif.ips(v).each do |addr| -%> 4 | ip -<%= v %> addr <%= op %> <%= addr.to_string %> dev <%= netif.name %> &> /dev/null || true 5 | <% end -%> 6 | 7 | <% if !netif.dhcp && netif.has_gateway?(v) -%> 8 | ip -<%= v %> route <%= op %> default via <%= netif.gateway(v) %> dev <%= netif.name %> <%= op == "del" ? '|| true' : '' %> 9 | <% end -%> 10 | 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_initscripts/routed/ifcfg.erb: -------------------------------------------------------------------------------- 1 | DEVICE=<%= netif.name %> 2 | BOOTPROTO=static 3 | ONBOOT=yes 4 | DEFROUTE=no 5 | <% netif.active_ip_versions.each do |v| -%> 6 | <% if v == 4 -%> 7 | <% netif.ips(v).each_with_index do |addr, i| -%> 8 | IPADDR<%= i %>=<%= addr.to_s %> 9 | NETMASK<%= i %>=<%= addr.netmask %> 10 | <% end -%> 11 | <% elsif v == 6 -%> 12 | <% first_ip, *rest_ips = netif.ips(v) -%> 13 | IPV6INIT="yes" 14 | IPV6ADDR=<%= first_ip.to_string %> 15 | IPV6ADDR_SECONDARIES="<%= rest_ips.map { |addr| addr.to_string }.join(' ') %>" 16 | <% end -%> 17 | <% end -%> 18 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_initscripts/routed/route_v4.erb: -------------------------------------------------------------------------------- 1 | <%= netif.default_via(4) %> dev <%= netif.name %> 2 | default via <%= netif.default_via(4) %> dev <%= netif.name %> 3 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_initscripts/routed/route_v6.erb: -------------------------------------------------------------------------------- 1 | <%= netif.default_via(6) %> dev <%= netif.name %> 2 | default via <%= netif.default_via(6) %> dev <%= netif.name %> 3 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_network_manager/nm_conf.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS every time the container 2 | # starts. Do not edit this file, your changes will be lost! 3 | # 4 | # To stop osctld from manipulating this file, run 5 | # 6 | # chmod u-w /etc/NetworkManager/conf.d/osctl.conf 7 | # 8 | 9 | <% netifs.each do |netif| -%> 10 | [device] 11 | match-device=interface-name:<%= netif.name %> 12 | managed=1 13 | 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_network_manager/routed/route_v4.erb: -------------------------------------------------------------------------------- 1 | <%= netif.default_via(4) %> dev <%= netif.name %> 2 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_network_manager/routed/route_v6.erb: -------------------------------------------------------------------------------- 1 | <%= netif.default_via(6) %> dev <%= netif.name %> 2 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/redhat_network_manager/udev_rules.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS every time the container 2 | # starts. Do not edit this file, your changes will be lost! 3 | # 4 | # To stop osctld from manipulating this file, run 5 | # 6 | # chmod u-w /etc/udev/rules.d/86-osctl.rules 7 | # 8 | 9 | <% netifs.each do |netif| -%> 10 | ENV{ID_NET_DRIVER}=="veth", ENV{INTERFACE}=="<%= netif.name %>", ENV{NM_UNMANAGED}="0" 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/slackware/bridge.erb: -------------------------------------------------------------------------------- 1 | <% if netif.dhcp -%> 2 | dhcpcd <%= netif.name %> 3 | <% end -%> 4 | 5 | <% netif.active_ip_versions.each do |v| -%> 6 | <% netif.ips(v).each do |addr| -%> 7 | ip -<%= v %> addr <%= cmd %> <%= addr.to_string %> dev <%= netif.name %> 8 | <% end -%> 9 | 10 | <% if !netif.dhcp && netif.has_gateway?(v) -%> 11 | ip -<%= v %> route <%= cmd %> default via <%= netif.gateway(v) %> dev <%= netif.name %> 12 | <% end -%> 13 | <% end -%> 14 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/slackware/routed.erb: -------------------------------------------------------------------------------- 1 | <% if cmd == 'add' -%> 2 | echo 0 > /proc/sys/net/ipv6/conf/<%= netif.name %>/accept_dad 3 | <% end -%> 4 | 5 | <% netif.active_ip_versions.each do |v| -%> 6 | <% all_ips = netif.ips(v) -%> 7 | <% all_ips.each do |addr| -%> 8 | ip -<%= v %> addr <%= cmd %> <%= addr.to_string %> dev <%= netif.name %> 9 | <% end -%> 10 | ip -<%= v %> route <%= cmd %> <%= netif.default_via(v) %> dev <%= netif.name %> 11 | ip -<%= v %> route <%= cmd %> default via <%= netif.default_via(v) %> dev <%= netif.name %> 12 | <% end -%> 13 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/suse_sysconfig/bridge/ifcfg.erb: -------------------------------------------------------------------------------- 1 | STARTMODE=auto 2 | <% if netif.dhcp -%> 3 | BOOTPROTO=dhcp 4 | ONBOOT=yes 5 | <% else -%> 6 | BOOTPROTO=static 7 | <% all_ips.each_with_index do |addr, i| -%> 8 | IPADDR_<%= i %>=<%= addr.to_string %> 9 | <% end -%> 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/suse_sysconfig/bridge/ifroute.erb: -------------------------------------------------------------------------------- 1 | <% netif.active_ip_versions.each do |v| -%> 2 | <% if netif.has_gateway?(v) -%> 3 | default <%= netif.gateway(v) %> <%= v == 4 ? '0.0.0.0' : '::' %> <%= netif.name %> 4 | <% end -%> 5 | <% end -%> 6 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/suse_sysconfig/routed/ifcfg.erb: -------------------------------------------------------------------------------- 1 | STARTMODE=auto 2 | BOOTPROTO=static 3 | <% all_ips.each_with_index do |addr, i| -%> 4 | IPADDR_<%= i %>=<%= addr.to_string %> 5 | <% end -%> 6 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/suse_sysconfig/routed/ifroute.erb: -------------------------------------------------------------------------------- 1 | <% netif.active_ip_versions.each do |v| -%> 2 | <%= netif.default_via(v).to_string %> - - <%= netif.name %> 3 | default <%= netif.default_via(v).to_s %> <%= v == 4 ? '0.0.0.0' : '::' %> <%= netif.name %> 4 | <% end -%> 5 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/systemd_networkd/bridge.erb: -------------------------------------------------------------------------------- 1 | # This file is generated by osctld from vpsAdminOS. Do not edit this file, all 2 | # changes will be lost. To stop osctld from manipulating this file, run 3 | # 4 | # chmod u-w /etc/systemd/network/<%= netif.name %>.network 5 | 6 | [Match] 7 | Name=<%= netif.name %> 8 | 9 | [Network] 10 | DHCP=<%= netif.dhcp ? 'true' : 'false' %> 11 | <% netif.active_ip_versions.each do |v| -%> 12 | <% netif.ips(v).each do |addr| -%> 13 | Address=<%= addr.to_string %> 14 | <% end -%> 15 | <% end -%> 16 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/void/bridge.erb: -------------------------------------------------------------------------------- 1 | <% if netif.dhcp -%> 2 | dhcpcd <%= netif.name %> 3 | <% end -%> 4 | 5 | <% netif.active_ip_versions.each do |v| -%> 6 | <% netif.ips(v).each do |addr| -%> 7 | ip -<%= v %> addr add <%= addr.to_string %> dev <%= netif.name %> 8 | <% end -%> 9 | 10 | <% if !netif.dhcp && netif.has_gateway?(v) -%> 11 | ip -<%= v %> route add default via <%= netif.gateway(v) %> dev <%= netif.name %> 12 | <% end -%> 13 | <% end -%> 14 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/void/hostname.erb: -------------------------------------------------------------------------------- 1 | if [ -r /etc/hostname ] ; then 2 | hostname "$(cat /etc/hostname)" 3 | fi 4 | -------------------------------------------------------------------------------- /osctld/templates/dist_config/network/void/routed.erb: -------------------------------------------------------------------------------- 1 | echo 0 > /proc/sys/net/ipv6/conf/<%= netif.name %>/accept_dad 2 | 3 | <% netif.active_ip_versions.each do |v| -%> 4 | <% all_ips = netif.ips(v) -%> 5 | <% all_ips.each do |addr| -%> 6 | ip -<%= v %> addr add <%= addr.to_string %> dev <%= netif.name %> 7 | <% end -%> 8 | ip -<%= v %> route add <%= netif.default_via(v) %> dev <%= netif.name %> 9 | ip -<%= v %> route add default via <%= netif.default_via(v) %> dev <%= netif.name %> 10 | <% end -%> 11 | -------------------------------------------------------------------------------- /osup/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osup/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: ../.rubocop.yml 2 | 3 | Style/GlobalVars: 4 | Enabled: false 5 | -------------------------------------------------------------------------------- /osup/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /osup/Makefile: -------------------------------------------------------------------------------- 1 | VERSION := $(shell date +%Y%m%d%H%M%S) 2 | NAME := undefined 3 | 4 | migration: 5 | @mkdir "migrations/$(VERSION)-$(NAME)" 6 | @cp -rp migrations/.template/* "migrations/$(VERSION)-$(NAME)" 7 | @echo "migrations/$(VERSION)-$(NAME)" 8 | 9 | .PHONY: migration 10 | -------------------------------------------------------------------------------- /osup/bin/osup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osup/cli' 3 | OsUp::Cli.run 4 | -------------------------------------------------------------------------------- /osup/lib/osup/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osup' 2 | 3 | module OsUp 4 | module Cli 5 | def self.run 6 | App.run 7 | end 8 | end 9 | end 10 | 11 | require_rel 'cli' 12 | -------------------------------------------------------------------------------- /osup/lib/osup/cli/command.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsUp 4 | class Cli::Command < OsCtl::Lib::Cli::Command 5 | def self.run(klass, method) 6 | proc do |global_opts, opts, args| 7 | if global_opts[:debug] 8 | OsCtl::Lib::Logger.setup(:stdout) 9 | else 10 | OsCtl::Lib::Logger.setup(:none) 11 | end 12 | 13 | cmd = klass.new(global_opts, opts, args) 14 | cmd.method(method).call 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /osup/lib/osup/cli/runner.rb: -------------------------------------------------------------------------------- 1 | module OsUp 2 | class Cli::Runner < Cli::Command 3 | def run 4 | require_args!('pool', 'dataset', 'migration dirname', 'action') 5 | 6 | m = Migration.load(OsUp.migration_dir, args[2]) 7 | Process.setproctitle("osup: #{args[0]} #{m.id} up") 8 | 9 | $MIGRATION_ID = m.id 10 | $POOL = args[0] 11 | $DATASET = args[1] 12 | load(m.action_script(args[3])) 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /osup/lib/osup/version.rb: -------------------------------------------------------------------------------- 1 | module OsUp 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /osup/migrations/.template/down.rb: -------------------------------------------------------------------------------- 1 | # Rollback the pool 2 | -------------------------------------------------------------------------------- /osup/migrations/.template/spec.yml: -------------------------------------------------------------------------------- 1 | # Optional name, shown in `osup status` 2 | # name: 3 | 4 | description: | 5 | Describe what your migration is doing. 6 | 7 | # What datasets should be protected 8 | snapshot: 9 | - conf 10 | # - log 11 | # - hook 12 | 13 | # If the migration does not need the pool exported from osctld 14 | # export_pool: false 15 | 16 | # Use when the pool has to be exported from osctld, but the containers do not 17 | # have to be restarted 18 | # stop_containers: false 19 | -------------------------------------------------------------------------------- /osup/migrations/.template/up.rb: -------------------------------------------------------------------------------- 1 | # Upgrade the pool 2 | -------------------------------------------------------------------------------- /osup/migrations/20180825200854-set-ct-dataset-canmount-noauto/down.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | include OsCtl::Lib::Utils::Log 4 | include OsCtl::Lib::Utils::System 5 | 6 | zfs(:list, '-Hr -o name', "#{$DATASET}/ct").output.split("\n")[1..].each do |ds| 7 | zfs(:set, 'canmount=on', ds) 8 | end 9 | -------------------------------------------------------------------------------- /osup/migrations/20180825200854-set-ct-dataset-canmount-noauto/up.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | include OsCtl::Lib::Utils::Log 4 | include OsCtl::Lib::Utils::System 5 | 6 | zfs(:list, '-Hr -o name', "#{$DATASET}/ct").output.split("\n")[1..].each do |ds| 7 | zfs(:set, 'canmount=noauto', ds) 8 | end 9 | -------------------------------------------------------------------------------- /osup/migrations/20190408134218-remove-user-datasets/spec.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | User datasets have been replaced by temporary directories in `/run/osctl`. 3 | There is no need to store user data in persistent storage, since all of them 4 | are autogenerated by osctld. 5 | 6 | snapshot: [] 7 | -------------------------------------------------------------------------------- /osup/migrations/20190408134218-remove-user-datasets/up.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | include OsCtl::Lib::Utils::Log 4 | include OsCtl::Lib::Utils::System 5 | 6 | zfs(:destroy, '-r', File.join($DATASET, 'user')) 7 | -------------------------------------------------------------------------------- /osup/migrations/20190408152558-remove-user-ugid/spec.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Static user/group ID configuration for system users osctld is creating is 3 | unnecessary. User/group IDs for system users can be assigned at runtime 4 | by osctld. 5 | 6 | snapshot: 7 | - conf 8 | -------------------------------------------------------------------------------- /osup/migrations/20190624220030-rename-migrations-to-send-receive/down.rb: -------------------------------------------------------------------------------- 1 | require_relative 'common' 2 | 3 | m = RenameMigration.new 4 | m.rename_pool_config('send-receive', 'migration') 5 | m.rename_ct_configs('send_log', 'migration_log') 6 | -------------------------------------------------------------------------------- /osup/migrations/20190624220030-rename-migrations-to-send-receive/spec.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Pool configuration directory where data related to container migration 3 | are stored were renamed from migration to send-receive. Configuration keys 4 | in container configs are updated as well. 5 | 6 | snapshot: 7 | - conf 8 | -------------------------------------------------------------------------------- /osup/migrations/20190624220030-rename-migrations-to-send-receive/up.rb: -------------------------------------------------------------------------------- 1 | require_relative 'common' 2 | 3 | m = RenameMigration.new 4 | m.rename_pool_config('migration', 'send-receive') 5 | m.rename_ct_configs('migration_log', 'send_log') 6 | -------------------------------------------------------------------------------- /osup/migrations/20190814085557-add-dev-kmsg/down.rb: -------------------------------------------------------------------------------- 1 | # On rollback, the device is left alone. It is up to the administrator to remove 2 | # it. The device may be required in some configurations, which we don't want to 3 | # break. 4 | -------------------------------------------------------------------------------- /osup/migrations/20190814085557-add-dev-kmsg/spec.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Adds /dev/kmsg device (major=1 minor=11) to the root group with all access 3 | allowed. The device is needed as an interface to syslog with syslog namespace 4 | enabled. 5 | 6 | Note that the device is left alone on rollback. It is up to the administrator 7 | to remove it. The device may be required in some configurations, which we 8 | don't want to break. The command to remove it is 9 | 10 | osctl group devices del :/ char 1 11 11 | 12 | snapshot: 13 | - conf 14 | -------------------------------------------------------------------------------- /osup/migrations/20190814085557-add-dev-kmsg/up.rb: -------------------------------------------------------------------------------- 1 | require_relative 'common' 2 | 3 | pool = Pool.new 4 | root_group = GroupConfig.new(pool, '/') 5 | root_group.ensure_device(Device.new({ 6 | 'type' => 'char', 7 | 'major' => '1', 8 | 'minor' => '11', 9 | 'mode' => 'rwm', 10 | 'name' => '/dev/kmsg', 11 | 'inherit' => true, 12 | 'inherited' => false 13 | })) 14 | root_group.save 15 | -------------------------------------------------------------------------------- /osup/migrations/20220406162532-fix-container-nofile-prlimit/down.rb: -------------------------------------------------------------------------------- 1 | # Nothing to do 2 | -------------------------------------------------------------------------------- /osup/migrations/20220406162532-fix-container-nofile-prlimit/spec.yml: -------------------------------------------------------------------------------- 1 | description: | 2 | Remove faulty nofile prlimit entry from container configs. A bug in osctld 3 | caused the default nofile prlimit entry to have its key stored as Symbol 4 | instead of String. If there already is a string nofile prlimit, we remove 5 | the symbol prlimit. Otherwise we convert the key to string. 6 | 7 | snapshot: 8 | - conf 9 | 10 | stop_containers: false 11 | -------------------------------------------------------------------------------- /osvm/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /osvm/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /osvm/bin/osvm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'osvm/cli' 3 | OsVm::Cli.run 4 | -------------------------------------------------------------------------------- /osvm/lib/osvm.rb: -------------------------------------------------------------------------------- 1 | module OsVm; end 2 | 3 | require 'osvm/exceptions' 4 | require 'osvm/machine' 5 | require 'osvm/machine_config' 6 | require 'osvm/machine_log' 7 | require 'osvm/shared_dir' 8 | require 'osvm/version' 9 | -------------------------------------------------------------------------------- /osvm/lib/osvm/cli.rb: -------------------------------------------------------------------------------- 1 | require 'osvm' 2 | require 'osvm/cli/app' 3 | require 'osvm/cli/command' 4 | 5 | module OsVm::Cli 6 | def self.run 7 | App.run 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /osvm/lib/osvm/cli/command.rb: -------------------------------------------------------------------------------- 1 | require 'libosctl' 2 | 3 | module OsVm 4 | class Cli::Command < OsCtl::Lib::Cli::Command 5 | def self.run(method) 6 | proc do |global_opts, opts, args| 7 | cmd = new(global_opts, opts, args) 8 | cmd.method(method).call 9 | end 10 | end 11 | 12 | def script 13 | require_args!('file', strict: false) 14 | 15 | # Remove osvm command-line arguments, so that ARGV contains only arguments 16 | # for the script. 17 | ARGV.shift # script 18 | ARGV.shift # 19 | 20 | load(args[0]) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /osvm/lib/osvm/exceptions.rb: -------------------------------------------------------------------------------- 1 | module OsVm 2 | class Error < ::StandardError; end 3 | 4 | class TimeoutError < Error; end 5 | 6 | class UnrecoverableTimeoutError < TimeoutError; end 7 | 8 | class CommandError < Error; end 9 | 10 | class CommandSucceeded < CommandError; end 11 | 12 | class CommandFailed < CommandError; end 13 | end 14 | -------------------------------------------------------------------------------- /osvm/lib/osvm/version.rb: -------------------------------------------------------------------------------- 1 | module OsVm 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /svctl/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /svctl/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | gem 'libosctl', source: 'https://rubygems.vpsfree.cz' 6 | else 7 | gem 'libosctl', path: '../libosctl' 8 | end 9 | 10 | group :development do 11 | gem 'md2man' 12 | gem 'rake' 13 | gem 'yard' 14 | end 15 | -------------------------------------------------------------------------------- /svctl/bin/svctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'svctl/cli' 3 | SvCtl::Cli.run 4 | -------------------------------------------------------------------------------- /svctl/lib/svctl/cli.rb: -------------------------------------------------------------------------------- 1 | require 'svctl' 2 | require 'svctl/cli/app' 3 | require 'svctl/cli/command' 4 | 5 | module SvCtl::Cli 6 | def self.run 7 | App.run 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /svctl/lib/svctl/version.rb: -------------------------------------------------------------------------------- 1 | module SvCtl 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /test-runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | mkdir -p result 4 | nix-build --out-link result/test-runner os/packages/test-runner/entry.nix > /dev/null 5 | exec ./result/test-runner/bin/test-runner "$@" 6 | -------------------------------------------------------------------------------- /test-runner/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | man/style.css 4 | man/*.html 5 | man/**/*.html 6 | man/man?/*.? 7 | html_doc 8 | .yardoc 9 | -------------------------------------------------------------------------------- /test-runner/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | if ENV.has_key?('OS_BUILD_ID') 5 | source 'https://rubygems.vpsfree.cz' do 6 | gem 'libosctl' 7 | gem 'osvm' 8 | end 9 | else 10 | gem 'libosctl', path: '../libosctl' 11 | gem 'osvm', path: '../osvm' 12 | end 13 | 14 | group :development do 15 | gem 'md2man' 16 | gem 'rake' 17 | gem 'yard' 18 | end 19 | -------------------------------------------------------------------------------- /test-runner/bin/test-runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'test-runner/cli' 3 | TestRunner::Cli.run 4 | -------------------------------------------------------------------------------- /test-runner/lib/test-runner.rb: -------------------------------------------------------------------------------- 1 | module TestRunner 2 | module Cli; end 3 | end 4 | 5 | require 'test-runner/executor' 6 | require 'test-runner/test' 7 | require 'test-runner/test_config' 8 | require 'test-runner/test_evaluator' 9 | require 'test-runner/test_list' 10 | require 'test-runner/test_result' 11 | require 'test-runner/test_script' 12 | require 'test-runner/test_script_list' 13 | require 'test-runner/test_script_result' 14 | require 'test-runner/version' 15 | -------------------------------------------------------------------------------- /test-runner/lib/test-runner/cli.rb: -------------------------------------------------------------------------------- 1 | require 'test-runner' 2 | require 'test-runner/cli/app' 3 | require 'test-runner/cli/command' 4 | require 'test-runner/cli/label_filters' 5 | require 'test-runner/cli/tag_filters' 6 | 7 | module TestRunner::Cli 8 | def self.run 9 | App.run 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test-runner/lib/test-runner/version.rb: -------------------------------------------------------------------------------- 1 | module TestRunner 2 | VERSION = '25.05.0'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /tests/configs/pool-tank.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | { 3 | boot.zfs.pools.tank = { 4 | layout = [ 5 | { devices = [ "sda" ]; } 6 | ]; 7 | importAttempts = lib.mkDefault 3; 8 | doCreate = true; 9 | install = true; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /tests/machines/empty.nix: -------------------------------------------------------------------------------- 1 | pkgs: { 2 | config = { 3 | imports = [ ../configs/base.nix ]; 4 | 5 | boot.zfs.pools = {}; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /tests/machines/tank.nix: -------------------------------------------------------------------------------- 1 | pkgs: { 2 | disks = [ 3 | { type = "file"; device = "{machine}-sda.img"; size = "10G"; } 4 | ]; 5 | 6 | config = { 7 | imports = [ 8 | ../configs/base.nix 9 | ../configs/pool-tank.nix 10 | ]; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /tests/machines/with-empty.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config }: 2 | { 3 | config = { 4 | imports = [ 5 | ../configs/base.nix 6 | config 7 | ]; 8 | 9 | boot.zfs.pools = {}; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /tests/machines/with-tank.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config }: 2 | { 3 | disks = [ 4 | { type = "file"; device = "{machine}-sda.img"; size = "10G"; } 5 | ]; 6 | 7 | config = { 8 | imports = [ 9 | ../configs/base.nix 10 | ../configs/pool-tank.nix 11 | config 12 | ]; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /tests/suite/boot.nix: -------------------------------------------------------------------------------- 1 | import ../make-test.nix ({ pkgs }: { 2 | name = "boot"; 3 | 4 | description = '' 5 | Test that the system is capable of booting 6 | ''; 7 | 8 | tags = [ "ci" ]; 9 | 10 | machine = import ../machines/empty.nix pkgs; 11 | 12 | testScript = '' 13 | machine.start 14 | machine.wait_for_boot 15 | ''; 16 | }) 17 | -------------------------------------------------------------------------------- /tests/suite/defaults.nix: -------------------------------------------------------------------------------- 1 | import ../make-test.nix ({ pkgs }: { 2 | name = "defaults"; 3 | 4 | description = '' 5 | Test expected default vpsAdminOS configuration 6 | ''; 7 | 8 | tags = [ "ci" ]; 9 | 10 | machine = import ../machines/empty.nix pkgs; 11 | 12 | testScript = '' 13 | machine.start 14 | machine.fails('cat /sys/module/apparmor/parameters/enabled') 15 | ''; 16 | }) 17 | -------------------------------------------------------------------------------- /tests/suite/docker/almalinux-10.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "almalinux"; 3 | version = "10"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker yum update -y", 7 | "osctl ct exec docker yum install -y yum-utils", 8 | "osctl ct exec docker yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo", 9 | "osctl ct exec docker yum install -y docker-ce docker-ce-cli containerd.io", 10 | "osctl ct exec docker systemctl start docker", 11 | ) 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /tests/suite/docker/almalinux-8.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "almalinux"; 3 | version = "8"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker yum update -y", 7 | "osctl ct exec docker yum install -y yum-utils", 8 | "osctl ct exec docker yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo", 9 | "osctl ct exec docker yum install -y docker-ce docker-ce-cli containerd.io", 10 | "osctl ct exec docker systemctl start docker", 11 | ) 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /tests/suite/docker/almalinux-9.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "almalinux"; 3 | version = "9"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker yum update -y", 7 | "osctl ct exec docker yum install -y yum-utils", 8 | "osctl ct exec docker yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo", 9 | "osctl ct exec docker yum install -y docker-ce docker-ce-cli containerd.io", 10 | "osctl ct exec docker systemctl start docker", 11 | ) 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /tests/suite/docker/alpine-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "alpine"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker apk update", 7 | "osctl ct exec docker apk add docker", 8 | "osctl ct exec docker service docker start", 9 | ) 10 | ''; 11 | } 12 | -------------------------------------------------------------------------------- /tests/suite/docker/arch-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "arch"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker pacman -Syu --noconfirm docker", 7 | "osctl ct exec docker systemctl enable docker.service", 8 | "osctl ct exec docker systemctl start docker.service", 9 | ) 10 | ''; 11 | } 12 | -------------------------------------------------------------------------------- /tests/suite/docker/fedora-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "fedora"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec docker dnf -y update", 7 | "osctl ct exec docker dnf -y install dnf-plugins-core", 8 | "osctl ct exec docker dnf-3 config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo", 9 | "osctl ct exec docker dnf -y install docker-ce docker-ce-cli containerd.io", 10 | "osctl ct exec docker systemctl start docker", 11 | ) 12 | ''; 13 | } 14 | -------------------------------------------------------------------------------- /tests/suite/osctl/ct-exec-v1.nix: -------------------------------------------------------------------------------- 1 | import ./ct-exec-base.nix { 2 | name = "v1"; 3 | config = 4 | { config, ... }: 5 | { 6 | boot.enableUnifiedCgroupHierarchy = false; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /tests/suite/osctl/ct-exec-v2.nix: -------------------------------------------------------------------------------- 1 | import ./ct-exec-base.nix { 2 | name = "v2"; 3 | config = 4 | { config, ... }: 5 | { 6 | boot.enableUnifiedCgroupHierarchy = true; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /tests/suite/osctl/ct-runscript-v1.nix: -------------------------------------------------------------------------------- 1 | import ./ct-runscript-base.nix { 2 | name = "v1"; 3 | config = 4 | { config, ... }: 5 | { 6 | boot.enableUnifiedCgroupHierarchy = false; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /tests/suite/osctl/ct-runscript-v2.nix: -------------------------------------------------------------------------------- 1 | import ./ct-runscript-base.nix { 2 | name = "v2"; 3 | config = 4 | { config, ... }: 5 | { 6 | boot.enableUnifiedCgroupHierarchy = true; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /tests/suite/podman/debian-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "debian"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec podmanct apt-get -y update", 7 | "osctl ct exec podmanct apt-get -y install podman", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/podman/fedora-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "fedora"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec podmanct dnf -y update", 7 | "osctl ct exec podmanct dnf -y install podman", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/podman/ubuntu-latest.nix: -------------------------------------------------------------------------------- 1 | import ./base.nix { 2 | distribution = "ubuntu"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec podmanct apt-get -y update", 7 | "osctl ct exec podmanct apt-get -y install podman", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/snap/hello-base.nix: -------------------------------------------------------------------------------- 1 | { distribution, version, setupScript }: 2 | import ./base.nix { 3 | name = "hello"; 4 | description = "snap hello-world"; 5 | inherit distribution version setupScript; 6 | testScript = '' 7 | machine.succeeds("osctl ct exec snapct snap install hello-world") 8 | st, output = machine.succeeds("osctl ct exec snapct snap run hello-world") 9 | 10 | if output.strip != 'Hello World!' 11 | fail "snap run hello-world not working, output:\n#{output}" 12 | end 13 | ''; 14 | } 15 | -------------------------------------------------------------------------------- /tests/suite/snap/hello-fedora.nix: -------------------------------------------------------------------------------- 1 | import ./hello-base.nix { 2 | distribution = "fedora"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec snapct dnf -y update", 7 | "osctl ct exec snapct dnf -y install squashfuse snapd", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/snap/hello-ubuntu.nix: -------------------------------------------------------------------------------- 1 | import ./hello-base.nix { 2 | distribution = "ubuntu"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec snapct apt-get update -y", 7 | "osctl ct exec snapct apt-get -y install snapd", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/snap/lxd-fedora.nix: -------------------------------------------------------------------------------- 1 | import ./lxd-base.nix { 2 | distribution = "fedora"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec snapct dnf -y update", 7 | "osctl ct exec snapct dnf -y install screen squashfuse snapd", 8 | "osctl ct exec snapct ln -s /var/lib/snapd/snap /snap", 9 | ) 10 | ''; 11 | } 12 | -------------------------------------------------------------------------------- /tests/suite/snap/lxd-ubuntu.nix: -------------------------------------------------------------------------------- 1 | import ./lxd-base.nix { 2 | distribution = "ubuntu"; 3 | version = "latest"; 4 | setupScript = '' 5 | machine.all_succeed( 6 | "osctl ct exec snapct apt-get update -y", 7 | "osctl ct exec snapct apt-get -y install screen snapd", 8 | ) 9 | ''; 10 | } 11 | -------------------------------------------------------------------------------- /tests/suite/zfs/ugidmap/cleanup.sh: -------------------------------------------------------------------------------- 1 | log_must zfs destroy -r $TESTPOOL/$TESTFS 2 | log_must userdel $ZFS_USER 3 | log_must groupdel $ZFS_USER 4 | -------------------------------------------------------------------------------- /tests/suite/zfs/ugidmap/setup.sh: -------------------------------------------------------------------------------- 1 | log_must zfs create $TESTPOOL/$TESTFS 2 | log_must zfs create $TESTPOOL/$TESTFS/both 3 | log_must zfs create $TESTPOOL/$TESTFS/both/child 4 | log_must zfs create $TESTPOOL/$TESTFS/uid 5 | log_must zfs create $TESTPOOL/$TESTFS/uid/child 6 | log_must zfs create $TESTPOOL/$TESTFS/gid 7 | log_must zfs create $TESTPOOL/$TESTFS/gid/child 8 | log_must zfs create $TESTPOOL/$TESTFS/multimap 9 | log_must zfs create $TESTPOOL/$TESTFS/acl 10 | 11 | log_must groupadd -g $TEST_GID $ZFS_USER 12 | log_must useradd -c "ZFS UID/GID Mapping Test User" -u $TEST_UID -g $TEST_GID $ZFS_USER 13 | -------------------------------------------------------------------------------- /tests/suite/zfs/xattr.nix: -------------------------------------------------------------------------------- 1 | import ../../make-test.nix ({ pkgs }: { 2 | name = "zfs-xattr"; 3 | 4 | description = '' 5 | Test that zfs xattr=on/sa by default 6 | ''; 7 | 8 | tags = [ "ci" ]; 9 | 10 | machine = import ../../machines/tank.nix pkgs; 11 | 12 | testScript = '' 13 | machine.start 14 | machine.wait_for_service("pool-tank") 15 | 16 | st, output = machine.succeeds("zfs get -H -o value xattr tank") 17 | fail "xattr = '#{output}', expected 'on' or 'sa'" unless %w[on sa].include?(output.strip) 18 | ''; 19 | }) 20 | -------------------------------------------------------------------------------- /tools/osctl-env-exec/.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg 3 | -------------------------------------------------------------------------------- /tools/osctl-env-exec/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | -------------------------------------------------------------------------------- /tools/osctl-env-exec/Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | -------------------------------------------------------------------------------- /tools/osctl-env-exec/bin/osctl-env-exec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | Process.exec(*ARGV) 3 | -------------------------------------------------------------------------------- /tools/update_gem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | # Usage: $0 3 | 4 | set -e 5 | 6 | PKGS="$1" 7 | GEMDIR="$2" 8 | GEM="$(basename $2)" 9 | 10 | export OS_BUILD_ID="$3" 11 | 12 | pushd "$GEMDIR" 13 | [ -f Gemfile.lock ] && rm -f Gemfile.lock 14 | bundle install 15 | pkg=$(bundle exec rake build | grep -oP "pkg/.+\.gem") 16 | version=$(echo $pkg | grep -oP "\d+\.\d+\.\d+\.build\d+") 17 | 18 | gem inabox "$pkg" 19 | 20 | [ "$PKGS" == "_nopkg" ] && exit 21 | 22 | popd 23 | pushd "$PKGS/$GEM" 24 | rm -f Gemfile.lock gemset.nix 25 | sed -ri "s/gem '$GEM'[^$]*/gem '$GEM', '$version'/" Gemfile 26 | 27 | bundix -l 28 | --------------------------------------------------------------------------------