From b6f7a9e34db45885b698caf53d09d2f23350a398 Mon Sep 17 00:00:00 2001 From: spiritLHLS Date: Fri, 23 May 2025 07:23:18 +0000 Subject: [PATCH] deploy: a7479c22b54f3d4658fb8b3fa5e87f0430b4b3e6 --- 404.html | 15 +- assets/{a1.662d9415.png => a1.DvgNELwZ.png} | Bin assets/{a10.36860678.png => a10.CPK2ZJEJ.png} | Bin assets/{a11.bbc20080.png => a11.Bq6vmveu.png} | Bin assets/{a12.da46fe54.png => a12.bStrZLWw.png} | Bin assets/{a13.b49276aa.png => a13.DRz8WTJR.png} | Bin assets/{a14.908480a6.png => a14.D56M6gMb.png} | Bin assets/{a15.9533f30d.png => a15.CtjmUhal.png} | Bin assets/{a16.2257f2d8.png => a16.BL0_sgNg.png} | Bin assets/{a17.b57c7755.png => a17.B9keXK9k.png} | Bin assets/{a18.c3a22602.png => a18.Bu92JFv5.png} | Bin assets/{a19.1eefd81d.png => a19.DZjr60Xs.png} | Bin assets/{a2.1d7d86db.png => a2.BQniQEw_.png} | Bin assets/{a20.24042237.png => a20.CesdkIR_.png} | Bin assets/{a21.2bb37c9a.png => a21.BO8sy8n4.png} | Bin assets/{a22.44ab6d75.png => a22.COjD9r-B.png} | Bin assets/{a23.191de0ca.png => a23.BxEEAckp.png} | Bin assets/{a24.d2a9c729.png => a24.BrCKYLHX.png} | Bin assets/{a25.3e24d99b.png => a25.CUB6zoiS.png} | Bin assets/{a26.2fce6332.png => a26.zvaFRs59.png} | Bin assets/{a27.dd61884c.png => a27.QkS9Cjl7.png} | Bin assets/{a3.178777a1.png => a3.DHUpjnAe.png} | Bin assets/{a31.6d3a9d85.png => a31.BiCzGFMR.png} | Bin assets/{a32.d9973307.png => a32.54sdf1AZ.png} | Bin assets/{a33.8b54ce3f.png => a33.QYBAXO71.png} | Bin assets/{a34.07f5cc75.png => a34.BBqAz_kr.png} | Bin assets/{a35.78be61d4.png => a35.B8NF_iJX.png} | Bin assets/{a36.a36765c2.png => a36.CPvsggxV.png} | Bin assets/{a37.e6740eaa.png => a37.DJRI7pv9.png} | Bin assets/{a38.999b4ffb.png => a38.BhfuTk-3.png} | Bin assets/{a39.9dac95e1.png => a39.BNtfZ4xd.png} | Bin assets/{a4.65c15963.png => a4.BtVJtyBL.png} | Bin assets/{a40.7f5ad4ea.png => a40.DTfyEQe2.png} | Bin assets/{a41.bbc5e317.png => a41.Cb6MjiUm.png} | Bin assets/{a42.de7d1da7.png => a42.Du63tHI8.png} | Bin assets/{a43.e713599d.png => a43.Cxy9Fqxr.png} | Bin assets/{a44.5c4e5e0a.png => a44.Dhcgau_f.png} | Bin assets/{a45.2c32612e.png => a45.DQgcLv5f.png} | Bin assets/{a5.01b8514f.png => a5.CamDlEuL.png} | Bin assets/{a6.67efded0.png => a6.auUigeOH.png} | Bin assets/{a7.b8de9a6c.png => a7.3_Is3HF1.png} | Bin assets/{a8.69056d9a.png => a8.CkyIulFy.png} | Bin assets/{a9.d4cc5fc0.png => a9.Dg58RrTs.png} | Bin assets/app.7da1868b.js | 1 - assets/app.D4kLJnX4.js | 1 + assets/{ar.0d8bb8f3.png => ar.Dy_5EjFU.png} | Bin assets/{b1.c1fdb506.png => b1.CSqggjTM.png} | Bin assets/{b10.52a93636.png => b10.DGHfd73s.png} | Bin assets/{b11.2e525d8d.png => b11.DKZjwgY8.png} | Bin assets/{b12.54c3189d.png => b12.BISDj2Ri.png} | Bin assets/{b13.3b3ae784.png => b13.WGr5jMeK.png} | Bin assets/{b14.662b1a1b.png => b14.BqBpvoFk.png} | Bin assets/{b15.0c5536d8.png => b15.Cd3Rj7ju.png} | Bin assets/{b16.0fbcfcb1.png => b16.BR7AHi1X.png} | Bin assets/{b17.4e7429fe.png => b17.Cn1C4e1e.png} | Bin assets/{b18.8211f293.png => b18.ElAa2UCQ.png} | Bin assets/{b19.2128d0fa.png => b19.BwC-oHOW.png} | Bin assets/{b2.519a9bf0.png => b2.BnvPQMj3.png} | Bin assets/{b20.8a62698b.png => b20.Dj-0rOwy.png} | Bin assets/{b21.dfe1e8f0.png => b21.CYRPkSXE.png} | Bin assets/{b22.13e3438c.png => b22.BH7kRZ3Z.png} | Bin assets/{b23.e293a560.png => b23.JVX-KOL7.png} | Bin assets/{b24.23cbc29a.png => b24.a2fv8lkf.png} | Bin assets/{b25.f2c2ebd7.png => b25.BJrNgkiA.png} | Bin assets/{b26.b7136167.png => b26.5bTO5HK5.png} | Bin assets/{b27.cc8f8644.png => b27.BSRz6moE.png} | Bin assets/{b28.2bf4d8b9.png => b28.WNjJaEPB.png} | Bin assets/{b29.8d301c10.png => b29.Bs69Ykqp.png} | Bin assets/{b3.42fd37a2.png => b3.DPn2dzFl.png} | Bin assets/{b30.a50bc8f3.png => b30.B96bh_Ou.png} | Bin assets/{b31.4881ca1d.png => b31.BBIAIScF.png} | Bin assets/{b32.b857654b.png => b32.8G5Xy9mr.png} | Bin assets/{b33.1125a81c.png => b33.RYxcR7vu.png} | Bin assets/{b34.2101ce9a.png => b34.Dw6MyLex.png} | Bin assets/{b35.83c5a766.png => b35.DUCPsVIG.png} | Bin assets/{b36.ea1f048c.png => b36.7aKaNaLh.png} | Bin assets/{b37.b60405a9.png => b37.B5CHAJzN.png} | Bin assets/{b38.4d73fbe3.png => b38.Pnnij22W.png} | Bin assets/{b39.c59ccabe.png => b39.ajiHDdbx.png} | Bin assets/{b4.b6d283a7.png => b4.JBQupWN9.png} | Bin assets/{b40.c1d0ee00.png => b40.B6FTkFUT.png} | Bin assets/{b41.0c6d7432.png => b41.DcCdod5l.png} | Bin assets/{b42.66cc353b.png => b42.CT1JvTLX.png} | Bin assets/{b43.a775b641.png => b43.HthhPs5o.png} | Bin assets/{b44.2d540844.png => b44.C9NeP-UC.png} | Bin assets/{b45.fe0240c6.png => b45.BWxBBH-l.png} | Bin assets/{b46.f6b9da14.png => b46.B6Ds58im.png} | Bin assets/{b5.4cd5361f.png => b5.DeuT9J-4.png} | Bin assets/{b6.36f0470d.png => b6.cZYHMwJ8.png} | Bin assets/{b7.9714bb16.png => b7.5Fkbt05C.png} | Bin assets/{b8.2eb373bf.png => b8.BXlK1Dnb.png} | Bin assets/{b9.3f01ffdc.png => b9.CaK5eLKm.png} | Bin assets/{br.bb3418b4.png => br.CyzpZwsx.png} | Bin assets/case_case1.md.3cf726ff.js | 58 ------ assets/case_case1.md.3cf726ff.lean.js | 58 ------ assets/case_case1.md.URFLodrr.js | 58 ++++++ assets/case_case1.md.URFLodrr.lean.js | 1 + assets/case_case2.md.CDLx6tKM.js | 36 ++++ assets/case_case2.md.CDLx6tKM.lean.js | 1 + assets/case_case2.md.d9673a40.js | 36 ---- assets/case_case2.md.d9673a40.lean.js | 36 ---- assets/case_case3.md.8bd8db2f.js | 1 - assets/case_case3.md.8bd8db2f.lean.js | 1 - assets/case_case3.md.Dr71EzwR.js | 1 + assets/case_case3.md.Dr71EzwR.lean.js | 1 + assets/case_case4.md.14b56d9f.js | 1 - assets/case_case4.md.14b56d9f.lean.js | 1 - assets/case_case4.md.BCt0xHGw.js | 1 + assets/case_case4.md.BCt0xHGw.lean.js | 1 + assets/case_case5.md.991f7ced.js | 1 - assets/case_case5.md.991f7ced.lean.js | 1 - assets/case_case5.md.D0hZllGZ.js | 1 + assets/case_case5.md.D0hZllGZ.lean.js | 1 + assets/case_case6.md.DBcKFtJZ.js | 1 + assets/case_case6.md.DBcKFtJZ.lean.js | 1 + assets/case_case6.md.d14d2ac7.js | 1 - assets/case_case6.md.d14d2ac7.lean.js | 1 - assets/case_case7.md.Ca88kvzN.js | 1 + assets/case_case7.md.Ca88kvzN.lean.js | 1 + assets/case_case7.md.b84f4c02.js | 1 - assets/case_case7.md.b84f4c02.lean.js | 1 - ....259f5ee0.js => case_index.md.D_IkUok9.js} | 2 +- ...lean.js => case_index.md.D_IkUok9.lean.js} | 2 +- assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js | 12 ++ assets/chunks/VPAlgoliaSearchBox.faa390b4.js | 17 -- assets/chunks/framework.70afa331.js | 2 - assets/chunks/framework.CSeR4K32.js | 18 ++ assets/chunks/theme.DJQtrHna.js | 2 + assets/chunks/theme.b9d97670.js | 7 - assets/chunks/wk7.6fe7513d.js | 1 - assets/chunks/wk7.776871bd.js | 1 - assets/chunks/wk7.Bl1-W8YX.js | 1 + assets/chunks/wk7.BpuwpIoq.js | 1 + assets/{cpu.4618bc7b.png => cpu.DedcVQ_T.png} | Bin ...aa55.js => developer_index.md.CXHgEkLk.js} | 2 +- ...js => developer_index.md.CXHgEkLk.lean.js} | 2 +- assets/developer_l10n.md.DbKLx65f.js | 1 + assets/developer_l10n.md.DbKLx65f.lean.js | 1 + assets/developer_l10n.md.f381c679.js | 1 - assets/developer_l10n.md.f381c679.lean.js | 1 - ...{disks.8065a143.png => disks.BJniy5pO.png} | Bin ...iso.a2c0c1ef.png => dlwiniso.BxXucu9m.png} | Bin ...o1.4fa2fea0.png => dlwiniso1.CQyxWlSu.png} | Bin .../{dns0.1beb9fa7.png => dns0.DDagSewr.png} | Bin ...e.js => en_developer_index.md.zTlMOyHV.js} | 2 +- ...=> en_developer_index.md.zTlMOyHV.lean.js} | 2 +- assets/en_developer_l10n.md.2567a7c2.js | 1 - assets/en_developer_l10n.md.2567a7c2.lean.js | 1 - assets/en_developer_l10n.md.CFaXJ2l2.js | 1 + assets/en_developer_l10n.md.CFaXJ2l2.lean.js | 1 + ...en_guide_block_block_docker.md.2627dfbd.js | 1 - ...ide_block_block_docker.md.2627dfbd.lean.js | 1 - ...en_guide_block_block_docker.md.Bu7zbkEq.js | 1 + ...ide_block_block_docker.md.Bu7zbkEq.lean.js | 1 + .../en_guide_block_block_incus.md.95762549.js | 1 - ...uide_block_block_incus.md.95762549.lean.js | 1 - .../en_guide_block_block_incus.md.BTs-piI_.js | 1 + ...uide_block_block_incus.md.BTs-piI_.lean.js | 1 + ..._guide_block_block_iptables.md.6506e0bc.js | 54 ------ ...e_block_block_iptables.md.6506e0bc.lean.js | 54 ------ ..._guide_block_block_iptables.md.ByV6snur.js | 54 ++++++ ...e_block_block_iptables.md.ByV6snur.lean.js | 1 + .../en_guide_block_block_lxd.md.616a5093.js | 1 - ..._guide_block_block_lxd.md.616a5093.lean.js | 1 - .../en_guide_block_block_lxd.md.BToyiHH5.js | 1 + ..._guide_block_block_lxd.md.BToyiHH5.lean.js | 1 + .../en_guide_block_block_pve.md.86088ae1.js | 3 - ..._guide_block_block_pve.md.86088ae1.lean.js | 3 - .../en_guide_block_block_pve.md.Bi62dGs9.js | 3 + ..._guide_block_block_pve.md.Bi62dGs9.lean.js | 1 + assets/en_guide_dashboard.md.04c46e68.js | 1 - assets/en_guide_dashboard.md.04c46e68.lean.js | 1 - assets/en_guide_dashboard.md.CwRb4UsX.js | 1 + assets/en_guide_dashboard.md.CwRb4UsX.lean.js | 1 + assets/en_guide_dashboardq.md.220142b4.js | 1 - .../en_guide_dashboardq.md.220142b4.lean.js | 1 - assets/en_guide_dashboardq.md.BaUPP2a8.js | 1 + .../en_guide_dashboardq.md.BaUPP2a8.lean.js | 1 + ...guide_docker_docker_android.md.BulF4nM1.js | 6 + ..._docker_docker_android.md.BulF4nM1.lean.js | 1 + ...guide_docker_docker_android.md.ffbfb237.js | 6 - ..._docker_docker_android.md.ffbfb237.lean.js | 6 - ...n_guide_docker_docker_build.md.5395d3b9.js | 24 --- ...de_docker_docker_build.md.5395d3b9.lean.js | 24 --- ...n_guide_docker_docker_build.md.DvGO9A3O.js | 24 +++ ...de_docker_docker_build.md.DvGO9A3O.lean.js | 1 + ..._guide_docker_docker_custom.md.4e05a2c3.js | 10 - ...e_docker_docker_custom.md.4e05a2c3.lean.js | 10 - ..._guide_docker_docker_custom.md.CoAvHe_n.js | 10 + ...e_docker_docker_custom.md.CoAvHe_n.lean.js | 1 + ...guide_docker_docker_install.md.2b0bb4e4.js | 1 - ..._docker_docker_install.md.2b0bb4e4.lean.js | 1 - ...guide_docker_docker_install.md.DMUsaTt3.js | 1 + ..._docker_docker_install.md.DMUsaTt3.lean.js | 1 + ...n_guide_docker_docker_macos.md.48b99172.js | 1 - ...de_docker_docker_macos.md.48b99172.lean.js | 1 - ...n_guide_docker_docker_macos.md.DItPel8U.js | 1 + ...de_docker_docker_macos.md.DItPel8U.lean.js | 1 + ...uide_docker_docker_precheck.md.BrsWou7M.js | 1 + ...docker_docker_precheck.md.BrsWou7M.lean.js | 1 + ...uide_docker_docker_precheck.md.a9b1c276.js | 1 - ...docker_docker_precheck.md.a9b1c276.lean.js | 1 - .../en_guide_docker_docker_qa.md.fed2a991.js | 1 - ...guide_docker_docker_qa.md.fed2a991.lean.js | 1 - .../en_guide_docker_docker_qa.md.q3nJoH_p.js | 1 + ...guide_docker_docker_qa.md.q3nJoH_p.lean.js | 1 + ..._guide_docker_docker_thanks.md.CLSD9Nhw.js | 1 + ...e_docker_docker_thanks.md.CLSD9Nhw.lean.js | 1 + ..._guide_docker_docker_thanks.md.d7efa635.js | 1 - ...e_docker_docker_thanks.md.d7efa635.lean.js | 1 - ...guide_docker_docker_windows.md.CDb3Bppx.js | 26 +++ ..._docker_docker_windows.md.CDb3Bppx.lean.js | 1 + ...guide_docker_docker_windows.md.aeb5b431.js | 26 --- ..._docker_docker_windows.md.aeb5b431.lean.js | 26 --- ...en_guide_incus_incus_custom.md.DUBzNIug.js | 80 ++++++++ ...ide_incus_incus_custom.md.DUBzNIug.lean.js | 1 + ...en_guide_incus_incus_custom.md.f6f0e581.js | 80 -------- ...ide_incus_incus_custom.md.f6f0e581.lean.js | 80 -------- ...de_incus_incus_extra_config.md.06d84d9b.js | 11 -- ...cus_incus_extra_config.md.06d84d9b.lean.js | 11 -- ...de_incus_incus_extra_config.md.BkutcTAl.js | 11 ++ ...cus_incus_extra_config.md.BkutcTAl.lean.js | 1 + ...n_guide_incus_incus_install.md.BgEyJdKz.js | 17 ++ ...de_incus_incus_install.md.BgEyJdKz.lean.js | 1 + ...n_guide_incus_incus_install.md.ce7c0d18.js | 17 -- ...de_incus_incus_install.md.ce7c0d18.lean.js | 17 -- .../en_guide_incus_incus_lxc.md.BxXye95l.js | 25 +++ ..._guide_incus_incus_lxc.md.BxXye95l.lean.js | 1 + .../en_guide_incus_incus_lxc.md.c5c0a6f8.js | 25 --- ..._guide_incus_incus_lxc.md.c5c0a6f8.lean.js | 25 --- ..._guide_incus_incus_precheck.md.44458de1.js | 1 - ...e_incus_incus_precheck.md.44458de1.lean.js | 1 - ..._guide_incus_incus_precheck.md.DeMpsPcV.js | 1 + ...e_incus_incus_precheck.md.DeMpsPcV.lean.js | 1 + assets/en_guide_incus_incus_qa.md.L3eCjNtY.js | 1 + ...n_guide_incus_incus_qa.md.L3eCjNtY.lean.js | 1 + assets/en_guide_incus_incus_qa.md.bea92aa8.js | 1 - ...n_guide_incus_incus_qa.md.bea92aa8.lean.js | 1 - ...en_guide_incus_incus_thanks.md.5f3fccbe.js | 1 - ...ide_incus_incus_thanks.md.5f3fccbe.lean.js | 1 - ...en_guide_incus_incus_thanks.md.CjY9f-A0.js | 1 + ...ide_incus_incus_thanks.md.CjY9f-A0.lean.js | 1 + ...n_guide_incus_incus_windows.md.7fb5eecc.js | 28 --- ...de_incus_incus_windows.md.7fb5eecc.lean.js | 28 --- ...n_guide_incus_incus_windows.md.CPQ_HdzK.js | 28 +++ ...de_incus_incus_windows.md.CPQ_HdzK.lean.js | 1 + assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.js | 80 ++++++++ ...n_guide_lxd_lxd_custom.md.-wt5FjRv.lean.js | 1 + assets/en_guide_lxd_lxd_custom.md.f8616b5f.js | 80 -------- ...n_guide_lxd_lxd_custom.md.f8616b5f.lean.js | 80 -------- ..._guide_lxd_lxd_extra_config.md.3ce9da2c.js | 16 -- ...e_lxd_lxd_extra_config.md.3ce9da2c.lean.js | 16 -- ..._guide_lxd_lxd_extra_config.md.BsivFFBx.js | 16 ++ ...e_lxd_lxd_extra_config.md.BsivFFBx.lean.js | 1 + .../en_guide_lxd_lxd_install.md.b53a57be.js | 6 - ..._guide_lxd_lxd_install.md.b53a57be.lean.js | 6 - .../en_guide_lxd_lxd_install.md.z7YfDjTq.js | 6 + ..._guide_lxd_lxd_install.md.z7YfDjTq.lean.js | 1 + assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.js | 25 --- .../en_guide_lxd_lxd_lxc.md.5c2b1e85.lean.js | 25 --- assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.js | 25 +++ .../en_guide_lxd_lxd_lxc.md.xW6rYEDm.lean.js | 1 + .../en_guide_lxd_lxd_precheck.md.995523b7.js | 1 - ...guide_lxd_lxd_precheck.md.995523b7.lean.js | 1 - .../en_guide_lxd_lxd_precheck.md.COYnNjKf.js | 1 + ...guide_lxd_lxd_precheck.md.COYnNjKf.lean.js | 1 + assets/en_guide_lxd_lxd_qa.md.7268ae8d.js | 1 - .../en_guide_lxd_lxd_qa.md.7268ae8d.lean.js | 1 - assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.js | 1 + .../en_guide_lxd_lxd_qa.md.Bs8c7UP0.lean.js | 1 + ...=> en_guide_lxd_lxd_thanks.md.CeZBLRKW.js} | 2 +- ...n_guide_lxd_lxd_thanks.md.CeZBLRKW.lean.js | 1 + assets/en_guide_lxd_lxd_thanks.md.bbb08af5.js | 1 - ...n_guide_lxd_lxd_thanks.md.bbb08af5.lean.js | 1 - .../en_guide_lxd_lxd_windows.md.586d29ea.js | 18 -- ..._guide_lxd_lxd_windows.md.586d29ea.lean.js | 18 -- .../en_guide_lxd_lxd_windows.md.CDGEBwH6.js | 18 ++ ..._guide_lxd_lxd_windows.md.CDGEBwH6.lean.js | 1 + .../en_guide_pve_images_readme.md.Dq3BR6Q6.js | 1 + ...uide_pve_images_readme.md.Dq3BR6Q6.lean.js | 1 + .../en_guide_pve_images_readme.md.f8849b0b.js | 1 - ...uide_pve_images_readme.md.f8849b0b.lean.js | 1 - .../en_guide_pve_pve_android.md.D8JpIji1.js | 1 + ..._guide_pve_pve_android.md.D8JpIji1.lean.js | 1 + .../en_guide_pve_pve_android.md.bc9044ee.js | 1 - ..._guide_pve_pve_android.md.bc9044ee.lean.js | 1 - assets/en_guide_pve_pve_custom.md.4615a36e.js | 30 --- ...n_guide_pve_pve_custom.md.4615a36e.lean.js | 30 --- assets/en_guide_pve_pve_custom.md.BNwEwNPy.js | 30 +++ ...n_guide_pve_pve_custom.md.BNwEwNPy.lean.js | 1 + .../en_guide_pve_pve_install.md.69e0d919.js | 1 - ..._guide_pve_pve_install.md.69e0d919.lean.js | 1 - .../en_guide_pve_pve_install.md.DG8IYoZ0.js | 1 + ..._guide_pve_pve_install.md.DG8IYoZ0.lean.js | 1 + assets/en_guide_pve_pve_kvm.md.97ca4d66.js | 15 -- .../en_guide_pve_pve_kvm.md.97ca4d66.lean.js | 15 -- assets/en_guide_pve_pve_kvm.md.CutjUOCm.js | 15 ++ .../en_guide_pve_pve_kvm.md.CutjUOCm.lean.js | 1 + assets/en_guide_pve_pve_lxc.md.5f264fc4.js | 12 -- .../en_guide_pve_pve_lxc.md.5f264fc4.lean.js | 12 -- assets/en_guide_pve_pve_lxc.md.DacQBeid.js | 12 ++ .../en_guide_pve_pve_lxc.md.DacQBeid.lean.js | 1 + assets/en_guide_pve_pve_macos.md.785a524c.js | 9 - ...en_guide_pve_pve_macos.md.785a524c.lean.js | 9 - assets/en_guide_pve_pve_macos.md.Cy9mzi8X.js | 9 + ...en_guide_pve_pve_macos.md.Cy9mzi8X.lean.js | 1 + .../en_guide_pve_pve_precheck.md.2c6a4e25.js | 3 - ...guide_pve_pve_precheck.md.2c6a4e25.lean.js | 3 - .../en_guide_pve_pve_precheck.md.Dc6vpMBO.js | 3 + ...guide_pve_pve_precheck.md.Dc6vpMBO.lean.js | 1 + assets/en_guide_pve_pve_qa.md.3406e13c.js | 13 -- .../en_guide_pve_pve_qa.md.3406e13c.lean.js | 13 -- assets/en_guide_pve_pve_qa.md.BYBr2UQn.js | 13 ++ .../en_guide_pve_pve_qa.md.BYBr2UQn.lean.js | 1 + assets/en_guide_pve_pve_thanks.md.Dw43XV-y.js | 1 + ...n_guide_pve_pve_thanks.md.Dw43XV-y.lean.js | 1 + assets/en_guide_pve_pve_thanks.md.dc0491f9.js | 1 - ...n_guide_pve_pve_thanks.md.dc0491f9.lean.js | 1 - .../en_guide_pve_pve_windows.md.923bbd33.js | 2 - ..._guide_pve_pve_windows.md.923bbd33.lean.js | 2 - .../en_guide_pve_pve_windows.md.vqwXYaPa.js | 2 + ..._guide_pve_pve_windows.md.vqwXYaPa.lean.js | 1 + assets/en_incomplete_bashvm.md.DWaL7zdf.js | 1 + .../en_incomplete_bashvm.md.DWaL7zdf.lean.js | 1 + assets/en_incomplete_bashvm.md.fce6926b.js | 1 - .../en_incomplete_bashvm.md.fce6926b.lean.js | 1 - assets/en_incomplete_cockpit.md.DKGXpcw0.js | 1 + .../en_incomplete_cockpit.md.DKGXpcw0.lean.js | 1 + assets/en_incomplete_cockpit.md.a60c11d2.js | 1 - .../en_incomplete_cockpit.md.a60c11d2.lean.js | 1 - assets/en_incomplete_convoy.md.ClbXbvA3.js | 1 + .../en_incomplete_convoy.md.ClbXbvA3.lean.js | 1 + assets/en_incomplete_convoy.md.ccd54afd.js | 1 - .../en_incomplete_convoy.md.ccd54afd.lean.js | 1 - ....js => en_incomplete_index.md.B8q1NrDT.js} | 2 +- ...> en_incomplete_index.md.B8q1NrDT.lean.js} | 2 +- .../en_incomplete_pterodactyl.md.CFqYcu_4.js | 1 + ...incomplete_pterodactyl.md.CFqYcu_4.lean.js | 1 + .../en_incomplete_pterodactyl.md.df0ba4ff.js | 1 - ...incomplete_pterodactyl.md.df0ba4ff.lean.js | 1 - .../en_incomplete_virtfusion.md.C7tkSFJE.js | 7 + ..._incomplete_virtfusion.md.C7tkSFJE.lean.js | 1 + .../en_incomplete_virtfusion.md.e7f03a8b.js | 7 - ..._incomplete_virtfusion.md.e7f03a8b.lean.js | 7 - ...complete_virtualizor-docker.md.449703b7.js | 1 - ...ete_virtualizor-docker.md.449703b7.lean.js | 1 - ...complete_virtualizor-docker.md.CKtWMSs2.js | 1 + ...ete_virtualizor-docker.md.CKtWMSs2.lean.js | 1 + .../en_incomplete_webvirtcloud.md.DfzbkCBK.js | 45 +++++ ...ncomplete_webvirtcloud.md.DfzbkCBK.lean.js | 1 + .../en_incomplete_webvirtcloud.md.a6e9dff8.js | 45 ----- ...ncomplete_webvirtcloud.md.a6e9dff8.lean.js | 45 ----- ...mplete_webvirtcloud_retspen.md.8ec2f567.js | 5 - ...e_webvirtcloud_retspen.md.8ec2f567.lean.js | 5 - ...mplete_webvirtcloud_retspen.md.CjZPDsE1.js | 5 + ...e_webvirtcloud_retspen.md.CjZPDsE1.lean.js | 1 + .../en_incomplete_webvirtmgr.md.611aa9ab.js | 3 - ..._incomplete_webvirtmgr.md.611aa9ab.lean.js | 3 - .../en_incomplete_webvirtmgr.md.8Ub32E-h.js | 3 + ..._incomplete_webvirtmgr.md.8Ub32E-h.lean.js | 1 + ...md.83e2fa26.js => en_index.md.DhJzLyfV.js} | 2 +- ...6.lean.js => en_index.md.DhJzLyfV.lean.js} | 2 +- ...inish.0c3eac87.png => finish.Cf6DgPp1.png} | Bin ...eral.ea03923c.png => general.BkOp2iK4.png} | Bin .../{gic1.42bfd260.png => gic1.XkdPXihx.png} | Bin .../{gic2.ff78c941.png => gic2.s5VB7-xp.png} | Bin .../{gic3.4a04cf3d.png => gic3.2zLznATL.png} | Bin .../{gic4.e2343160.png => gic4.CX3t8C19.png} | Bin .../{gic5.54522dff.png => gic5.pjwHWuhn.png} | Bin .../{gic6.97561122.png => gic6.BnmyenL0.png} | Bin .../{gic7.a8679083.png => gic7.ZYHWzF5W.png} | Bin .../{gic8.fe7d0b3c.png => gic8.BwCbmRgC.png} | Bin .../{gic9.4cdf4daa.png => gic9.62-9wTBo.png} | Bin .../guide_block_block_docker.md.5830a230.js | 1 - ...ide_block_block_docker.md.5830a230.lean.js | 1 - .../guide_block_block_docker.md.C-tufkRV.js | 1 + ...ide_block_block_docker.md.C-tufkRV.lean.js | 1 + assets/guide_block_block_incus.md.9da06b17.js | 1 - ...uide_block_block_incus.md.9da06b17.lean.js | 1 - assets/guide_block_block_incus.md.D3fB2bDD.js | 1 + ...uide_block_block_incus.md.D3fB2bDD.lean.js | 1 + .../guide_block_block_iptables.md.56fd36c5.js | 54 ------ ...e_block_block_iptables.md.56fd36c5.lean.js | 54 ------ .../guide_block_block_iptables.md.DkS3brgv.js | 54 ++++++ ...e_block_block_iptables.md.DkS3brgv.lean.js | 1 + assets/guide_block_block_lxd.md.BrbV-k4o.js | 1 + .../guide_block_block_lxd.md.BrbV-k4o.lean.js | 1 + assets/guide_block_block_lxd.md.cf1b102e.js | 1 - .../guide_block_block_lxd.md.cf1b102e.lean.js | 1 - assets/guide_block_block_pve.md.0b046fe8.js | 4 - .../guide_block_block_pve.md.0b046fe8.lean.js | 4 - assets/guide_block_block_pve.md.BntEIKAB.js | 4 + .../guide_block_block_pve.md.BntEIKAB.lean.js | 1 + assets/guide_dashboard.md.7c9eeb09.js | 1 - assets/guide_dashboard.md.7c9eeb09.lean.js | 1 - assets/guide_dashboard.md.D2bjCnlL.js | 1 + assets/guide_dashboard.md.D2bjCnlL.lean.js | 1 + assets/guide_dashboardq.md.02164389.js | 1 - assets/guide_dashboardq.md.02164389.lean.js | 1 - assets/guide_dashboardq.md.DGJ9X51L.js | 1 + assets/guide_dashboardq.md.DGJ9X51L.lean.js | 1 + ...guide_docker_docker_android.md.DyBMNwLg.js | 6 + ..._docker_docker_android.md.DyBMNwLg.lean.js | 1 + ...guide_docker_docker_android.md.c556d7ea.js | 6 - ..._docker_docker_android.md.c556d7ea.lean.js | 6 - .../guide_docker_docker_build.md.DoAlFeWZ.js | 24 +++ ...de_docker_docker_build.md.DoAlFeWZ.lean.js | 1 + .../guide_docker_docker_build.md.d0d61806.js | 24 --- ...de_docker_docker_build.md.d0d61806.lean.js | 24 --- .../guide_docker_docker_custom.md.01bd0eed.js | 11 -- ...e_docker_docker_custom.md.01bd0eed.lean.js | 11 -- .../guide_docker_docker_custom.md.uaKETGnt.js | 11 ++ ...e_docker_docker_custom.md.uaKETGnt.lean.js | 1 + ...guide_docker_docker_install.md.69dee249.js | 1 - ..._docker_docker_install.md.69dee249.lean.js | 1 - ...guide_docker_docker_install.md.DkBio7r4.js | 1 + ..._docker_docker_install.md.DkBio7r4.lean.js | 1 + .../guide_docker_docker_macos.md.7497eb24.js | 1 - ...de_docker_docker_macos.md.7497eb24.lean.js | 1 - .../guide_docker_docker_macos.md.B-ddHhbN.js | 1 + ...de_docker_docker_macos.md.B-ddHhbN.lean.js | 1 + ...uide_docker_docker_precheck.md.78609506.js | 1 - ...docker_docker_precheck.md.78609506.lean.js | 1 - ...uide_docker_docker_precheck.md.Dgik3VYv.js | 1 + ...docker_docker_precheck.md.Dgik3VYv.lean.js | 1 + assets/guide_docker_docker_qa.md.94f80b81.js | 1 - ...guide_docker_docker_qa.md.94f80b81.lean.js | 1 - assets/guide_docker_docker_qa.md.BAZeywiq.js | 1 + ...guide_docker_docker_qa.md.BAZeywiq.lean.js | 1 + .../guide_docker_docker_thanks.md.4049eaf0.js | 1 - ...e_docker_docker_thanks.md.4049eaf0.lean.js | 1 - .../guide_docker_docker_thanks.md.CMHMSDTy.js | 1 + ...e_docker_docker_thanks.md.CMHMSDTy.lean.js | 1 + ...guide_docker_docker_windows.md.9011d893.js | 26 --- ..._docker_docker_windows.md.9011d893.lean.js | 26 --- ...guide_docker_docker_windows.md.BAGQZpoB.js | 26 +++ ..._docker_docker_windows.md.BAGQZpoB.lean.js | 1 + .../guide_incus_incus_custom.md.Bm8HnEPC.js | 80 ++++++++ ...ide_incus_incus_custom.md.Bm8HnEPC.lean.js | 1 + .../guide_incus_incus_custom.md.b1aba773.js | 80 -------- ...ide_incus_incus_custom.md.b1aba773.lean.js | 80 -------- ...de_incus_incus_extra_config.md.91dfbfa5.js | 11 -- ...cus_incus_extra_config.md.91dfbfa5.lean.js | 11 -- ...de_incus_incus_extra_config.md.AJ5M0HDo.js | 11 ++ ...cus_incus_extra_config.md.AJ5M0HDo.lean.js | 1 + .../guide_incus_incus_install.md.BmXHRJpC.js | 17 ++ ...de_incus_incus_install.md.BmXHRJpC.lean.js | 1 + .../guide_incus_incus_install.md.ba70a2a0.js | 17 -- ...de_incus_incus_install.md.ba70a2a0.lean.js | 17 -- assets/guide_incus_incus_lxc.md.3de28e6b.js | 25 --- .../guide_incus_incus_lxc.md.3de28e6b.lean.js | 25 --- assets/guide_incus_incus_lxc.md.CcPIDp5T.js | 25 +++ .../guide_incus_incus_lxc.md.CcPIDp5T.lean.js | 1 + .../guide_incus_incus_precheck.md.6bf5b424.js | 1 - ...e_incus_incus_precheck.md.6bf5b424.lean.js | 1 - .../guide_incus_incus_precheck.md.DTFAD1HQ.js | 1 + ...e_incus_incus_precheck.md.DTFAD1HQ.lean.js | 1 + assets/guide_incus_incus_qa.md.780b508f.js | 1 - .../guide_incus_incus_qa.md.780b508f.lean.js | 1 - assets/guide_incus_incus_qa.md.D2Pi0dJG.js | 1 + .../guide_incus_incus_qa.md.D2Pi0dJG.lean.js | 1 + ...ide_incus_incus_thanks.md.4ec3421d.lean.js | 1 - .../guide_incus_incus_thanks.md.DJw_BEEC.js | 1 + ...ide_incus_incus_thanks.md.DJw_BEEC.lean.js | 1 + .../guide_incus_incus_windows.md.5ba7b2ce.js | 28 --- ...de_incus_incus_windows.md.5ba7b2ce.lean.js | 28 --- .../guide_incus_incus_windows.md.CFcsS3lD.js | 28 +++ ...de_incus_incus_windows.md.CFcsS3lD.lean.js | 1 + assets/guide_lxd_lxd_custom.md.20323fda.js | 80 -------- .../guide_lxd_lxd_custom.md.20323fda.lean.js | 80 -------- assets/guide_lxd_lxd_custom.md.gEdxHFHM.js | 80 ++++++++ .../guide_lxd_lxd_custom.md.gEdxHFHM.lean.js | 1 + .../guide_lxd_lxd_extra_config.md.DhbmRlmf.js | 16 ++ ...e_lxd_lxd_extra_config.md.DhbmRlmf.lean.js | 1 + .../guide_lxd_lxd_extra_config.md.c1ea1bc8.js | 16 -- ...e_lxd_lxd_extra_config.md.c1ea1bc8.lean.js | 16 -- assets/guide_lxd_lxd_install.md.8dc77da5.js | 6 - .../guide_lxd_lxd_install.md.8dc77da5.lean.js | 6 - assets/guide_lxd_lxd_install.md.D4zH3hWU.js | 6 + .../guide_lxd_lxd_install.md.D4zH3hWU.lean.js | 1 + assets/guide_lxd_lxd_lxc.md.728ada33.js | 25 --- assets/guide_lxd_lxd_lxc.md.728ada33.lean.js | 25 --- assets/guide_lxd_lxd_lxc.md.PKqgxyhI.js | 25 +++ assets/guide_lxd_lxd_lxc.md.PKqgxyhI.lean.js | 1 + assets/guide_lxd_lxd_precheck.md.42adf95c.js | 1 - ...guide_lxd_lxd_precheck.md.42adf95c.lean.js | 1 - assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.js | 1 + ...guide_lxd_lxd_precheck.md.BDmkuKzJ.lean.js | 1 + assets/guide_lxd_lxd_qa.md.44833073.js | 2 - assets/guide_lxd_lxd_qa.md.44833073.lean.js | 2 - assets/guide_lxd_lxd_qa.md.C4FXk4za.js | 2 + assets/guide_lxd_lxd_qa.md.C4FXk4za.lean.js | 1 + assets/guide_lxd_lxd_thanks.md.6aebeab6.js | 1 - .../guide_lxd_lxd_thanks.md.6aebeab6.lean.js | 1 - assets/guide_lxd_lxd_thanks.md.oRZKHNsx.js | 1 + .../guide_lxd_lxd_thanks.md.oRZKHNsx.lean.js | 1 + assets/guide_lxd_lxd_windows.md.9b33f709.js | 18 -- .../guide_lxd_lxd_windows.md.9b33f709.lean.js | 18 -- assets/guide_lxd_lxd_windows.md.CpTtBXvV.js | 18 ++ .../guide_lxd_lxd_windows.md.CpTtBXvV.lean.js | 1 + assets/guide_pve_images_readme.md.ZJUoqm_K.js | 1 + ...uide_pve_images_readme.md.ZJUoqm_K.lean.js | 1 + assets/guide_pve_images_readme.md.e91db2b4.js | 1 - ...uide_pve_images_readme.md.e91db2b4.lean.js | 1 - assets/guide_pve_pve_android.md.5728ca62.js | 1 - .../guide_pve_pve_android.md.5728ca62.lean.js | 1 - assets/guide_pve_pve_android.md.DauuQgmC.js | 1 + .../guide_pve_pve_android.md.DauuQgmC.lean.js | 1 + assets/guide_pve_pve_custom.md.0uRKiuWM.js | 30 +++ .../guide_pve_pve_custom.md.0uRKiuWM.lean.js | 1 + assets/guide_pve_pve_custom.md.c31784f7.js | 30 --- .../guide_pve_pve_custom.md.c31784f7.lean.js | 30 --- assets/guide_pve_pve_install.md.CdRZOjQC.js | 1 + .../guide_pve_pve_install.md.CdRZOjQC.lean.js | 1 + assets/guide_pve_pve_install.md.b9ed6cd8.js | 1 - .../guide_pve_pve_install.md.b9ed6cd8.lean.js | 1 - assets/guide_pve_pve_kvm.md.43713910.js | 15 -- assets/guide_pve_pve_kvm.md.43713910.lean.js | 15 -- assets/guide_pve_pve_kvm.md.DiXxjdva.js | 15 ++ assets/guide_pve_pve_kvm.md.DiXxjdva.lean.js | 1 + assets/guide_pve_pve_lxc.md.704d4792.js | 12 -- assets/guide_pve_pve_lxc.md.704d4792.lean.js | 12 -- assets/guide_pve_pve_lxc.md.D_RYunJp.js | 12 ++ assets/guide_pve_pve_lxc.md.D_RYunJp.lean.js | 1 + assets/guide_pve_pve_macos.md.21762f54.js | 9 - .../guide_pve_pve_macos.md.21762f54.lean.js | 9 - assets/guide_pve_pve_macos.md.CRq8lCuz.js | 9 + .../guide_pve_pve_macos.md.CRq8lCuz.lean.js | 1 + assets/guide_pve_pve_precheck.md.2c856c99.js | 3 - ...guide_pve_pve_precheck.md.2c856c99.lean.js | 3 - assets/guide_pve_pve_precheck.md.Bwa9qWce.js | 3 + ...guide_pve_pve_precheck.md.Bwa9qWce.lean.js | 1 + assets/guide_pve_pve_qa.md.76a49097.js | 13 -- assets/guide_pve_pve_qa.md.76a49097.lean.js | 13 -- assets/guide_pve_pve_qa.md.KEIUXkXN.js | 13 ++ assets/guide_pve_pve_qa.md.KEIUXkXN.lean.js | 1 + assets/guide_pve_pve_thanks.md.3bbf24dc.js | 1 - .../guide_pve_pve_thanks.md.3bbf24dc.lean.js | 1 - assets/guide_pve_pve_thanks.md.DqgEZrWa.js | 1 + .../guide_pve_pve_thanks.md.DqgEZrWa.lean.js | 1 + assets/guide_pve_pve_windows.md.37289db4.js | 2 - .../guide_pve_pve_windows.md.37289db4.lean.js | 2 - assets/guide_pve_pve_windows.md.CLu8AekJ.js | 2 + .../guide_pve_pve_windows.md.CLu8AekJ.lean.js | 1 + assets/incomplete_bashvm.md.B5fMrqJh.js | 1 + assets/incomplete_bashvm.md.B5fMrqJh.lean.js | 1 + assets/incomplete_bashvm.md.e680b5ae.js | 1 - assets/incomplete_bashvm.md.e680b5ae.lean.js | 1 - assets/incomplete_cockpit.md.77e4fe67.js | 1 - assets/incomplete_cockpit.md.77e4fe67.lean.js | 1 - assets/incomplete_cockpit.md.HGnaxkEA.js | 1 + assets/incomplete_cockpit.md.HGnaxkEA.lean.js | 1 + assets/incomplete_convoy.md.CxPU1hOM.js | 1 + assets/incomplete_convoy.md.CxPU1hOM.lean.js | 1 + assets/incomplete_convoy.md.f7a4bd52.js | 1 - assets/incomplete_convoy.md.f7a4bd52.lean.js | 1 - ...f0c.js => incomplete_index.md.CYVk98K2.js} | 2 +- ...s => incomplete_index.md.CYVk98K2.lean.js} | 2 +- assets/incomplete_pterodactyl.md.16ac57df.js | 1 - ...incomplete_pterodactyl.md.16ac57df.lean.js | 1 - assets/incomplete_pterodactyl.md.ywtPLv_5.js | 1 + ...incomplete_pterodactyl.md.ywtPLv_5.lean.js | 1 + assets/incomplete_virtfusion.md.DnaD-J8U.js | 7 + .../incomplete_virtfusion.md.DnaD-J8U.lean.js | 1 + assets/incomplete_virtfusion.md.a22bdacd.js | 7 - .../incomplete_virtfusion.md.a22bdacd.lean.js | 7 - ...complete_virtualizor-docker.md.BgClRxGW.js | 1 + ...ete_virtualizor-docker.md.BgClRxGW.lean.js | 1 + ...complete_virtualizor-docker.md.a05fb0f7.js | 1 - ...ete_virtualizor-docker.md.a05fb0f7.lean.js | 1 - assets/incomplete_webvirtcloud.md.2369e889.js | 48 ----- ...ncomplete_webvirtcloud.md.2369e889.lean.js | 48 ----- assets/incomplete_webvirtcloud.md.4rNDyChD.js | 48 +++++ ...ncomplete_webvirtcloud.md.4rNDyChD.lean.js | 1 + ...mplete_webvirtcloud_retspen.md.8469ad25.js | 7 - ...e_webvirtcloud_retspen.md.8469ad25.lean.js | 7 - ...mplete_webvirtcloud_retspen.md.BzOOyV6B.js | 7 + ...e_webvirtcloud_retspen.md.BzOOyV6B.lean.js | 1 + assets/incomplete_webvirtmgr.md.d2161404.js | 5 - .../incomplete_webvirtmgr.md.d2161404.lean.js | 5 - assets/incomplete_webvirtmgr.md.y6DQ_-c0.js | 5 + .../incomplete_webvirtmgr.md.y6DQ_-c0.lean.js | 1 + ...ex.md.33ff85ee.js => index.md.BVw2CyLu.js} | 2 +- ...85ee.lean.js => index.md.BVw2CyLu.lean.js} | 2 +- .../inter-italic-cyrillic-ext.33bd5a8e.woff2 | Bin 28332 -> 0 bytes .../inter-italic-cyrillic-ext.r48I6akx.woff2 | Bin 0 -> 43112 bytes assets/inter-italic-cyrillic.By2_1cv3.woff2 | Bin 0 -> 31300 bytes assets/inter-italic-cyrillic.ea42a392.woff2 | Bin 17824 -> 0 bytes assets/inter-italic-greek-ext.1u6EdAuj.woff2 | Bin 0 -> 17404 bytes assets/inter-italic-greek-ext.4fbe9427.woff2 | Bin 12188 -> 0 bytes assets/inter-italic-greek.8f4463c4.woff2 | Bin 23264 -> 0 bytes assets/inter-italic-greek.DJ8dCoTZ.woff2 | Bin 0 -> 32564 bytes assets/inter-italic-latin-ext.CN1xVJS-.woff2 | Bin 0 -> 120840 bytes assets/inter-italic-latin-ext.bd8920cc.woff2 | Bin 63552 -> 0 bytes assets/inter-italic-latin.C2AdPX0b.woff2 | Bin 0 -> 74784 bytes assets/inter-italic-latin.bd3b6f56.woff2 | Bin 46048 -> 0 bytes assets/inter-italic-vietnamese.6ce511fb.woff2 | Bin 8784 -> 0 bytes assets/inter-italic-vietnamese.BSbpV94h.woff2 | Bin 0 -> 14884 bytes .../inter-roman-cyrillic-ext.BBPuwvHQ.woff2 | Bin 0 -> 40488 bytes .../inter-roman-cyrillic-ext.e75737ce.woff2 | Bin 26600 -> 0 bytes assets/inter-roman-cyrillic.5f2c6c8c.woff2 | Bin 16780 -> 0 bytes assets/inter-roman-cyrillic.C5lxZ8CY.woff2 | Bin 0 -> 29164 bytes assets/inter-roman-greek-ext.CqjqNYQ-.woff2 | Bin 0 -> 16272 bytes assets/inter-roman-greek-ext.ab0619bc.woff2 | Bin 11808 -> 0 bytes assets/inter-roman-greek.BBVDIX6e.woff2 | Bin 0 -> 29920 bytes assets/inter-roman-greek.d5a6d92a.woff2 | Bin 21776 -> 0 bytes assets/inter-roman-latin-ext.0030eebd.woff2 | Bin 59608 -> 0 bytes assets/inter-roman-latin-ext.4ZJIpNVo.woff2 | Bin 0 -> 110160 bytes assets/inter-roman-latin.2ed14f66.woff2 | Bin 42464 -> 0 bytes assets/inter-roman-latin.Di8DUHzh.woff2 | Bin 0 -> 67792 bytes assets/inter-roman-vietnamese.14ce25a6.woff2 | Bin 8492 -> 0 bytes assets/inter-roman-vietnamese.BjW4sHH5.woff2 | Bin 0 -> 14072 bytes assets/{kvm.d81063e5.png => kvm.CI48mv3H.png} | Bin ...ower1.28498396.png => lower1.DFw6c1iw.png} | Bin ...ower2.e782a20a.png => lower2.SPGPKJ4N.png} | Bin .../{lxd1.78537e30.png => lxd1.CbGLa5s4.png} | Bin ...{lxd10.a25a745c.png => lxd10.BjQ0l1K7.png} | Bin ...{lxd11.b83f953c.png => lxd11.D6E5sVW2.png} | Bin ...{lxd12.0da335dd.png => lxd12.B9udKIzn.png} | Bin ...{lxd13.308fe0de.png => lxd13.Dwv7xBpz.png} | Bin ...{lxd14.8dbfdcd6.png => lxd14.Whdz6cP-.png} | Bin ...{lxd15.70114933.png => lxd15.BjW7LbDr.png} | Bin ...{lxd16.a595fa36.png => lxd16.CgeIdYJ2.png} | Bin ...{lxd17.d7ea65d8.png => lxd17.CWPY1pea.png} | Bin ...{lxd18.d6225daa.png => lxd18.DqnpcYcL.png} | Bin ...{lxd19.69674669.png => lxd19.B9_MB265.png} | Bin .../{lxd2.da10b5ec.png => lxd2.C4eWfnaM.png} | Bin ...{lxd20.179fc6e1.png => lxd20.rK3P3TT8.png} | Bin ...{lxd21.48123d6a.png => lxd21.w-R0l00Y.png} | Bin ...{lxd22.4386597e.png => lxd22.45M-VX6J.png} | Bin ...{lxd23.c26427e3.png => lxd23.CLaVW0qk.png} | Bin .../{lxd3.917f56de.png => lxd3.tQBNiKQo.png} | Bin .../{lxd4.83a1a121.png => lxd4.CSfRHLxz.png} | Bin .../{lxd5.4ebc1444.png => lxd5.WUJi0qzd.png} | Bin .../{lxd6.572825bf.png => lxd6.Cnds779U.png} | Bin .../{lxd7.b73982c7.png => lxd7.EJ0s1ls2.png} | Bin .../{lxd8.9fcc21e5.png => lxd8.DAOueoww.png} | Bin .../{lxd9.00250a32.png => lxd9.Dgmw4lpJ.png} | Bin ...{lxdd0.b1d6b8bc.png => lxdd0.QoEngFSd.png} | Bin ...{lxdd1.433ff357.png => lxdd1.CVTAIewh.png} | Bin ...{lxdd2.6a93138a.png => lxdd2.C_mYE7sL.png} | Bin ...{lxdd3.f56cf598.png => lxdd3.DZ2Na5-t.png} | Bin ...{lxdd4.28d80b71.png => lxdd4.CO1I1FPh.png} | Bin .../{mac0.935d53f3.png => mac0.CofQ9vw_.png} | Bin ...{mac00.4296be7b.png => mac00.DelKhhmr.png} | Bin .../{mac1.3307e401.png => mac1.D7yJtJrl.png} | Bin ...{mac10.e9c284db.png => mac10.CZg7Yifb.png} | Bin ...{mac11.a7587e0e.png => mac11.P11nsmhn.png} | Bin ...{mac12.06b051d3.png => mac12.DHTBO7ih.png} | Bin ...{mac13.7d4e3199.png => mac13.DDrsH3zK.png} | Bin ...{mac14.39a58b6a.png => mac14.dLHoMtJy.png} | Bin ...{mac15.f151793c.png => mac15.vkr7IxY1.png} | Bin ...{mac16.eae177db.png => mac16.CeB_3pKz.png} | Bin ...{mac17.be61913a.png => mac17.qkqeaTbW.png} | Bin ...{mac18.f9454618.png => mac18.ChbyoMxq.png} | Bin ...{mac19.845f5510.png => mac19.C_d085-7.png} | Bin .../{mac2.da6ce0bc.png => mac2.du7V_m90.png} | Bin ...{mac20.49a5800c.png => mac20.DsWyqQaw.png} | Bin ...{mac21.2c30b60f.png => mac21.XZ5wILhH.png} | Bin .../{mac3.76a50b9f.png => mac3.BCWQuf_Q.png} | Bin .../{mac4.c341ba50.png => mac4.B0L5oLF9.png} | Bin .../{mac5.39e1c9a4.png => mac5.QrcmrZyS.png} | Bin .../{mac6.1cc0462b.png => mac6.CEnQahaC.png} | Bin .../{mac7.181275ae.png => mac7.Cq44sm3y.png} | Bin .../{mac8.dd556f02.png => mac8.CfhgXZ8s.png} | Bin .../{mac9.c5d88eba.png => mac9.DIA9P3VH.png} | Bin ...emory.c4992870.png => memory.CH7Gxf76.png} | Bin .../{net1.4f166207.png => net1.CUyp8ayS.png} | Bin .../{net2.e2773ada.png => net2.BP2m5XnQ.png} | Bin .../{net3.40e8a226.png => net3.BJFg7Me5.png} | Bin .../{net4.a81e777c.png => net4.CANZtcPE.png} | Bin ...work.48037353.png => network.DPXM5W42.png} | Bin ...odisk.5ec86f3b.png => nodisk.CH47I8Tu.png} | Bin ...isk1.671c1309.png => nodisk1.gZ09o2py.png} | Bin ...isk2.ff20bb76.png => nodisk2.Do6XEKMW.png} | Bin ...isk3.71534a11.png => nodisk3.1vBQc75S.png} | Bin ...isk4.b08d75e3.png => nodisk4.CJjHGgtp.png} | Bin ...kg.30da8d76.png => onlinepkg.-C5qKOrj.png} | Bin assets/{os.b2be1a5c.png => os.CX7bMEp5.png} | Bin ..._1.0f7e84f0.png => pve_kvm_1.BEDy-Dxt.png} | Bin ..._2.cefb9578.png => pve_kvm_2.C98l0GO8.png} | Bin ..._3.1d307586.png => pve_kvm_3.DzuyyWMo.png} | Bin ...{start.3aebbfd4.png => start.vjgB4hml.png} | Bin assets/style.DFTx90Kk.css | 1 + assets/style.e150f059.css | 1 - ...ystem.8e69987e.png => system.C_AmkiPg.png} | Bin .../{vcr1.30d933ab.jpg => vcr1.NRLOOynQ.jpg} | Bin ...{vcr10.548c566e.jpg => vcr10.D8t6cQ5v.jpg} | Bin ...{vcr11.58ce8ace.jpg => vcr11.Cz1VMbIx.jpg} | Bin ...{vcr12.3aa69b2a.jpg => vcr12.BNQe5j_u.jpg} | Bin ...{vcr13.fcbcc557.jpg => vcr13.JV3PfcCZ.jpg} | Bin ...{vcr14.7009c833.jpg => vcr14.Cjyr65Qp.jpg} | Bin .../{vcr2.9b30a319.jpg => vcr2.DC9j-Ib5.jpg} | Bin .../{vcr3.0aa5a564.jpg => vcr3.Ea5Km6nQ.jpg} | Bin .../{vcr4.18a1487e.jpg => vcr4.B9DOiqQ8.jpg} | Bin .../{vcr5.97deb479.jpg => vcr5.BajXu8XE.jpg} | Bin .../{vcr6.e706123b.jpg => vcr6.CxN-b1o3.jpg} | Bin .../{vcr7.43c60335.jpg => vcr7.D4aYKhIW.jpg} | Bin .../{vcr8.1bf1f353.jpg => vcr8.ByRFpMlF.jpg} | Bin .../{vcr9.b5afa4b4.jpg => vcr9.B4apCqgi.jpg} | Bin ...irtio.b42d8275.png => virtio.CUVhk14O.png} | Bin ...echat.e3b2e06e.jpg => wechat.BhfskdFa.jpg} | Bin .../{win1.7d3fc058.png => win1.BYIcp55m.png} | Bin .../{win1.c8d28bad.png => win1.CJKAoRm5.png} | Bin .../{win2.72bb0e48.jpg => win2.BNn7RQzT.jpg} | Bin .../{win3.442eb15f.jpg => win3.BgsODJcQ.jpg} | Bin .../{win4.75bd03c1.jpg => win4.DwKt_Ood.jpg} | Bin .../{win5.58c1b996.jpg => win5.BSQ3T_9y.jpg} | Bin .../{win5.cacd68cb.jpg => win5.C8qmMo1u.jpg} | Bin .../{win6.f4215c61.jpg => win6.B-575Zc1.jpg} | Bin .../{win6.19e58640.jpg => win6.Cx0KdzQb.jpg} | Bin .../{win7.8f856089.jpg => win7.CI43Ul0V.jpg} | Bin .../{win7.854d0e0a.jpg => win7.xhBfJRvu.jpg} | Bin ...{wincf.76927350.jpg => wincf.B_Jc2M1G.jpg} | Bin ...{wintj.56bef513.jpg => wintj.tP8uDOfH.jpg} | Bin assets/{wk1.7d9f24d7.png => wk1.BGnwsbrE.png} | Bin assets/{wk2.2e88d91a.png => wk2.BasdNK2d.png} | Bin assets/{wk3.975bc38e.png => wk3.CWstwLHH.png} | Bin assets/{wk4.004be17f.png => wk4.K5XvE6uQ.png} | Bin assets/{wk5.6cdba880.png => wk5.BEJ5BAWW.png} | Bin assets/{wk6.667c5c95.png => wk6.D9MKwk3w.png} | Bin assets/{wk7.38e3cd7d.png => wk7.B0gH-0gL.png} | Bin assets/{wv1.5ac4a026.png => wv1.8ARiSJ9x.png} | Bin case/case1.html | 135 ++++++------- case/case2.html | 91 ++++----- case/case3.html | 21 +- case/case4.html | 21 +- case/case5.html | 21 +- case/case6.html | 21 +- case/case7.html | 21 +- case/index.html | 21 +- developer/index.html | 21 +- developer/l10n.html | 23 ++- en/developer/index.html | 21 +- en/developer/l10n.html | 23 ++- en/guide/block/block_docker.html | 21 +- en/guide/block/block_incus.html | 21 +- en/guide/block/block_iptables.html | 127 +++++++------ en/guide/block/block_lxd.html | 21 +- en/guide/block/block_pve.html | 25 +-- en/guide/dashboard.html | 23 ++- en/guide/dashboardq.html | 23 ++- en/guide/docker/docker_android.html | 31 +-- en/guide/docker/docker_build.html | 67 +++---- en/guide/docker/docker_custom.html | 39 ++-- en/guide/docker/docker_install.html | 21 +- en/guide/docker/docker_macos.html | 21 +- en/guide/docker/docker_precheck.html | 21 +- en/guide/docker/docker_qa.html | 21 +- en/guide/docker/docker_thanks.html | 23 ++- en/guide/docker/docker_windows.html | 71 +++---- en/guide/incus/incus_custom.html | 175 ++++++++--------- en/guide/incus/incus_extra_config.html | 41 ++-- en/guide/incus/incus_install.html | 53 +++--- en/guide/incus/incus_lxc.html | 69 +++---- en/guide/incus/incus_precheck.html | 21 +- en/guide/incus/incus_qa.html | 23 ++- en/guide/incus/incus_thanks.html | 23 ++- en/guide/incus/incus_windows.html | 69 +++---- en/guide/lxd/lxd_custom.html | 175 ++++++++--------- en/guide/lxd/lxd_extra_config.html | 51 ++--- en/guide/lxd/lxd_install.html | 33 ++-- en/guide/lxd/lxd_lxc.html | 69 +++---- en/guide/lxd/lxd_precheck.html | 21 +- en/guide/lxd/lxd_qa.html | 25 +-- en/guide/lxd/lxd_thanks.html | 23 ++- en/guide/lxd/lxd_windows.html | 55 +++--- en/guide/pve/images/readme.html | 23 ++- en/guide/pve/pve_android.html | 21 +- en/guide/pve/pve_custom.html | 79 ++++---- en/guide/pve/pve_install.html | 21 +- en/guide/pve/pve_kvm.html | 49 ++--- en/guide/pve/pve_lxc.html | 43 +++-- en/guide/pve/pve_macos.html | 39 ++-- en/guide/pve/pve_precheck.html | 25 +-- en/guide/pve/pve_qa.html | 45 +++-- en/guide/pve/pve_thanks.html | 23 ++- en/guide/pve/pve_windows.html | 25 +-- en/incomplete/bashvm.html | 23 ++- en/incomplete/cockpit.html | 23 ++- en/incomplete/convoy.html | 23 ++- en/incomplete/index.html | 21 +- en/incomplete/pterodactyl.html | 23 ++- en/incomplete/virtfusion.html | 35 ++-- en/incomplete/virtualizor-docker.html | 23 ++- en/incomplete/webvirtcloud.html | 109 +++++------ en/incomplete/webvirtcloud_retspen.html | 31 +-- en/incomplete/webvirtmgr.html | 27 +-- en/index.html | 21 +- guide/block/block_docker.html | 21 +- guide/block/block_incus.html | 21 +- guide/block/block_iptables.html | 127 +++++++------ guide/block/block_lxd.html | 21 +- guide/block/block_pve.html | 25 +-- guide/dashboard.html | 23 ++- guide/dashboardq.html | 23 ++- guide/docker/docker_android.html | 31 +-- guide/docker/docker_build.html | 67 +++---- guide/docker/docker_custom.html | 41 ++-- guide/docker/docker_install.html | 21 +- guide/docker/docker_macos.html | 21 +- guide/docker/docker_precheck.html | 21 +- guide/docker/docker_qa.html | 21 +- guide/docker/docker_thanks.html | 23 ++- guide/docker/docker_windows.html | 71 +++---- guide/incus/incus_custom.html | 179 +++++++++--------- guide/incus/incus_extra_config.html | 41 ++-- guide/incus/incus_install.html | 53 +++--- guide/incus/incus_lxc.html | 69 +++---- guide/incus/incus_precheck.html | 21 +- guide/incus/incus_qa.html | 21 +- guide/incus/incus_thanks.html | 23 ++- guide/incus/incus_windows.html | 69 +++---- guide/lxd/lxd_custom.html | 179 +++++++++--------- guide/lxd/lxd_extra_config.html | 51 ++--- guide/lxd/lxd_install.html | 33 ++-- guide/lxd/lxd_lxc.html | 69 +++---- guide/lxd/lxd_precheck.html | 21 +- guide/lxd/lxd_qa.html | 23 ++- guide/lxd/lxd_thanks.html | 23 ++- guide/lxd/lxd_windows.html | 55 +++--- guide/pve/images/readme.html | 23 ++- guide/pve/pve_android.html | 21 +- guide/pve/pve_custom.html | 79 ++++---- guide/pve/pve_install.html | 21 +- guide/pve/pve_kvm.html | 49 ++--- guide/pve/pve_lxc.html | 43 +++-- guide/pve/pve_macos.html | 39 ++-- guide/pve/pve_precheck.html | 25 +-- guide/pve/pve_qa.html | 45 +++-- guide/pve/pve_thanks.html | 23 ++- guide/pve/pve_windows.html | 25 +-- hashmap.json | 2 +- incomplete/bashvm.html | 23 ++- incomplete/cockpit.html | 23 ++- incomplete/convoy.html | 23 ++- incomplete/index.html | 21 +- incomplete/pterodactyl.html | 23 ++- incomplete/virtfusion.html | 35 ++-- incomplete/virtualizor-docker.html | 23 ++- incomplete/webvirtcloud.html | 115 +++++------ incomplete/webvirtcloud_retspen.html | 35 ++-- incomplete/webvirtmgr.html | 31 +-- index.html | 21 +- sitemap.xml | 2 +- vp-icons.css | 1 + 846 files changed, 4146 insertions(+), 4970 deletions(-) rename assets/{a1.662d9415.png => a1.DvgNELwZ.png} (100%) rename assets/{a10.36860678.png => a10.CPK2ZJEJ.png} (100%) rename assets/{a11.bbc20080.png => a11.Bq6vmveu.png} (100%) rename assets/{a12.da46fe54.png => a12.bStrZLWw.png} (100%) rename assets/{a13.b49276aa.png => a13.DRz8WTJR.png} (100%) rename assets/{a14.908480a6.png => a14.D56M6gMb.png} (100%) rename assets/{a15.9533f30d.png => a15.CtjmUhal.png} (100%) rename assets/{a16.2257f2d8.png => a16.BL0_sgNg.png} (100%) rename assets/{a17.b57c7755.png => a17.B9keXK9k.png} (100%) rename assets/{a18.c3a22602.png => a18.Bu92JFv5.png} (100%) rename assets/{a19.1eefd81d.png => a19.DZjr60Xs.png} (100%) rename assets/{a2.1d7d86db.png => a2.BQniQEw_.png} (100%) rename assets/{a20.24042237.png => a20.CesdkIR_.png} (100%) rename assets/{a21.2bb37c9a.png => a21.BO8sy8n4.png} (100%) rename assets/{a22.44ab6d75.png => a22.COjD9r-B.png} (100%) rename assets/{a23.191de0ca.png => a23.BxEEAckp.png} (100%) rename assets/{a24.d2a9c729.png => a24.BrCKYLHX.png} (100%) rename assets/{a25.3e24d99b.png => a25.CUB6zoiS.png} (100%) rename assets/{a26.2fce6332.png => a26.zvaFRs59.png} (100%) rename assets/{a27.dd61884c.png => a27.QkS9Cjl7.png} (100%) rename assets/{a3.178777a1.png => a3.DHUpjnAe.png} (100%) rename assets/{a31.6d3a9d85.png => a31.BiCzGFMR.png} (100%) rename assets/{a32.d9973307.png => a32.54sdf1AZ.png} (100%) rename assets/{a33.8b54ce3f.png => a33.QYBAXO71.png} (100%) rename assets/{a34.07f5cc75.png => a34.BBqAz_kr.png} (100%) rename assets/{a35.78be61d4.png => a35.B8NF_iJX.png} (100%) rename assets/{a36.a36765c2.png => a36.CPvsggxV.png} (100%) rename assets/{a37.e6740eaa.png => a37.DJRI7pv9.png} (100%) rename assets/{a38.999b4ffb.png => a38.BhfuTk-3.png} (100%) rename assets/{a39.9dac95e1.png => a39.BNtfZ4xd.png} (100%) rename assets/{a4.65c15963.png => a4.BtVJtyBL.png} (100%) rename assets/{a40.7f5ad4ea.png => a40.DTfyEQe2.png} (100%) rename assets/{a41.bbc5e317.png => a41.Cb6MjiUm.png} (100%) rename assets/{a42.de7d1da7.png => a42.Du63tHI8.png} (100%) rename assets/{a43.e713599d.png => a43.Cxy9Fqxr.png} (100%) rename assets/{a44.5c4e5e0a.png => a44.Dhcgau_f.png} (100%) rename assets/{a45.2c32612e.png => a45.DQgcLv5f.png} (100%) rename assets/{a5.01b8514f.png => a5.CamDlEuL.png} (100%) rename assets/{a6.67efded0.png => a6.auUigeOH.png} (100%) rename assets/{a7.b8de9a6c.png => a7.3_Is3HF1.png} (100%) rename assets/{a8.69056d9a.png => a8.CkyIulFy.png} (100%) rename assets/{a9.d4cc5fc0.png => a9.Dg58RrTs.png} (100%) delete mode 100644 assets/app.7da1868b.js create mode 100644 assets/app.D4kLJnX4.js rename assets/{ar.0d8bb8f3.png => ar.Dy_5EjFU.png} (100%) rename assets/{b1.c1fdb506.png => b1.CSqggjTM.png} (100%) rename assets/{b10.52a93636.png => b10.DGHfd73s.png} (100%) rename assets/{b11.2e525d8d.png => b11.DKZjwgY8.png} (100%) rename assets/{b12.54c3189d.png => b12.BISDj2Ri.png} (100%) rename assets/{b13.3b3ae784.png => b13.WGr5jMeK.png} (100%) rename assets/{b14.662b1a1b.png => b14.BqBpvoFk.png} (100%) rename assets/{b15.0c5536d8.png => b15.Cd3Rj7ju.png} (100%) rename assets/{b16.0fbcfcb1.png => b16.BR7AHi1X.png} (100%) rename assets/{b17.4e7429fe.png => b17.Cn1C4e1e.png} (100%) rename assets/{b18.8211f293.png => b18.ElAa2UCQ.png} (100%) rename assets/{b19.2128d0fa.png => b19.BwC-oHOW.png} (100%) rename assets/{b2.519a9bf0.png => b2.BnvPQMj3.png} (100%) rename assets/{b20.8a62698b.png => b20.Dj-0rOwy.png} (100%) rename assets/{b21.dfe1e8f0.png => b21.CYRPkSXE.png} (100%) rename assets/{b22.13e3438c.png => b22.BH7kRZ3Z.png} (100%) rename assets/{b23.e293a560.png => b23.JVX-KOL7.png} (100%) rename assets/{b24.23cbc29a.png => b24.a2fv8lkf.png} (100%) rename assets/{b25.f2c2ebd7.png => b25.BJrNgkiA.png} (100%) rename assets/{b26.b7136167.png => b26.5bTO5HK5.png} (100%) rename assets/{b27.cc8f8644.png => b27.BSRz6moE.png} (100%) rename assets/{b28.2bf4d8b9.png => b28.WNjJaEPB.png} (100%) rename assets/{b29.8d301c10.png => b29.Bs69Ykqp.png} (100%) rename assets/{b3.42fd37a2.png => b3.DPn2dzFl.png} (100%) rename assets/{b30.a50bc8f3.png => b30.B96bh_Ou.png} (100%) rename assets/{b31.4881ca1d.png => b31.BBIAIScF.png} (100%) rename assets/{b32.b857654b.png => b32.8G5Xy9mr.png} (100%) rename assets/{b33.1125a81c.png => b33.RYxcR7vu.png} (100%) rename assets/{b34.2101ce9a.png => b34.Dw6MyLex.png} (100%) rename assets/{b35.83c5a766.png => b35.DUCPsVIG.png} (100%) rename assets/{b36.ea1f048c.png => b36.7aKaNaLh.png} (100%) rename assets/{b37.b60405a9.png => b37.B5CHAJzN.png} (100%) rename assets/{b38.4d73fbe3.png => b38.Pnnij22W.png} (100%) rename assets/{b39.c59ccabe.png => b39.ajiHDdbx.png} (100%) rename assets/{b4.b6d283a7.png => b4.JBQupWN9.png} (100%) rename assets/{b40.c1d0ee00.png => b40.B6FTkFUT.png} (100%) rename assets/{b41.0c6d7432.png => b41.DcCdod5l.png} (100%) rename assets/{b42.66cc353b.png => b42.CT1JvTLX.png} (100%) rename assets/{b43.a775b641.png => b43.HthhPs5o.png} (100%) rename assets/{b44.2d540844.png => b44.C9NeP-UC.png} (100%) rename assets/{b45.fe0240c6.png => b45.BWxBBH-l.png} (100%) rename assets/{b46.f6b9da14.png => b46.B6Ds58im.png} (100%) rename assets/{b5.4cd5361f.png => b5.DeuT9J-4.png} (100%) rename assets/{b6.36f0470d.png => b6.cZYHMwJ8.png} (100%) rename assets/{b7.9714bb16.png => b7.5Fkbt05C.png} (100%) rename assets/{b8.2eb373bf.png => b8.BXlK1Dnb.png} (100%) rename assets/{b9.3f01ffdc.png => b9.CaK5eLKm.png} (100%) rename assets/{br.bb3418b4.png => br.CyzpZwsx.png} (100%) delete mode 100644 assets/case_case1.md.3cf726ff.js delete mode 100644 assets/case_case1.md.3cf726ff.lean.js create mode 100644 assets/case_case1.md.URFLodrr.js create mode 100644 assets/case_case1.md.URFLodrr.lean.js create mode 100644 assets/case_case2.md.CDLx6tKM.js create mode 100644 assets/case_case2.md.CDLx6tKM.lean.js delete mode 100644 assets/case_case2.md.d9673a40.js delete mode 100644 assets/case_case2.md.d9673a40.lean.js delete mode 100644 assets/case_case3.md.8bd8db2f.js delete mode 100644 assets/case_case3.md.8bd8db2f.lean.js create mode 100644 assets/case_case3.md.Dr71EzwR.js create mode 100644 assets/case_case3.md.Dr71EzwR.lean.js delete mode 100644 assets/case_case4.md.14b56d9f.js delete mode 100644 assets/case_case4.md.14b56d9f.lean.js create mode 100644 assets/case_case4.md.BCt0xHGw.js create mode 100644 assets/case_case4.md.BCt0xHGw.lean.js delete mode 100644 assets/case_case5.md.991f7ced.js delete mode 100644 assets/case_case5.md.991f7ced.lean.js create mode 100644 assets/case_case5.md.D0hZllGZ.js create mode 100644 assets/case_case5.md.D0hZllGZ.lean.js create mode 100644 assets/case_case6.md.DBcKFtJZ.js create mode 100644 assets/case_case6.md.DBcKFtJZ.lean.js delete mode 100644 assets/case_case6.md.d14d2ac7.js delete mode 100644 assets/case_case6.md.d14d2ac7.lean.js create mode 100644 assets/case_case7.md.Ca88kvzN.js create mode 100644 assets/case_case7.md.Ca88kvzN.lean.js delete mode 100644 assets/case_case7.md.b84f4c02.js delete mode 100644 assets/case_case7.md.b84f4c02.lean.js rename assets/{case_index.md.259f5ee0.js => case_index.md.D_IkUok9.js} (78%) rename assets/{case_index.md.259f5ee0.lean.js => case_index.md.D_IkUok9.lean.js} (78%) create mode 100644 assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js delete mode 100644 assets/chunks/VPAlgoliaSearchBox.faa390b4.js delete mode 100644 assets/chunks/framework.70afa331.js create mode 100644 assets/chunks/framework.CSeR4K32.js create mode 100644 assets/chunks/theme.DJQtrHna.js delete mode 100644 assets/chunks/theme.b9d97670.js delete mode 100644 assets/chunks/wk7.6fe7513d.js delete mode 100644 assets/chunks/wk7.776871bd.js create mode 100644 assets/chunks/wk7.Bl1-W8YX.js create mode 100644 assets/chunks/wk7.BpuwpIoq.js rename assets/{cpu.4618bc7b.png => cpu.DedcVQ_T.png} (100%) rename assets/{developer_index.md.4b11aa55.js => developer_index.md.CXHgEkLk.js} (67%) rename assets/{developer_index.md.4b11aa55.lean.js => developer_index.md.CXHgEkLk.lean.js} (67%) create mode 100644 assets/developer_l10n.md.DbKLx65f.js create mode 100644 assets/developer_l10n.md.DbKLx65f.lean.js delete mode 100644 assets/developer_l10n.md.f381c679.js delete mode 100644 assets/developer_l10n.md.f381c679.lean.js rename assets/{disks.8065a143.png => disks.BJniy5pO.png} (100%) rename assets/{dlwiniso.a2c0c1ef.png => dlwiniso.BxXucu9m.png} (100%) rename assets/{dlwiniso1.4fa2fea0.png => dlwiniso1.CQyxWlSu.png} (100%) rename assets/{dns0.1beb9fa7.png => dns0.DDagSewr.png} (100%) rename assets/{en_developer_index.md.a033415e.js => en_developer_index.md.zTlMOyHV.js} (77%) rename assets/{en_developer_index.md.a033415e.lean.js => en_developer_index.md.zTlMOyHV.lean.js} (77%) delete mode 100644 assets/en_developer_l10n.md.2567a7c2.js delete mode 100644 assets/en_developer_l10n.md.2567a7c2.lean.js create mode 100644 assets/en_developer_l10n.md.CFaXJ2l2.js create mode 100644 assets/en_developer_l10n.md.CFaXJ2l2.lean.js delete mode 100644 assets/en_guide_block_block_docker.md.2627dfbd.js delete mode 100644 assets/en_guide_block_block_docker.md.2627dfbd.lean.js create mode 100644 assets/en_guide_block_block_docker.md.Bu7zbkEq.js create mode 100644 assets/en_guide_block_block_docker.md.Bu7zbkEq.lean.js delete mode 100644 assets/en_guide_block_block_incus.md.95762549.js delete mode 100644 assets/en_guide_block_block_incus.md.95762549.lean.js create mode 100644 assets/en_guide_block_block_incus.md.BTs-piI_.js create mode 100644 assets/en_guide_block_block_incus.md.BTs-piI_.lean.js delete mode 100644 assets/en_guide_block_block_iptables.md.6506e0bc.js delete mode 100644 assets/en_guide_block_block_iptables.md.6506e0bc.lean.js create mode 100644 assets/en_guide_block_block_iptables.md.ByV6snur.js create mode 100644 assets/en_guide_block_block_iptables.md.ByV6snur.lean.js delete mode 100644 assets/en_guide_block_block_lxd.md.616a5093.js delete mode 100644 assets/en_guide_block_block_lxd.md.616a5093.lean.js create mode 100644 assets/en_guide_block_block_lxd.md.BToyiHH5.js create mode 100644 assets/en_guide_block_block_lxd.md.BToyiHH5.lean.js delete mode 100644 assets/en_guide_block_block_pve.md.86088ae1.js delete mode 100644 assets/en_guide_block_block_pve.md.86088ae1.lean.js create mode 100644 assets/en_guide_block_block_pve.md.Bi62dGs9.js create mode 100644 assets/en_guide_block_block_pve.md.Bi62dGs9.lean.js delete mode 100644 assets/en_guide_dashboard.md.04c46e68.js delete mode 100644 assets/en_guide_dashboard.md.04c46e68.lean.js create mode 100644 assets/en_guide_dashboard.md.CwRb4UsX.js create mode 100644 assets/en_guide_dashboard.md.CwRb4UsX.lean.js delete mode 100644 assets/en_guide_dashboardq.md.220142b4.js delete mode 100644 assets/en_guide_dashboardq.md.220142b4.lean.js create mode 100644 assets/en_guide_dashboardq.md.BaUPP2a8.js create mode 100644 assets/en_guide_dashboardq.md.BaUPP2a8.lean.js create mode 100644 assets/en_guide_docker_docker_android.md.BulF4nM1.js create mode 100644 assets/en_guide_docker_docker_android.md.BulF4nM1.lean.js delete mode 100644 assets/en_guide_docker_docker_android.md.ffbfb237.js delete mode 100644 assets/en_guide_docker_docker_android.md.ffbfb237.lean.js delete mode 100644 assets/en_guide_docker_docker_build.md.5395d3b9.js delete mode 100644 assets/en_guide_docker_docker_build.md.5395d3b9.lean.js create mode 100644 assets/en_guide_docker_docker_build.md.DvGO9A3O.js create mode 100644 assets/en_guide_docker_docker_build.md.DvGO9A3O.lean.js delete mode 100644 assets/en_guide_docker_docker_custom.md.4e05a2c3.js delete mode 100644 assets/en_guide_docker_docker_custom.md.4e05a2c3.lean.js create mode 100644 assets/en_guide_docker_docker_custom.md.CoAvHe_n.js create mode 100644 assets/en_guide_docker_docker_custom.md.CoAvHe_n.lean.js delete mode 100644 assets/en_guide_docker_docker_install.md.2b0bb4e4.js delete mode 100644 assets/en_guide_docker_docker_install.md.2b0bb4e4.lean.js create mode 100644 assets/en_guide_docker_docker_install.md.DMUsaTt3.js create mode 100644 assets/en_guide_docker_docker_install.md.DMUsaTt3.lean.js delete mode 100644 assets/en_guide_docker_docker_macos.md.48b99172.js delete mode 100644 assets/en_guide_docker_docker_macos.md.48b99172.lean.js create mode 100644 assets/en_guide_docker_docker_macos.md.DItPel8U.js create mode 100644 assets/en_guide_docker_docker_macos.md.DItPel8U.lean.js create mode 100644 assets/en_guide_docker_docker_precheck.md.BrsWou7M.js create mode 100644 assets/en_guide_docker_docker_precheck.md.BrsWou7M.lean.js delete mode 100644 assets/en_guide_docker_docker_precheck.md.a9b1c276.js delete mode 100644 assets/en_guide_docker_docker_precheck.md.a9b1c276.lean.js delete mode 100644 assets/en_guide_docker_docker_qa.md.fed2a991.js delete mode 100644 assets/en_guide_docker_docker_qa.md.fed2a991.lean.js create mode 100644 assets/en_guide_docker_docker_qa.md.q3nJoH_p.js create mode 100644 assets/en_guide_docker_docker_qa.md.q3nJoH_p.lean.js create mode 100644 assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.js create mode 100644 assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.lean.js delete mode 100644 assets/en_guide_docker_docker_thanks.md.d7efa635.js delete mode 100644 assets/en_guide_docker_docker_thanks.md.d7efa635.lean.js create mode 100644 assets/en_guide_docker_docker_windows.md.CDb3Bppx.js create mode 100644 assets/en_guide_docker_docker_windows.md.CDb3Bppx.lean.js delete mode 100644 assets/en_guide_docker_docker_windows.md.aeb5b431.js delete mode 100644 assets/en_guide_docker_docker_windows.md.aeb5b431.lean.js create mode 100644 assets/en_guide_incus_incus_custom.md.DUBzNIug.js create mode 100644 assets/en_guide_incus_incus_custom.md.DUBzNIug.lean.js delete mode 100644 assets/en_guide_incus_incus_custom.md.f6f0e581.js delete mode 100644 assets/en_guide_incus_incus_custom.md.f6f0e581.lean.js delete mode 100644 assets/en_guide_incus_incus_extra_config.md.06d84d9b.js delete mode 100644 assets/en_guide_incus_incus_extra_config.md.06d84d9b.lean.js create mode 100644 assets/en_guide_incus_incus_extra_config.md.BkutcTAl.js create mode 100644 assets/en_guide_incus_incus_extra_config.md.BkutcTAl.lean.js create mode 100644 assets/en_guide_incus_incus_install.md.BgEyJdKz.js create mode 100644 assets/en_guide_incus_incus_install.md.BgEyJdKz.lean.js delete mode 100644 assets/en_guide_incus_incus_install.md.ce7c0d18.js delete mode 100644 assets/en_guide_incus_incus_install.md.ce7c0d18.lean.js create mode 100644 assets/en_guide_incus_incus_lxc.md.BxXye95l.js create mode 100644 assets/en_guide_incus_incus_lxc.md.BxXye95l.lean.js delete mode 100644 assets/en_guide_incus_incus_lxc.md.c5c0a6f8.js delete mode 100644 assets/en_guide_incus_incus_lxc.md.c5c0a6f8.lean.js delete mode 100644 assets/en_guide_incus_incus_precheck.md.44458de1.js delete mode 100644 assets/en_guide_incus_incus_precheck.md.44458de1.lean.js create mode 100644 assets/en_guide_incus_incus_precheck.md.DeMpsPcV.js create mode 100644 assets/en_guide_incus_incus_precheck.md.DeMpsPcV.lean.js create mode 100644 assets/en_guide_incus_incus_qa.md.L3eCjNtY.js create mode 100644 assets/en_guide_incus_incus_qa.md.L3eCjNtY.lean.js delete mode 100644 assets/en_guide_incus_incus_qa.md.bea92aa8.js delete mode 100644 assets/en_guide_incus_incus_qa.md.bea92aa8.lean.js delete mode 100644 assets/en_guide_incus_incus_thanks.md.5f3fccbe.js delete mode 100644 assets/en_guide_incus_incus_thanks.md.5f3fccbe.lean.js create mode 100644 assets/en_guide_incus_incus_thanks.md.CjY9f-A0.js create mode 100644 assets/en_guide_incus_incus_thanks.md.CjY9f-A0.lean.js delete mode 100644 assets/en_guide_incus_incus_windows.md.7fb5eecc.js delete mode 100644 assets/en_guide_incus_incus_windows.md.7fb5eecc.lean.js create mode 100644 assets/en_guide_incus_incus_windows.md.CPQ_HdzK.js create mode 100644 assets/en_guide_incus_incus_windows.md.CPQ_HdzK.lean.js create mode 100644 assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.js create mode 100644 assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.lean.js delete mode 100644 assets/en_guide_lxd_lxd_custom.md.f8616b5f.js delete mode 100644 assets/en_guide_lxd_lxd_custom.md.f8616b5f.lean.js delete mode 100644 assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.js delete mode 100644 assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.lean.js create mode 100644 assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.js create mode 100644 assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.lean.js delete mode 100644 assets/en_guide_lxd_lxd_install.md.b53a57be.js delete mode 100644 assets/en_guide_lxd_lxd_install.md.b53a57be.lean.js create mode 100644 assets/en_guide_lxd_lxd_install.md.z7YfDjTq.js create mode 100644 assets/en_guide_lxd_lxd_install.md.z7YfDjTq.lean.js delete mode 100644 assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.js delete mode 100644 assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.lean.js create mode 100644 assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.js create mode 100644 assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.lean.js delete mode 100644 assets/en_guide_lxd_lxd_precheck.md.995523b7.js delete mode 100644 assets/en_guide_lxd_lxd_precheck.md.995523b7.lean.js create mode 100644 assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.js create mode 100644 assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.lean.js delete mode 100644 assets/en_guide_lxd_lxd_qa.md.7268ae8d.js delete mode 100644 assets/en_guide_lxd_lxd_qa.md.7268ae8d.lean.js create mode 100644 assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.js create mode 100644 assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.lean.js rename assets/{guide_incus_incus_thanks.md.4ec3421d.js => en_guide_lxd_lxd_thanks.md.CeZBLRKW.js} (51%) create mode 100644 assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.lean.js delete mode 100644 assets/en_guide_lxd_lxd_thanks.md.bbb08af5.js delete mode 100644 assets/en_guide_lxd_lxd_thanks.md.bbb08af5.lean.js delete mode 100644 assets/en_guide_lxd_lxd_windows.md.586d29ea.js delete mode 100644 assets/en_guide_lxd_lxd_windows.md.586d29ea.lean.js create mode 100644 assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.js create mode 100644 assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.lean.js create mode 100644 assets/en_guide_pve_images_readme.md.Dq3BR6Q6.js create mode 100644 assets/en_guide_pve_images_readme.md.Dq3BR6Q6.lean.js delete mode 100644 assets/en_guide_pve_images_readme.md.f8849b0b.js delete mode 100644 assets/en_guide_pve_images_readme.md.f8849b0b.lean.js create mode 100644 assets/en_guide_pve_pve_android.md.D8JpIji1.js create mode 100644 assets/en_guide_pve_pve_android.md.D8JpIji1.lean.js delete mode 100644 assets/en_guide_pve_pve_android.md.bc9044ee.js delete mode 100644 assets/en_guide_pve_pve_android.md.bc9044ee.lean.js delete mode 100644 assets/en_guide_pve_pve_custom.md.4615a36e.js delete mode 100644 assets/en_guide_pve_pve_custom.md.4615a36e.lean.js create mode 100644 assets/en_guide_pve_pve_custom.md.BNwEwNPy.js create mode 100644 assets/en_guide_pve_pve_custom.md.BNwEwNPy.lean.js delete mode 100644 assets/en_guide_pve_pve_install.md.69e0d919.js delete mode 100644 assets/en_guide_pve_pve_install.md.69e0d919.lean.js create mode 100644 assets/en_guide_pve_pve_install.md.DG8IYoZ0.js create mode 100644 assets/en_guide_pve_pve_install.md.DG8IYoZ0.lean.js delete mode 100644 assets/en_guide_pve_pve_kvm.md.97ca4d66.js delete mode 100644 assets/en_guide_pve_pve_kvm.md.97ca4d66.lean.js create mode 100644 assets/en_guide_pve_pve_kvm.md.CutjUOCm.js create mode 100644 assets/en_guide_pve_pve_kvm.md.CutjUOCm.lean.js delete mode 100644 assets/en_guide_pve_pve_lxc.md.5f264fc4.js delete mode 100644 assets/en_guide_pve_pve_lxc.md.5f264fc4.lean.js create mode 100644 assets/en_guide_pve_pve_lxc.md.DacQBeid.js create mode 100644 assets/en_guide_pve_pve_lxc.md.DacQBeid.lean.js delete mode 100644 assets/en_guide_pve_pve_macos.md.785a524c.js delete mode 100644 assets/en_guide_pve_pve_macos.md.785a524c.lean.js create mode 100644 assets/en_guide_pve_pve_macos.md.Cy9mzi8X.js create mode 100644 assets/en_guide_pve_pve_macos.md.Cy9mzi8X.lean.js delete mode 100644 assets/en_guide_pve_pve_precheck.md.2c6a4e25.js delete mode 100644 assets/en_guide_pve_pve_precheck.md.2c6a4e25.lean.js create mode 100644 assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.js create mode 100644 assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.lean.js delete mode 100644 assets/en_guide_pve_pve_qa.md.3406e13c.js delete mode 100644 assets/en_guide_pve_pve_qa.md.3406e13c.lean.js create mode 100644 assets/en_guide_pve_pve_qa.md.BYBr2UQn.js create mode 100644 assets/en_guide_pve_pve_qa.md.BYBr2UQn.lean.js create mode 100644 assets/en_guide_pve_pve_thanks.md.Dw43XV-y.js create mode 100644 assets/en_guide_pve_pve_thanks.md.Dw43XV-y.lean.js delete mode 100644 assets/en_guide_pve_pve_thanks.md.dc0491f9.js delete mode 100644 assets/en_guide_pve_pve_thanks.md.dc0491f9.lean.js delete mode 100644 assets/en_guide_pve_pve_windows.md.923bbd33.js delete mode 100644 assets/en_guide_pve_pve_windows.md.923bbd33.lean.js create mode 100644 assets/en_guide_pve_pve_windows.md.vqwXYaPa.js create mode 100644 assets/en_guide_pve_pve_windows.md.vqwXYaPa.lean.js create mode 100644 assets/en_incomplete_bashvm.md.DWaL7zdf.js create mode 100644 assets/en_incomplete_bashvm.md.DWaL7zdf.lean.js delete mode 100644 assets/en_incomplete_bashvm.md.fce6926b.js delete mode 100644 assets/en_incomplete_bashvm.md.fce6926b.lean.js create mode 100644 assets/en_incomplete_cockpit.md.DKGXpcw0.js create mode 100644 assets/en_incomplete_cockpit.md.DKGXpcw0.lean.js delete mode 100644 assets/en_incomplete_cockpit.md.a60c11d2.js delete mode 100644 assets/en_incomplete_cockpit.md.a60c11d2.lean.js create mode 100644 assets/en_incomplete_convoy.md.ClbXbvA3.js create mode 100644 assets/en_incomplete_convoy.md.ClbXbvA3.lean.js delete mode 100644 assets/en_incomplete_convoy.md.ccd54afd.js delete mode 100644 assets/en_incomplete_convoy.md.ccd54afd.lean.js rename assets/{en_incomplete_index.md.675215c6.js => en_incomplete_index.md.B8q1NrDT.js} (87%) rename assets/{en_incomplete_index.md.675215c6.lean.js => en_incomplete_index.md.B8q1NrDT.lean.js} (87%) create mode 100644 assets/en_incomplete_pterodactyl.md.CFqYcu_4.js create mode 100644 assets/en_incomplete_pterodactyl.md.CFqYcu_4.lean.js delete mode 100644 assets/en_incomplete_pterodactyl.md.df0ba4ff.js delete mode 100644 assets/en_incomplete_pterodactyl.md.df0ba4ff.lean.js create mode 100644 assets/en_incomplete_virtfusion.md.C7tkSFJE.js create mode 100644 assets/en_incomplete_virtfusion.md.C7tkSFJE.lean.js delete mode 100644 assets/en_incomplete_virtfusion.md.e7f03a8b.js delete mode 100644 assets/en_incomplete_virtfusion.md.e7f03a8b.lean.js delete mode 100644 assets/en_incomplete_virtualizor-docker.md.449703b7.js delete mode 100644 assets/en_incomplete_virtualizor-docker.md.449703b7.lean.js create mode 100644 assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.js create mode 100644 assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.lean.js create mode 100644 assets/en_incomplete_webvirtcloud.md.DfzbkCBK.js create mode 100644 assets/en_incomplete_webvirtcloud.md.DfzbkCBK.lean.js delete mode 100644 assets/en_incomplete_webvirtcloud.md.a6e9dff8.js delete mode 100644 assets/en_incomplete_webvirtcloud.md.a6e9dff8.lean.js delete mode 100644 assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.js delete mode 100644 assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.lean.js create mode 100644 assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.js create mode 100644 assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.lean.js delete mode 100644 assets/en_incomplete_webvirtmgr.md.611aa9ab.js delete mode 100644 assets/en_incomplete_webvirtmgr.md.611aa9ab.lean.js create mode 100644 assets/en_incomplete_webvirtmgr.md.8Ub32E-h.js create mode 100644 assets/en_incomplete_webvirtmgr.md.8Ub32E-h.lean.js rename assets/{en_index.md.83e2fa26.js => en_index.md.DhJzLyfV.js} (91%) rename assets/{en_index.md.83e2fa26.lean.js => en_index.md.DhJzLyfV.lean.js} (91%) rename assets/{finish.0c3eac87.png => finish.Cf6DgPp1.png} (100%) rename assets/{general.ea03923c.png => general.BkOp2iK4.png} (100%) rename assets/{gic1.42bfd260.png => gic1.XkdPXihx.png} (100%) rename assets/{gic2.ff78c941.png => gic2.s5VB7-xp.png} (100%) rename assets/{gic3.4a04cf3d.png => gic3.2zLznATL.png} (100%) rename assets/{gic4.e2343160.png => gic4.CX3t8C19.png} (100%) rename assets/{gic5.54522dff.png => gic5.pjwHWuhn.png} (100%) rename assets/{gic6.97561122.png => gic6.BnmyenL0.png} (100%) rename assets/{gic7.a8679083.png => gic7.ZYHWzF5W.png} (100%) rename assets/{gic8.fe7d0b3c.png => gic8.BwCbmRgC.png} (100%) rename assets/{gic9.4cdf4daa.png => gic9.62-9wTBo.png} (100%) delete mode 100644 assets/guide_block_block_docker.md.5830a230.js delete mode 100644 assets/guide_block_block_docker.md.5830a230.lean.js create mode 100644 assets/guide_block_block_docker.md.C-tufkRV.js create mode 100644 assets/guide_block_block_docker.md.C-tufkRV.lean.js delete mode 100644 assets/guide_block_block_incus.md.9da06b17.js delete mode 100644 assets/guide_block_block_incus.md.9da06b17.lean.js create mode 100644 assets/guide_block_block_incus.md.D3fB2bDD.js create mode 100644 assets/guide_block_block_incus.md.D3fB2bDD.lean.js delete mode 100644 assets/guide_block_block_iptables.md.56fd36c5.js delete mode 100644 assets/guide_block_block_iptables.md.56fd36c5.lean.js create mode 100644 assets/guide_block_block_iptables.md.DkS3brgv.js create mode 100644 assets/guide_block_block_iptables.md.DkS3brgv.lean.js create mode 100644 assets/guide_block_block_lxd.md.BrbV-k4o.js create mode 100644 assets/guide_block_block_lxd.md.BrbV-k4o.lean.js delete mode 100644 assets/guide_block_block_lxd.md.cf1b102e.js delete mode 100644 assets/guide_block_block_lxd.md.cf1b102e.lean.js delete mode 100644 assets/guide_block_block_pve.md.0b046fe8.js delete mode 100644 assets/guide_block_block_pve.md.0b046fe8.lean.js create mode 100644 assets/guide_block_block_pve.md.BntEIKAB.js create mode 100644 assets/guide_block_block_pve.md.BntEIKAB.lean.js delete mode 100644 assets/guide_dashboard.md.7c9eeb09.js delete mode 100644 assets/guide_dashboard.md.7c9eeb09.lean.js create mode 100644 assets/guide_dashboard.md.D2bjCnlL.js create mode 100644 assets/guide_dashboard.md.D2bjCnlL.lean.js delete mode 100644 assets/guide_dashboardq.md.02164389.js delete mode 100644 assets/guide_dashboardq.md.02164389.lean.js create mode 100644 assets/guide_dashboardq.md.DGJ9X51L.js create mode 100644 assets/guide_dashboardq.md.DGJ9X51L.lean.js create mode 100644 assets/guide_docker_docker_android.md.DyBMNwLg.js create mode 100644 assets/guide_docker_docker_android.md.DyBMNwLg.lean.js delete mode 100644 assets/guide_docker_docker_android.md.c556d7ea.js delete mode 100644 assets/guide_docker_docker_android.md.c556d7ea.lean.js create mode 100644 assets/guide_docker_docker_build.md.DoAlFeWZ.js create mode 100644 assets/guide_docker_docker_build.md.DoAlFeWZ.lean.js delete mode 100644 assets/guide_docker_docker_build.md.d0d61806.js delete mode 100644 assets/guide_docker_docker_build.md.d0d61806.lean.js delete mode 100644 assets/guide_docker_docker_custom.md.01bd0eed.js delete mode 100644 assets/guide_docker_docker_custom.md.01bd0eed.lean.js create mode 100644 assets/guide_docker_docker_custom.md.uaKETGnt.js create mode 100644 assets/guide_docker_docker_custom.md.uaKETGnt.lean.js delete mode 100644 assets/guide_docker_docker_install.md.69dee249.js delete mode 100644 assets/guide_docker_docker_install.md.69dee249.lean.js create mode 100644 assets/guide_docker_docker_install.md.DkBio7r4.js create mode 100644 assets/guide_docker_docker_install.md.DkBio7r4.lean.js delete mode 100644 assets/guide_docker_docker_macos.md.7497eb24.js delete mode 100644 assets/guide_docker_docker_macos.md.7497eb24.lean.js create mode 100644 assets/guide_docker_docker_macos.md.B-ddHhbN.js create mode 100644 assets/guide_docker_docker_macos.md.B-ddHhbN.lean.js delete mode 100644 assets/guide_docker_docker_precheck.md.78609506.js delete mode 100644 assets/guide_docker_docker_precheck.md.78609506.lean.js create mode 100644 assets/guide_docker_docker_precheck.md.Dgik3VYv.js create mode 100644 assets/guide_docker_docker_precheck.md.Dgik3VYv.lean.js delete mode 100644 assets/guide_docker_docker_qa.md.94f80b81.js delete mode 100644 assets/guide_docker_docker_qa.md.94f80b81.lean.js create mode 100644 assets/guide_docker_docker_qa.md.BAZeywiq.js create mode 100644 assets/guide_docker_docker_qa.md.BAZeywiq.lean.js delete mode 100644 assets/guide_docker_docker_thanks.md.4049eaf0.js delete mode 100644 assets/guide_docker_docker_thanks.md.4049eaf0.lean.js create mode 100644 assets/guide_docker_docker_thanks.md.CMHMSDTy.js create mode 100644 assets/guide_docker_docker_thanks.md.CMHMSDTy.lean.js delete mode 100644 assets/guide_docker_docker_windows.md.9011d893.js delete mode 100644 assets/guide_docker_docker_windows.md.9011d893.lean.js create mode 100644 assets/guide_docker_docker_windows.md.BAGQZpoB.js create mode 100644 assets/guide_docker_docker_windows.md.BAGQZpoB.lean.js create mode 100644 assets/guide_incus_incus_custom.md.Bm8HnEPC.js create mode 100644 assets/guide_incus_incus_custom.md.Bm8HnEPC.lean.js delete mode 100644 assets/guide_incus_incus_custom.md.b1aba773.js delete mode 100644 assets/guide_incus_incus_custom.md.b1aba773.lean.js delete mode 100644 assets/guide_incus_incus_extra_config.md.91dfbfa5.js delete mode 100644 assets/guide_incus_incus_extra_config.md.91dfbfa5.lean.js create mode 100644 assets/guide_incus_incus_extra_config.md.AJ5M0HDo.js create mode 100644 assets/guide_incus_incus_extra_config.md.AJ5M0HDo.lean.js create mode 100644 assets/guide_incus_incus_install.md.BmXHRJpC.js create mode 100644 assets/guide_incus_incus_install.md.BmXHRJpC.lean.js delete mode 100644 assets/guide_incus_incus_install.md.ba70a2a0.js delete mode 100644 assets/guide_incus_incus_install.md.ba70a2a0.lean.js delete mode 100644 assets/guide_incus_incus_lxc.md.3de28e6b.js delete mode 100644 assets/guide_incus_incus_lxc.md.3de28e6b.lean.js create mode 100644 assets/guide_incus_incus_lxc.md.CcPIDp5T.js create mode 100644 assets/guide_incus_incus_lxc.md.CcPIDp5T.lean.js delete mode 100644 assets/guide_incus_incus_precheck.md.6bf5b424.js delete mode 100644 assets/guide_incus_incus_precheck.md.6bf5b424.lean.js create mode 100644 assets/guide_incus_incus_precheck.md.DTFAD1HQ.js create mode 100644 assets/guide_incus_incus_precheck.md.DTFAD1HQ.lean.js delete mode 100644 assets/guide_incus_incus_qa.md.780b508f.js delete mode 100644 assets/guide_incus_incus_qa.md.780b508f.lean.js create mode 100644 assets/guide_incus_incus_qa.md.D2Pi0dJG.js create mode 100644 assets/guide_incus_incus_qa.md.D2Pi0dJG.lean.js delete mode 100644 assets/guide_incus_incus_thanks.md.4ec3421d.lean.js create mode 100644 assets/guide_incus_incus_thanks.md.DJw_BEEC.js create mode 100644 assets/guide_incus_incus_thanks.md.DJw_BEEC.lean.js delete mode 100644 assets/guide_incus_incus_windows.md.5ba7b2ce.js delete mode 100644 assets/guide_incus_incus_windows.md.5ba7b2ce.lean.js create mode 100644 assets/guide_incus_incus_windows.md.CFcsS3lD.js create mode 100644 assets/guide_incus_incus_windows.md.CFcsS3lD.lean.js delete mode 100644 assets/guide_lxd_lxd_custom.md.20323fda.js delete mode 100644 assets/guide_lxd_lxd_custom.md.20323fda.lean.js create mode 100644 assets/guide_lxd_lxd_custom.md.gEdxHFHM.js create mode 100644 assets/guide_lxd_lxd_custom.md.gEdxHFHM.lean.js create mode 100644 assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.js create mode 100644 assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.lean.js delete mode 100644 assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.js delete mode 100644 assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.lean.js delete mode 100644 assets/guide_lxd_lxd_install.md.8dc77da5.js delete mode 100644 assets/guide_lxd_lxd_install.md.8dc77da5.lean.js create mode 100644 assets/guide_lxd_lxd_install.md.D4zH3hWU.js create mode 100644 assets/guide_lxd_lxd_install.md.D4zH3hWU.lean.js delete mode 100644 assets/guide_lxd_lxd_lxc.md.728ada33.js delete mode 100644 assets/guide_lxd_lxd_lxc.md.728ada33.lean.js create mode 100644 assets/guide_lxd_lxd_lxc.md.PKqgxyhI.js create mode 100644 assets/guide_lxd_lxd_lxc.md.PKqgxyhI.lean.js delete mode 100644 assets/guide_lxd_lxd_precheck.md.42adf95c.js delete mode 100644 assets/guide_lxd_lxd_precheck.md.42adf95c.lean.js create mode 100644 assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.js create mode 100644 assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.lean.js delete mode 100644 assets/guide_lxd_lxd_qa.md.44833073.js delete mode 100644 assets/guide_lxd_lxd_qa.md.44833073.lean.js create mode 100644 assets/guide_lxd_lxd_qa.md.C4FXk4za.js create mode 100644 assets/guide_lxd_lxd_qa.md.C4FXk4za.lean.js delete mode 100644 assets/guide_lxd_lxd_thanks.md.6aebeab6.js delete mode 100644 assets/guide_lxd_lxd_thanks.md.6aebeab6.lean.js create mode 100644 assets/guide_lxd_lxd_thanks.md.oRZKHNsx.js create mode 100644 assets/guide_lxd_lxd_thanks.md.oRZKHNsx.lean.js delete mode 100644 assets/guide_lxd_lxd_windows.md.9b33f709.js delete mode 100644 assets/guide_lxd_lxd_windows.md.9b33f709.lean.js create mode 100644 assets/guide_lxd_lxd_windows.md.CpTtBXvV.js create mode 100644 assets/guide_lxd_lxd_windows.md.CpTtBXvV.lean.js create mode 100644 assets/guide_pve_images_readme.md.ZJUoqm_K.js create mode 100644 assets/guide_pve_images_readme.md.ZJUoqm_K.lean.js delete mode 100644 assets/guide_pve_images_readme.md.e91db2b4.js delete mode 100644 assets/guide_pve_images_readme.md.e91db2b4.lean.js delete mode 100644 assets/guide_pve_pve_android.md.5728ca62.js delete mode 100644 assets/guide_pve_pve_android.md.5728ca62.lean.js create mode 100644 assets/guide_pve_pve_android.md.DauuQgmC.js create mode 100644 assets/guide_pve_pve_android.md.DauuQgmC.lean.js create mode 100644 assets/guide_pve_pve_custom.md.0uRKiuWM.js create mode 100644 assets/guide_pve_pve_custom.md.0uRKiuWM.lean.js delete mode 100644 assets/guide_pve_pve_custom.md.c31784f7.js delete mode 100644 assets/guide_pve_pve_custom.md.c31784f7.lean.js create mode 100644 assets/guide_pve_pve_install.md.CdRZOjQC.js create mode 100644 assets/guide_pve_pve_install.md.CdRZOjQC.lean.js delete mode 100644 assets/guide_pve_pve_install.md.b9ed6cd8.js delete mode 100644 assets/guide_pve_pve_install.md.b9ed6cd8.lean.js delete mode 100644 assets/guide_pve_pve_kvm.md.43713910.js delete mode 100644 assets/guide_pve_pve_kvm.md.43713910.lean.js create mode 100644 assets/guide_pve_pve_kvm.md.DiXxjdva.js create mode 100644 assets/guide_pve_pve_kvm.md.DiXxjdva.lean.js delete mode 100644 assets/guide_pve_pve_lxc.md.704d4792.js delete mode 100644 assets/guide_pve_pve_lxc.md.704d4792.lean.js create mode 100644 assets/guide_pve_pve_lxc.md.D_RYunJp.js create mode 100644 assets/guide_pve_pve_lxc.md.D_RYunJp.lean.js delete mode 100644 assets/guide_pve_pve_macos.md.21762f54.js delete mode 100644 assets/guide_pve_pve_macos.md.21762f54.lean.js create mode 100644 assets/guide_pve_pve_macos.md.CRq8lCuz.js create mode 100644 assets/guide_pve_pve_macos.md.CRq8lCuz.lean.js delete mode 100644 assets/guide_pve_pve_precheck.md.2c856c99.js delete mode 100644 assets/guide_pve_pve_precheck.md.2c856c99.lean.js create mode 100644 assets/guide_pve_pve_precheck.md.Bwa9qWce.js create mode 100644 assets/guide_pve_pve_precheck.md.Bwa9qWce.lean.js delete mode 100644 assets/guide_pve_pve_qa.md.76a49097.js delete mode 100644 assets/guide_pve_pve_qa.md.76a49097.lean.js create mode 100644 assets/guide_pve_pve_qa.md.KEIUXkXN.js create mode 100644 assets/guide_pve_pve_qa.md.KEIUXkXN.lean.js delete mode 100644 assets/guide_pve_pve_thanks.md.3bbf24dc.js delete mode 100644 assets/guide_pve_pve_thanks.md.3bbf24dc.lean.js create mode 100644 assets/guide_pve_pve_thanks.md.DqgEZrWa.js create mode 100644 assets/guide_pve_pve_thanks.md.DqgEZrWa.lean.js delete mode 100644 assets/guide_pve_pve_windows.md.37289db4.js delete mode 100644 assets/guide_pve_pve_windows.md.37289db4.lean.js create mode 100644 assets/guide_pve_pve_windows.md.CLu8AekJ.js create mode 100644 assets/guide_pve_pve_windows.md.CLu8AekJ.lean.js create mode 100644 assets/incomplete_bashvm.md.B5fMrqJh.js create mode 100644 assets/incomplete_bashvm.md.B5fMrqJh.lean.js delete mode 100644 assets/incomplete_bashvm.md.e680b5ae.js delete mode 100644 assets/incomplete_bashvm.md.e680b5ae.lean.js delete mode 100644 assets/incomplete_cockpit.md.77e4fe67.js delete mode 100644 assets/incomplete_cockpit.md.77e4fe67.lean.js create mode 100644 assets/incomplete_cockpit.md.HGnaxkEA.js create mode 100644 assets/incomplete_cockpit.md.HGnaxkEA.lean.js create mode 100644 assets/incomplete_convoy.md.CxPU1hOM.js create mode 100644 assets/incomplete_convoy.md.CxPU1hOM.lean.js delete mode 100644 assets/incomplete_convoy.md.f7a4bd52.js delete mode 100644 assets/incomplete_convoy.md.f7a4bd52.lean.js rename assets/{incomplete_index.md.13d9bf0c.js => incomplete_index.md.CYVk98K2.js} (85%) rename assets/{incomplete_index.md.13d9bf0c.lean.js => incomplete_index.md.CYVk98K2.lean.js} (85%) delete mode 100644 assets/incomplete_pterodactyl.md.16ac57df.js delete mode 100644 assets/incomplete_pterodactyl.md.16ac57df.lean.js create mode 100644 assets/incomplete_pterodactyl.md.ywtPLv_5.js create mode 100644 assets/incomplete_pterodactyl.md.ywtPLv_5.lean.js create mode 100644 assets/incomplete_virtfusion.md.DnaD-J8U.js create mode 100644 assets/incomplete_virtfusion.md.DnaD-J8U.lean.js delete mode 100644 assets/incomplete_virtfusion.md.a22bdacd.js delete mode 100644 assets/incomplete_virtfusion.md.a22bdacd.lean.js create mode 100644 assets/incomplete_virtualizor-docker.md.BgClRxGW.js create mode 100644 assets/incomplete_virtualizor-docker.md.BgClRxGW.lean.js delete mode 100644 assets/incomplete_virtualizor-docker.md.a05fb0f7.js delete mode 100644 assets/incomplete_virtualizor-docker.md.a05fb0f7.lean.js delete mode 100644 assets/incomplete_webvirtcloud.md.2369e889.js delete mode 100644 assets/incomplete_webvirtcloud.md.2369e889.lean.js create mode 100644 assets/incomplete_webvirtcloud.md.4rNDyChD.js create mode 100644 assets/incomplete_webvirtcloud.md.4rNDyChD.lean.js delete mode 100644 assets/incomplete_webvirtcloud_retspen.md.8469ad25.js delete mode 100644 assets/incomplete_webvirtcloud_retspen.md.8469ad25.lean.js create mode 100644 assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.js create mode 100644 assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.lean.js delete mode 100644 assets/incomplete_webvirtmgr.md.d2161404.js delete mode 100644 assets/incomplete_webvirtmgr.md.d2161404.lean.js create mode 100644 assets/incomplete_webvirtmgr.md.y6DQ_-c0.js create mode 100644 assets/incomplete_webvirtmgr.md.y6DQ_-c0.lean.js rename assets/{index.md.33ff85ee.js => index.md.BVw2CyLu.js} (89%) rename assets/{index.md.33ff85ee.lean.js => index.md.BVw2CyLu.lean.js} (89%) delete mode 100644 assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 create mode 100644 assets/inter-italic-cyrillic-ext.r48I6akx.woff2 create mode 100644 assets/inter-italic-cyrillic.By2_1cv3.woff2 delete mode 100644 assets/inter-italic-cyrillic.ea42a392.woff2 create mode 100644 assets/inter-italic-greek-ext.1u6EdAuj.woff2 delete mode 100644 assets/inter-italic-greek-ext.4fbe9427.woff2 delete mode 100644 assets/inter-italic-greek.8f4463c4.woff2 create mode 100644 assets/inter-italic-greek.DJ8dCoTZ.woff2 create mode 100644 assets/inter-italic-latin-ext.CN1xVJS-.woff2 delete mode 100644 assets/inter-italic-latin-ext.bd8920cc.woff2 create mode 100644 assets/inter-italic-latin.C2AdPX0b.woff2 delete mode 100644 assets/inter-italic-latin.bd3b6f56.woff2 delete mode 100644 assets/inter-italic-vietnamese.6ce511fb.woff2 create mode 100644 assets/inter-italic-vietnamese.BSbpV94h.woff2 create mode 100644 assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 delete mode 100644 assets/inter-roman-cyrillic-ext.e75737ce.woff2 delete mode 100644 assets/inter-roman-cyrillic.5f2c6c8c.woff2 create mode 100644 assets/inter-roman-cyrillic.C5lxZ8CY.woff2 create mode 100644 assets/inter-roman-greek-ext.CqjqNYQ-.woff2 delete mode 100644 assets/inter-roman-greek-ext.ab0619bc.woff2 create mode 100644 assets/inter-roman-greek.BBVDIX6e.woff2 delete mode 100644 assets/inter-roman-greek.d5a6d92a.woff2 delete mode 100644 assets/inter-roman-latin-ext.0030eebd.woff2 create mode 100644 assets/inter-roman-latin-ext.4ZJIpNVo.woff2 delete mode 100644 assets/inter-roman-latin.2ed14f66.woff2 create mode 100644 assets/inter-roman-latin.Di8DUHzh.woff2 delete mode 100644 assets/inter-roman-vietnamese.14ce25a6.woff2 create mode 100644 assets/inter-roman-vietnamese.BjW4sHH5.woff2 rename assets/{kvm.d81063e5.png => kvm.CI48mv3H.png} (100%) rename assets/{lower1.28498396.png => lower1.DFw6c1iw.png} (100%) rename assets/{lower2.e782a20a.png => lower2.SPGPKJ4N.png} (100%) rename assets/{lxd1.78537e30.png => lxd1.CbGLa5s4.png} (100%) rename assets/{lxd10.a25a745c.png => lxd10.BjQ0l1K7.png} (100%) rename assets/{lxd11.b83f953c.png => lxd11.D6E5sVW2.png} (100%) rename assets/{lxd12.0da335dd.png => lxd12.B9udKIzn.png} (100%) rename assets/{lxd13.308fe0de.png => lxd13.Dwv7xBpz.png} (100%) rename assets/{lxd14.8dbfdcd6.png => lxd14.Whdz6cP-.png} (100%) rename assets/{lxd15.70114933.png => lxd15.BjW7LbDr.png} (100%) rename assets/{lxd16.a595fa36.png => lxd16.CgeIdYJ2.png} (100%) rename assets/{lxd17.d7ea65d8.png => lxd17.CWPY1pea.png} (100%) rename assets/{lxd18.d6225daa.png => lxd18.DqnpcYcL.png} (100%) rename assets/{lxd19.69674669.png => lxd19.B9_MB265.png} (100%) rename assets/{lxd2.da10b5ec.png => lxd2.C4eWfnaM.png} (100%) rename assets/{lxd20.179fc6e1.png => lxd20.rK3P3TT8.png} (100%) rename assets/{lxd21.48123d6a.png => lxd21.w-R0l00Y.png} (100%) rename assets/{lxd22.4386597e.png => lxd22.45M-VX6J.png} (100%) rename assets/{lxd23.c26427e3.png => lxd23.CLaVW0qk.png} (100%) rename assets/{lxd3.917f56de.png => lxd3.tQBNiKQo.png} (100%) rename assets/{lxd4.83a1a121.png => lxd4.CSfRHLxz.png} (100%) rename assets/{lxd5.4ebc1444.png => lxd5.WUJi0qzd.png} (100%) rename assets/{lxd6.572825bf.png => lxd6.Cnds779U.png} (100%) rename assets/{lxd7.b73982c7.png => lxd7.EJ0s1ls2.png} (100%) rename assets/{lxd8.9fcc21e5.png => lxd8.DAOueoww.png} (100%) rename assets/{lxd9.00250a32.png => lxd9.Dgmw4lpJ.png} (100%) rename assets/{lxdd0.b1d6b8bc.png => lxdd0.QoEngFSd.png} (100%) rename assets/{lxdd1.433ff357.png => lxdd1.CVTAIewh.png} (100%) rename assets/{lxdd2.6a93138a.png => lxdd2.C_mYE7sL.png} (100%) rename assets/{lxdd3.f56cf598.png => lxdd3.DZ2Na5-t.png} (100%) rename assets/{lxdd4.28d80b71.png => lxdd4.CO1I1FPh.png} (100%) rename assets/{mac0.935d53f3.png => mac0.CofQ9vw_.png} (100%) rename assets/{mac00.4296be7b.png => mac00.DelKhhmr.png} (100%) rename assets/{mac1.3307e401.png => mac1.D7yJtJrl.png} (100%) rename assets/{mac10.e9c284db.png => mac10.CZg7Yifb.png} (100%) rename assets/{mac11.a7587e0e.png => mac11.P11nsmhn.png} (100%) rename assets/{mac12.06b051d3.png => mac12.DHTBO7ih.png} (100%) rename assets/{mac13.7d4e3199.png => mac13.DDrsH3zK.png} (100%) rename assets/{mac14.39a58b6a.png => mac14.dLHoMtJy.png} (100%) rename assets/{mac15.f151793c.png => mac15.vkr7IxY1.png} (100%) rename assets/{mac16.eae177db.png => mac16.CeB_3pKz.png} (100%) rename assets/{mac17.be61913a.png => mac17.qkqeaTbW.png} (100%) rename assets/{mac18.f9454618.png => mac18.ChbyoMxq.png} (100%) rename assets/{mac19.845f5510.png => mac19.C_d085-7.png} (100%) rename assets/{mac2.da6ce0bc.png => mac2.du7V_m90.png} (100%) rename assets/{mac20.49a5800c.png => mac20.DsWyqQaw.png} (100%) rename assets/{mac21.2c30b60f.png => mac21.XZ5wILhH.png} (100%) rename assets/{mac3.76a50b9f.png => mac3.BCWQuf_Q.png} (100%) rename assets/{mac4.c341ba50.png => mac4.B0L5oLF9.png} (100%) rename assets/{mac5.39e1c9a4.png => mac5.QrcmrZyS.png} (100%) rename assets/{mac6.1cc0462b.png => mac6.CEnQahaC.png} (100%) rename assets/{mac7.181275ae.png => mac7.Cq44sm3y.png} (100%) rename assets/{mac8.dd556f02.png => mac8.CfhgXZ8s.png} (100%) rename assets/{mac9.c5d88eba.png => mac9.DIA9P3VH.png} (100%) rename assets/{memory.c4992870.png => memory.CH7Gxf76.png} (100%) rename assets/{net1.4f166207.png => net1.CUyp8ayS.png} (100%) rename assets/{net2.e2773ada.png => net2.BP2m5XnQ.png} (100%) rename assets/{net3.40e8a226.png => net3.BJFg7Me5.png} (100%) rename assets/{net4.a81e777c.png => net4.CANZtcPE.png} (100%) rename assets/{network.48037353.png => network.DPXM5W42.png} (100%) rename assets/{nodisk.5ec86f3b.png => nodisk.CH47I8Tu.png} (100%) rename assets/{nodisk1.671c1309.png => nodisk1.gZ09o2py.png} (100%) rename assets/{nodisk2.ff20bb76.png => nodisk2.Do6XEKMW.png} (100%) rename assets/{nodisk3.71534a11.png => nodisk3.1vBQc75S.png} (100%) rename assets/{nodisk4.b08d75e3.png => nodisk4.CJjHGgtp.png} (100%) rename assets/{onlinepkg.30da8d76.png => onlinepkg.-C5qKOrj.png} (100%) rename assets/{os.b2be1a5c.png => os.CX7bMEp5.png} (100%) rename assets/{pve_kvm_1.0f7e84f0.png => pve_kvm_1.BEDy-Dxt.png} (100%) rename assets/{pve_kvm_2.cefb9578.png => pve_kvm_2.C98l0GO8.png} (100%) rename assets/{pve_kvm_3.1d307586.png => pve_kvm_3.DzuyyWMo.png} (100%) rename assets/{start.3aebbfd4.png => start.vjgB4hml.png} (100%) create mode 100644 assets/style.DFTx90Kk.css delete mode 100644 assets/style.e150f059.css rename assets/{system.8e69987e.png => system.C_AmkiPg.png} (100%) rename assets/{vcr1.30d933ab.jpg => vcr1.NRLOOynQ.jpg} (100%) rename assets/{vcr10.548c566e.jpg => vcr10.D8t6cQ5v.jpg} (100%) rename assets/{vcr11.58ce8ace.jpg => vcr11.Cz1VMbIx.jpg} (100%) rename assets/{vcr12.3aa69b2a.jpg => vcr12.BNQe5j_u.jpg} (100%) rename assets/{vcr13.fcbcc557.jpg => vcr13.JV3PfcCZ.jpg} (100%) rename assets/{vcr14.7009c833.jpg => vcr14.Cjyr65Qp.jpg} (100%) rename assets/{vcr2.9b30a319.jpg => vcr2.DC9j-Ib5.jpg} (100%) rename assets/{vcr3.0aa5a564.jpg => vcr3.Ea5Km6nQ.jpg} (100%) rename assets/{vcr4.18a1487e.jpg => vcr4.B9DOiqQ8.jpg} (100%) rename assets/{vcr5.97deb479.jpg => vcr5.BajXu8XE.jpg} (100%) rename assets/{vcr6.e706123b.jpg => vcr6.CxN-b1o3.jpg} (100%) rename assets/{vcr7.43c60335.jpg => vcr7.D4aYKhIW.jpg} (100%) rename assets/{vcr8.1bf1f353.jpg => vcr8.ByRFpMlF.jpg} (100%) rename assets/{vcr9.b5afa4b4.jpg => vcr9.B4apCqgi.jpg} (100%) rename assets/{virtio.b42d8275.png => virtio.CUVhk14O.png} (100%) rename assets/{wechat.e3b2e06e.jpg => wechat.BhfskdFa.jpg} (100%) rename assets/{win1.7d3fc058.png => win1.BYIcp55m.png} (100%) rename assets/{win1.c8d28bad.png => win1.CJKAoRm5.png} (100%) rename assets/{win2.72bb0e48.jpg => win2.BNn7RQzT.jpg} (100%) rename assets/{win3.442eb15f.jpg => win3.BgsODJcQ.jpg} (100%) rename assets/{win4.75bd03c1.jpg => win4.DwKt_Ood.jpg} (100%) rename assets/{win5.58c1b996.jpg => win5.BSQ3T_9y.jpg} (100%) rename assets/{win5.cacd68cb.jpg => win5.C8qmMo1u.jpg} (100%) rename assets/{win6.f4215c61.jpg => win6.B-575Zc1.jpg} (100%) rename assets/{win6.19e58640.jpg => win6.Cx0KdzQb.jpg} (100%) rename assets/{win7.8f856089.jpg => win7.CI43Ul0V.jpg} (100%) rename assets/{win7.854d0e0a.jpg => win7.xhBfJRvu.jpg} (100%) rename assets/{wincf.76927350.jpg => wincf.B_Jc2M1G.jpg} (100%) rename assets/{wintj.56bef513.jpg => wintj.tP8uDOfH.jpg} (100%) rename assets/{wk1.7d9f24d7.png => wk1.BGnwsbrE.png} (100%) rename assets/{wk2.2e88d91a.png => wk2.BasdNK2d.png} (100%) rename assets/{wk3.975bc38e.png => wk3.CWstwLHH.png} (100%) rename assets/{wk4.004be17f.png => wk4.K5XvE6uQ.png} (100%) rename assets/{wk5.6cdba880.png => wk5.BEJ5BAWW.png} (100%) rename assets/{wk6.667c5c95.png => wk6.D9MKwk3w.png} (100%) rename assets/{wk7.38e3cd7d.png => wk7.B0gH-0gL.png} (100%) rename assets/{wv1.5ac4a026.png => wv1.8ARiSJ9x.png} (100%) create mode 100644 vp-icons.css diff --git a/404.html b/404.html index cd3cd20b2b..16ceb43c30 100644 --- a/404.html +++ b/404.html @@ -5,19 +5,22 @@ 404 | 一键虚拟化项目 - + + + - - + + - + + -
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
- +
+ \ No newline at end of file diff --git a/assets/a1.662d9415.png b/assets/a1.DvgNELwZ.png similarity index 100% rename from assets/a1.662d9415.png rename to assets/a1.DvgNELwZ.png diff --git a/assets/a10.36860678.png b/assets/a10.CPK2ZJEJ.png similarity index 100% rename from assets/a10.36860678.png rename to assets/a10.CPK2ZJEJ.png diff --git a/assets/a11.bbc20080.png b/assets/a11.Bq6vmveu.png similarity index 100% rename from assets/a11.bbc20080.png rename to assets/a11.Bq6vmveu.png diff --git a/assets/a12.da46fe54.png b/assets/a12.bStrZLWw.png similarity index 100% rename from assets/a12.da46fe54.png rename to assets/a12.bStrZLWw.png diff --git a/assets/a13.b49276aa.png b/assets/a13.DRz8WTJR.png similarity index 100% rename from assets/a13.b49276aa.png rename to assets/a13.DRz8WTJR.png diff --git a/assets/a14.908480a6.png b/assets/a14.D56M6gMb.png similarity index 100% rename from assets/a14.908480a6.png rename to assets/a14.D56M6gMb.png diff --git a/assets/a15.9533f30d.png b/assets/a15.CtjmUhal.png similarity index 100% rename from assets/a15.9533f30d.png rename to assets/a15.CtjmUhal.png diff --git a/assets/a16.2257f2d8.png b/assets/a16.BL0_sgNg.png similarity index 100% rename from assets/a16.2257f2d8.png rename to assets/a16.BL0_sgNg.png diff --git a/assets/a17.b57c7755.png b/assets/a17.B9keXK9k.png similarity index 100% rename from assets/a17.b57c7755.png rename to assets/a17.B9keXK9k.png diff --git a/assets/a18.c3a22602.png b/assets/a18.Bu92JFv5.png similarity index 100% rename from assets/a18.c3a22602.png rename to assets/a18.Bu92JFv5.png diff --git a/assets/a19.1eefd81d.png b/assets/a19.DZjr60Xs.png similarity index 100% rename from assets/a19.1eefd81d.png rename to assets/a19.DZjr60Xs.png diff --git a/assets/a2.1d7d86db.png b/assets/a2.BQniQEw_.png similarity index 100% rename from assets/a2.1d7d86db.png rename to assets/a2.BQniQEw_.png diff --git a/assets/a20.24042237.png b/assets/a20.CesdkIR_.png similarity index 100% rename from assets/a20.24042237.png rename to assets/a20.CesdkIR_.png diff --git a/assets/a21.2bb37c9a.png b/assets/a21.BO8sy8n4.png similarity index 100% rename from assets/a21.2bb37c9a.png rename to assets/a21.BO8sy8n4.png diff --git a/assets/a22.44ab6d75.png b/assets/a22.COjD9r-B.png similarity index 100% rename from assets/a22.44ab6d75.png rename to assets/a22.COjD9r-B.png diff --git a/assets/a23.191de0ca.png b/assets/a23.BxEEAckp.png similarity index 100% rename from assets/a23.191de0ca.png rename to assets/a23.BxEEAckp.png diff --git a/assets/a24.d2a9c729.png b/assets/a24.BrCKYLHX.png similarity index 100% rename from assets/a24.d2a9c729.png rename to assets/a24.BrCKYLHX.png diff --git a/assets/a25.3e24d99b.png b/assets/a25.CUB6zoiS.png similarity index 100% rename from assets/a25.3e24d99b.png rename to assets/a25.CUB6zoiS.png diff --git a/assets/a26.2fce6332.png b/assets/a26.zvaFRs59.png similarity index 100% rename from assets/a26.2fce6332.png rename to assets/a26.zvaFRs59.png diff --git a/assets/a27.dd61884c.png b/assets/a27.QkS9Cjl7.png similarity index 100% rename from assets/a27.dd61884c.png rename to assets/a27.QkS9Cjl7.png diff --git a/assets/a3.178777a1.png b/assets/a3.DHUpjnAe.png similarity index 100% rename from assets/a3.178777a1.png rename to assets/a3.DHUpjnAe.png diff --git a/assets/a31.6d3a9d85.png b/assets/a31.BiCzGFMR.png similarity index 100% rename from assets/a31.6d3a9d85.png rename to assets/a31.BiCzGFMR.png diff --git a/assets/a32.d9973307.png b/assets/a32.54sdf1AZ.png similarity index 100% rename from assets/a32.d9973307.png rename to assets/a32.54sdf1AZ.png diff --git a/assets/a33.8b54ce3f.png b/assets/a33.QYBAXO71.png similarity index 100% rename from assets/a33.8b54ce3f.png rename to assets/a33.QYBAXO71.png diff --git a/assets/a34.07f5cc75.png b/assets/a34.BBqAz_kr.png similarity index 100% rename from assets/a34.07f5cc75.png rename to assets/a34.BBqAz_kr.png diff --git a/assets/a35.78be61d4.png b/assets/a35.B8NF_iJX.png similarity index 100% rename from assets/a35.78be61d4.png rename to assets/a35.B8NF_iJX.png diff --git a/assets/a36.a36765c2.png b/assets/a36.CPvsggxV.png similarity index 100% rename from assets/a36.a36765c2.png rename to assets/a36.CPvsggxV.png diff --git a/assets/a37.e6740eaa.png b/assets/a37.DJRI7pv9.png similarity index 100% rename from assets/a37.e6740eaa.png rename to assets/a37.DJRI7pv9.png diff --git a/assets/a38.999b4ffb.png b/assets/a38.BhfuTk-3.png similarity index 100% rename from assets/a38.999b4ffb.png rename to assets/a38.BhfuTk-3.png diff --git a/assets/a39.9dac95e1.png b/assets/a39.BNtfZ4xd.png similarity index 100% rename from assets/a39.9dac95e1.png rename to assets/a39.BNtfZ4xd.png diff --git a/assets/a4.65c15963.png b/assets/a4.BtVJtyBL.png similarity index 100% rename from assets/a4.65c15963.png rename to assets/a4.BtVJtyBL.png diff --git a/assets/a40.7f5ad4ea.png b/assets/a40.DTfyEQe2.png similarity index 100% rename from assets/a40.7f5ad4ea.png rename to assets/a40.DTfyEQe2.png diff --git a/assets/a41.bbc5e317.png b/assets/a41.Cb6MjiUm.png similarity index 100% rename from assets/a41.bbc5e317.png rename to assets/a41.Cb6MjiUm.png diff --git a/assets/a42.de7d1da7.png b/assets/a42.Du63tHI8.png similarity index 100% rename from assets/a42.de7d1da7.png rename to assets/a42.Du63tHI8.png diff --git a/assets/a43.e713599d.png b/assets/a43.Cxy9Fqxr.png similarity index 100% rename from assets/a43.e713599d.png rename to assets/a43.Cxy9Fqxr.png diff --git a/assets/a44.5c4e5e0a.png b/assets/a44.Dhcgau_f.png similarity index 100% rename from assets/a44.5c4e5e0a.png rename to assets/a44.Dhcgau_f.png diff --git a/assets/a45.2c32612e.png b/assets/a45.DQgcLv5f.png similarity index 100% rename from assets/a45.2c32612e.png rename to assets/a45.DQgcLv5f.png diff --git a/assets/a5.01b8514f.png b/assets/a5.CamDlEuL.png similarity index 100% rename from assets/a5.01b8514f.png rename to assets/a5.CamDlEuL.png diff --git a/assets/a6.67efded0.png b/assets/a6.auUigeOH.png similarity index 100% rename from assets/a6.67efded0.png rename to assets/a6.auUigeOH.png diff --git a/assets/a7.b8de9a6c.png b/assets/a7.3_Is3HF1.png similarity index 100% rename from assets/a7.b8de9a6c.png rename to assets/a7.3_Is3HF1.png diff --git a/assets/a8.69056d9a.png b/assets/a8.CkyIulFy.png similarity index 100% rename from assets/a8.69056d9a.png rename to assets/a8.CkyIulFy.png diff --git a/assets/a9.d4cc5fc0.png b/assets/a9.Dg58RrTs.png similarity index 100% rename from assets/a9.d4cc5fc0.png rename to assets/a9.Dg58RrTs.png diff --git a/assets/app.7da1868b.js b/assets/app.7da1868b.js deleted file mode 100644 index 6c429eae15..0000000000 --- a/assets/app.7da1868b.js +++ /dev/null @@ -1 +0,0 @@ -import{u as i,I as o,a2 as p,c as u,A as c,H as l,a3 as f,a4 as d,a5 as m,a6 as A,a7 as h,a8 as g,a9 as P,aa as v,ab as y,ac as C,ad as _,ae as b,af as w,S as D}from"./chunks/framework.70afa331.js";import{t as E}from"./chunks/theme.b9d97670.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=r(E),R=i({name:"VitePressApp",setup(){const{site:e}=u();return c(()=>{l(()=>{document.documentElement.lang=e.value.lang,document.documentElement.dir=e.value.dir})}),f(),d(),m(),s.setup&&s.setup(),()=>A(s.Layout)}});async function O(){const e=j(),a=T();a.provide(h,e);const t=g(e.route);return a.provide(P,t),a.component("Content",v),a.component("ClientOnly",y),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:C}),{app:a,router:e,data:t}}function T(){return _(R)}function j(){let e=o,a;return b(t=>{let n=w(t);return n?(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),o&&(e=!1),D(()=>import(n),[])):null},s.NotFound)}o&&O().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{O as createApp}; diff --git a/assets/app.D4kLJnX4.js b/assets/app.D4kLJnX4.js new file mode 100644 index 0000000000..5f65d00de9 --- /dev/null +++ b/assets/app.D4kLJnX4.js @@ -0,0 +1 @@ +import{t as p}from"./chunks/theme.DJQtrHna.js";import{R as s,a2 as i,a3 as u,a4 as c,a5 as l,a6 as f,a7 as d,a8 as m,a9 as h,aa as g,ab as A,d as v,u as y,v as C,s as P,ac as b,ad as w,ae as R,af as E}from"./chunks/framework.CSeR4K32.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(p),S=v({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=y();return C(()=>{P(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&b(),w(),R(),n.setup&&n.setup(),()=>E(n.Layout)}});async function T(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function D(){return A(S)}function _(){let e=s;return h(a=>{let t=g(a),o=null;return t&&(e&&(t=t.replace(/\.js$/,".lean.js")),o=import(t)),s&&(e=!1),o},n.NotFound)}s&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{T as createApp}; diff --git a/assets/ar.0d8bb8f3.png b/assets/ar.Dy_5EjFU.png similarity index 100% rename from assets/ar.0d8bb8f3.png rename to assets/ar.Dy_5EjFU.png diff --git a/assets/b1.c1fdb506.png b/assets/b1.CSqggjTM.png similarity index 100% rename from assets/b1.c1fdb506.png rename to assets/b1.CSqggjTM.png diff --git a/assets/b10.52a93636.png b/assets/b10.DGHfd73s.png similarity index 100% rename from assets/b10.52a93636.png rename to assets/b10.DGHfd73s.png diff --git a/assets/b11.2e525d8d.png b/assets/b11.DKZjwgY8.png similarity index 100% rename from assets/b11.2e525d8d.png rename to assets/b11.DKZjwgY8.png diff --git a/assets/b12.54c3189d.png b/assets/b12.BISDj2Ri.png similarity index 100% rename from assets/b12.54c3189d.png rename to assets/b12.BISDj2Ri.png diff --git a/assets/b13.3b3ae784.png b/assets/b13.WGr5jMeK.png similarity index 100% rename from assets/b13.3b3ae784.png rename to assets/b13.WGr5jMeK.png diff --git a/assets/b14.662b1a1b.png b/assets/b14.BqBpvoFk.png similarity index 100% rename from assets/b14.662b1a1b.png rename to assets/b14.BqBpvoFk.png diff --git a/assets/b15.0c5536d8.png b/assets/b15.Cd3Rj7ju.png similarity index 100% rename from assets/b15.0c5536d8.png rename to assets/b15.Cd3Rj7ju.png diff --git a/assets/b16.0fbcfcb1.png b/assets/b16.BR7AHi1X.png similarity index 100% rename from assets/b16.0fbcfcb1.png rename to assets/b16.BR7AHi1X.png diff --git a/assets/b17.4e7429fe.png b/assets/b17.Cn1C4e1e.png similarity index 100% rename from assets/b17.4e7429fe.png rename to assets/b17.Cn1C4e1e.png diff --git a/assets/b18.8211f293.png b/assets/b18.ElAa2UCQ.png similarity index 100% rename from assets/b18.8211f293.png rename to assets/b18.ElAa2UCQ.png diff --git a/assets/b19.2128d0fa.png b/assets/b19.BwC-oHOW.png similarity index 100% rename from assets/b19.2128d0fa.png rename to assets/b19.BwC-oHOW.png diff --git a/assets/b2.519a9bf0.png b/assets/b2.BnvPQMj3.png similarity index 100% rename from assets/b2.519a9bf0.png rename to assets/b2.BnvPQMj3.png diff --git a/assets/b20.8a62698b.png b/assets/b20.Dj-0rOwy.png similarity index 100% rename from assets/b20.8a62698b.png rename to assets/b20.Dj-0rOwy.png diff --git a/assets/b21.dfe1e8f0.png b/assets/b21.CYRPkSXE.png similarity index 100% rename from assets/b21.dfe1e8f0.png rename to assets/b21.CYRPkSXE.png diff --git a/assets/b22.13e3438c.png b/assets/b22.BH7kRZ3Z.png similarity index 100% rename from assets/b22.13e3438c.png rename to assets/b22.BH7kRZ3Z.png diff --git a/assets/b23.e293a560.png b/assets/b23.JVX-KOL7.png similarity index 100% rename from assets/b23.e293a560.png rename to assets/b23.JVX-KOL7.png diff --git a/assets/b24.23cbc29a.png b/assets/b24.a2fv8lkf.png similarity index 100% rename from assets/b24.23cbc29a.png rename to assets/b24.a2fv8lkf.png diff --git a/assets/b25.f2c2ebd7.png b/assets/b25.BJrNgkiA.png similarity index 100% rename from assets/b25.f2c2ebd7.png rename to assets/b25.BJrNgkiA.png diff --git a/assets/b26.b7136167.png b/assets/b26.5bTO5HK5.png similarity index 100% rename from assets/b26.b7136167.png rename to assets/b26.5bTO5HK5.png diff --git a/assets/b27.cc8f8644.png b/assets/b27.BSRz6moE.png similarity index 100% rename from assets/b27.cc8f8644.png rename to assets/b27.BSRz6moE.png diff --git a/assets/b28.2bf4d8b9.png b/assets/b28.WNjJaEPB.png similarity index 100% rename from assets/b28.2bf4d8b9.png rename to assets/b28.WNjJaEPB.png diff --git a/assets/b29.8d301c10.png b/assets/b29.Bs69Ykqp.png similarity index 100% rename from assets/b29.8d301c10.png rename to assets/b29.Bs69Ykqp.png diff --git a/assets/b3.42fd37a2.png b/assets/b3.DPn2dzFl.png similarity index 100% rename from assets/b3.42fd37a2.png rename to assets/b3.DPn2dzFl.png diff --git a/assets/b30.a50bc8f3.png b/assets/b30.B96bh_Ou.png similarity index 100% rename from assets/b30.a50bc8f3.png rename to assets/b30.B96bh_Ou.png diff --git a/assets/b31.4881ca1d.png b/assets/b31.BBIAIScF.png similarity index 100% rename from assets/b31.4881ca1d.png rename to assets/b31.BBIAIScF.png diff --git a/assets/b32.b857654b.png b/assets/b32.8G5Xy9mr.png similarity index 100% rename from assets/b32.b857654b.png rename to assets/b32.8G5Xy9mr.png diff --git a/assets/b33.1125a81c.png b/assets/b33.RYxcR7vu.png similarity index 100% rename from assets/b33.1125a81c.png rename to assets/b33.RYxcR7vu.png diff --git a/assets/b34.2101ce9a.png b/assets/b34.Dw6MyLex.png similarity index 100% rename from assets/b34.2101ce9a.png rename to assets/b34.Dw6MyLex.png diff --git a/assets/b35.83c5a766.png b/assets/b35.DUCPsVIG.png similarity index 100% rename from assets/b35.83c5a766.png rename to assets/b35.DUCPsVIG.png diff --git a/assets/b36.ea1f048c.png b/assets/b36.7aKaNaLh.png similarity index 100% rename from assets/b36.ea1f048c.png rename to assets/b36.7aKaNaLh.png diff --git a/assets/b37.b60405a9.png b/assets/b37.B5CHAJzN.png similarity index 100% rename from assets/b37.b60405a9.png rename to assets/b37.B5CHAJzN.png diff --git a/assets/b38.4d73fbe3.png b/assets/b38.Pnnij22W.png similarity index 100% rename from assets/b38.4d73fbe3.png rename to assets/b38.Pnnij22W.png diff --git a/assets/b39.c59ccabe.png b/assets/b39.ajiHDdbx.png similarity index 100% rename from assets/b39.c59ccabe.png rename to assets/b39.ajiHDdbx.png diff --git a/assets/b4.b6d283a7.png b/assets/b4.JBQupWN9.png similarity index 100% rename from assets/b4.b6d283a7.png rename to assets/b4.JBQupWN9.png diff --git a/assets/b40.c1d0ee00.png b/assets/b40.B6FTkFUT.png similarity index 100% rename from assets/b40.c1d0ee00.png rename to assets/b40.B6FTkFUT.png diff --git a/assets/b41.0c6d7432.png b/assets/b41.DcCdod5l.png similarity index 100% rename from assets/b41.0c6d7432.png rename to assets/b41.DcCdod5l.png diff --git a/assets/b42.66cc353b.png b/assets/b42.CT1JvTLX.png similarity index 100% rename from assets/b42.66cc353b.png rename to assets/b42.CT1JvTLX.png diff --git a/assets/b43.a775b641.png b/assets/b43.HthhPs5o.png similarity index 100% rename from assets/b43.a775b641.png rename to assets/b43.HthhPs5o.png diff --git a/assets/b44.2d540844.png b/assets/b44.C9NeP-UC.png similarity index 100% rename from assets/b44.2d540844.png rename to assets/b44.C9NeP-UC.png diff --git a/assets/b45.fe0240c6.png b/assets/b45.BWxBBH-l.png similarity index 100% rename from assets/b45.fe0240c6.png rename to assets/b45.BWxBBH-l.png diff --git a/assets/b46.f6b9da14.png b/assets/b46.B6Ds58im.png similarity index 100% rename from assets/b46.f6b9da14.png rename to assets/b46.B6Ds58im.png diff --git a/assets/b5.4cd5361f.png b/assets/b5.DeuT9J-4.png similarity index 100% rename from assets/b5.4cd5361f.png rename to assets/b5.DeuT9J-4.png diff --git a/assets/b6.36f0470d.png b/assets/b6.cZYHMwJ8.png similarity index 100% rename from assets/b6.36f0470d.png rename to assets/b6.cZYHMwJ8.png diff --git a/assets/b7.9714bb16.png b/assets/b7.5Fkbt05C.png similarity index 100% rename from assets/b7.9714bb16.png rename to assets/b7.5Fkbt05C.png diff --git a/assets/b8.2eb373bf.png b/assets/b8.BXlK1Dnb.png similarity index 100% rename from assets/b8.2eb373bf.png rename to assets/b8.BXlK1Dnb.png diff --git a/assets/b9.3f01ffdc.png b/assets/b9.CaK5eLKm.png similarity index 100% rename from assets/b9.3f01ffdc.png rename to assets/b9.CaK5eLKm.png diff --git a/assets/br.bb3418b4.png b/assets/br.CyzpZwsx.png similarity index 100% rename from assets/br.bb3418b4.png rename to assets/br.CyzpZwsx.png diff --git a/assets/case_case1.md.3cf726ff.js b/assets/case_case1.md.3cf726ff.js deleted file mode 100644 index df78364cc0..0000000000 --- a/assets/case_case1.md.3cf726ff.js +++ /dev/null @@ -1,58 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case1.md","filePath":"case/case1.md","lastUpdated":1747972048000}'),o={name:"case/case1.md"},p=l(`

仓库

Hits

Hits

融合怪测评项目

(GO版本除非必须的环境安装使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖也可全测项目)

如有问题请 issues 反馈。

Go 版本:https://github.com/oneclickvirt/ecs

Shell 版本:https://github.com/spiritLHLS/ecs


适配系统和架构

编译与测试支持情况

编译支持的架构测试支持的架构编译支持的系统测试支持的系统
amd64amd64LinuxLinux
armarmWindowsWindows
arm64arm64FreeBSDFreeBSD
386386OpenBSD
mipsMacOS
mipsle
s390xs390x
riscv64

功能

本项目初次使用建议查看说明:跳转


使用说明

Linux/FreeBSD/OpenBSD/MacOS

一键命令

一键命令默认安装依赖默认更新包管理器默认非互动模式

详细说明

详细说明中的命令可控制是否安装依赖是否更新包管理器默认互动模式可进行选择

  1. 下载脚本

    国际用户无加速:

    bash
    curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国际/国内使用 CDN 加速:

    bash
    curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国内用户使用 CNB 加速:

    bash
    curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
  2. 更新包管理器(可选择)并安装环境

    bash
    ./goecs.sh env

    非互动模式:

    bash
    export noninteractive=true && ./goecs.sh env
  3. 安装 goecs

    bash
    ./goecs.sh install
  4. 升级 goecs

    bash
    ./goecs.sh upgrade
  5. 卸载 goecs

    bash
    ./goecs.sh uninstall
  6. 帮助命令

    bash
    ./goecs.sh -h
  7. 唤起菜单

    bash
    goecs

命令参数化

bash
Usage: goecs [options]
-  -backtrace
-        Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
-  -basic
-        Enable/Disable basic test (default true)
-  -comm
-        Enable/Disable common media test (default true)
-  -cpu
-        Enable/Disable CPU test (default true)
-  -cpum string
-        Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
-  -cput string
-        Set CPU test thread mode (supported: single, multi) (default "multi")
-  -disk
-        Enable/Disable disk test (default true)
-  -diskm string
-        Set disk test method (supported: fio, dd, winsat) (default "fio")
-  -diskmc
-        Enable/Disable multiple disk checks, e.g., -diskmc=false
-  -diskp string
-        Set disk test path, e.g., -diskp /root
-  -email
-        Enable/Disable email port test (default true)
-  -h    Show help information
-  -l string
-        Set language (supported: en, zh) (default "zh")
-  -log
-        Enable/Disable logging in the current path
-  -memory
-        Enable/Disable memory test (default true)
-  -memorym string
-        Set memory test method (supported: sysbench, dd, winsat) (default "sysbench")
-  -menu
-        Enable/Disable menu mode, disable example: -menu=false (default true)
-  -nt3
-        Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
-  -nt3loc string
-        Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
-  -nt3t string
-        Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
-  -security
-        Enable/Disable security test (default true)
-  -speed
-        Enable/Disable speed test (default true)
-  -spnum int
-        Set the number of servers per operator for speed test (default 2)
-  -upload
-        Enable/Disable upload the result (default true)
-  -ut
-        Enable/Disable unlock media test (default true)
-  -v    Display version information

Windows

  1. 下载带 exe 文件的压缩包:Releases
  2. 解压后,右键以管理员模式运行。

Docker

国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm spiritlhl/goecs:latest -menu=false -l zh

使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。

国内镜像地址:https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

从源码进行编译

  1. 克隆仓库的 public 分支(不含私有依赖)
bash
git clone -b public https://github.com/oneclickvirt/ecs.git
-cd ecs
  1. 安装 Go 环境(如已安装可跳过)
bash
# 下载并安装 Go
-wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
-rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
-export PATH=$PATH:/usr/local/go/bin
  1. 编译
bash
go build -o goecs
  1. 运行测试
bash
./goecs -menu=false -l zh

支持的编译参数:

跨平台编译示例:

bash
# 编译 Windows 版本
-GOOS=windows GOARCH=amd64 go build -o goecs.exe
-# 编译 MacOS 版本
-GOOS=darwin GOARCH=amd64 go build -o goecs_darwin

QA

Q: 为什么默认使用sysbench而不是geekbench

A: 比较二者特点

比较项sysbenchgeekbench
适用范围轻量级,几乎可在任何服务器上运行重量级,小型机器无法运行
测试要求无需网络,无特殊硬件需求需联网,IPV4环境,至少1G内存
开源情况基于LUA,开源,可自行编译各架构版本官方二进制闭源代码,不支持自行编译
测试稳定性核心测试组件10年以上未变每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU)
测试内容仅测试计算性能覆盖多种性能测试,分数加权计算,但部分测试实际不常用
适用场景适合快速测试,仅测试计算性能适合综合全面的测试

goecs测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求

Q: 为什么使用Golang而不是Rust重构

A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,我懒得搞我没那个技术力

Q: 为什么不继续开发Shell版本而是选择重构

A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)

Q: 每个测试项目的说明有吗?

A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明

Q: 测试进行到一半如何手动终止?

A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。

Q: 非Root环境如何进行测试?

A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。

致谢

感谢 he.net bgp.tools ipinfo.io ip.sb cheervision.co scamalytics.com abuseipdb.com virustotal.com ip2location.com ip-api.com ipregistry.co ipdata.co ipgeolocation.io ipwhois.io ipapi.com ipapi.is ipqualityscore.com bigdatacloud.com 等网站提供的API进行检测,感谢互联网各网站提供的查询资源

感谢

h501

提供的免费托管支持本开源项目的共享测试结果存储

同时感谢以下平台提供编辑和测试支持

golandibm`,84),e=[p];function t(r,c,C,y,D,A){return a(),n("div",null,e)}const d=s(o,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/case_case1.md.3cf726ff.lean.js b/assets/case_case1.md.3cf726ff.lean.js deleted file mode 100644 index df78364cc0..0000000000 --- a/assets/case_case1.md.3cf726ff.lean.js +++ /dev/null @@ -1,58 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case1.md","filePath":"case/case1.md","lastUpdated":1747972048000}'),o={name:"case/case1.md"},p=l(`

仓库

Hits

Hits

融合怪测评项目

(GO版本除非必须的环境安装使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖也可全测项目)

如有问题请 issues 反馈。

Go 版本:https://github.com/oneclickvirt/ecs

Shell 版本:https://github.com/spiritLHLS/ecs


适配系统和架构

编译与测试支持情况

编译支持的架构测试支持的架构编译支持的系统测试支持的系统
amd64amd64LinuxLinux
armarmWindowsWindows
arm64arm64FreeBSDFreeBSD
386386OpenBSD
mipsMacOS
mipsle
s390xs390x
riscv64

功能

本项目初次使用建议查看说明:跳转


使用说明

Linux/FreeBSD/OpenBSD/MacOS

一键命令

一键命令默认安装依赖默认更新包管理器默认非互动模式

详细说明

详细说明中的命令可控制是否安装依赖是否更新包管理器默认互动模式可进行选择

  1. 下载脚本

    国际用户无加速:

    bash
    curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国际/国内使用 CDN 加速:

    bash
    curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国内用户使用 CNB 加速:

    bash
    curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
  2. 更新包管理器(可选择)并安装环境

    bash
    ./goecs.sh env

    非互动模式:

    bash
    export noninteractive=true && ./goecs.sh env
  3. 安装 goecs

    bash
    ./goecs.sh install
  4. 升级 goecs

    bash
    ./goecs.sh upgrade
  5. 卸载 goecs

    bash
    ./goecs.sh uninstall
  6. 帮助命令

    bash
    ./goecs.sh -h
  7. 唤起菜单

    bash
    goecs

命令参数化

bash
Usage: goecs [options]
-  -backtrace
-        Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
-  -basic
-        Enable/Disable basic test (default true)
-  -comm
-        Enable/Disable common media test (default true)
-  -cpu
-        Enable/Disable CPU test (default true)
-  -cpum string
-        Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
-  -cput string
-        Set CPU test thread mode (supported: single, multi) (default "multi")
-  -disk
-        Enable/Disable disk test (default true)
-  -diskm string
-        Set disk test method (supported: fio, dd, winsat) (default "fio")
-  -diskmc
-        Enable/Disable multiple disk checks, e.g., -diskmc=false
-  -diskp string
-        Set disk test path, e.g., -diskp /root
-  -email
-        Enable/Disable email port test (default true)
-  -h    Show help information
-  -l string
-        Set language (supported: en, zh) (default "zh")
-  -log
-        Enable/Disable logging in the current path
-  -memory
-        Enable/Disable memory test (default true)
-  -memorym string
-        Set memory test method (supported: sysbench, dd, winsat) (default "sysbench")
-  -menu
-        Enable/Disable menu mode, disable example: -menu=false (default true)
-  -nt3
-        Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
-  -nt3loc string
-        Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
-  -nt3t string
-        Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
-  -security
-        Enable/Disable security test (default true)
-  -speed
-        Enable/Disable speed test (default true)
-  -spnum int
-        Set the number of servers per operator for speed test (default 2)
-  -upload
-        Enable/Disable upload the result (default true)
-  -ut
-        Enable/Disable unlock media test (default true)
-  -v    Display version information

Windows

  1. 下载带 exe 文件的压缩包:Releases
  2. 解压后,右键以管理员模式运行。

Docker

国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm spiritlhl/goecs:latest -menu=false -l zh

使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。

国内镜像地址:https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

从源码进行编译

  1. 克隆仓库的 public 分支(不含私有依赖)
bash
git clone -b public https://github.com/oneclickvirt/ecs.git
-cd ecs
  1. 安装 Go 环境(如已安装可跳过)
bash
# 下载并安装 Go
-wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
-rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
-export PATH=$PATH:/usr/local/go/bin
  1. 编译
bash
go build -o goecs
  1. 运行测试
bash
./goecs -menu=false -l zh

支持的编译参数:

跨平台编译示例:

bash
# 编译 Windows 版本
-GOOS=windows GOARCH=amd64 go build -o goecs.exe
-# 编译 MacOS 版本
-GOOS=darwin GOARCH=amd64 go build -o goecs_darwin

QA

Q: 为什么默认使用sysbench而不是geekbench

A: 比较二者特点

比较项sysbenchgeekbench
适用范围轻量级,几乎可在任何服务器上运行重量级,小型机器无法运行
测试要求无需网络,无特殊硬件需求需联网,IPV4环境,至少1G内存
开源情况基于LUA,开源,可自行编译各架构版本官方二进制闭源代码,不支持自行编译
测试稳定性核心测试组件10年以上未变每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU)
测试内容仅测试计算性能覆盖多种性能测试,分数加权计算,但部分测试实际不常用
适用场景适合快速测试,仅测试计算性能适合综合全面的测试

goecs测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求

Q: 为什么使用Golang而不是Rust重构

A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,我懒得搞我没那个技术力

Q: 为什么不继续开发Shell版本而是选择重构

A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)

Q: 每个测试项目的说明有吗?

A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明

Q: 测试进行到一半如何手动终止?

A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。

Q: 非Root环境如何进行测试?

A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。

致谢

感谢 he.net bgp.tools ipinfo.io ip.sb cheervision.co scamalytics.com abuseipdb.com virustotal.com ip2location.com ip-api.com ipregistry.co ipdata.co ipgeolocation.io ipwhois.io ipapi.com ipapi.is ipqualityscore.com bigdatacloud.com 等网站提供的API进行检测,感谢互联网各网站提供的查询资源

感谢

h501

提供的免费托管支持本开源项目的共享测试结果存储

同时感谢以下平台提供编辑和测试支持

golandibm`,84),e=[p];function t(r,c,C,y,D,A){return a(),n("div",null,e)}const d=s(o,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/case_case1.md.URFLodrr.js b/assets/case_case1.md.URFLodrr.js new file mode 100644 index 0000000000..0be3045e1c --- /dev/null +++ b/assets/case_case1.md.URFLodrr.js @@ -0,0 +1,58 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case1.md","filePath":"case/case1.md","lastUpdated":1747984962000}'),e={name:"case/case1.md"};function n(l,s,k,p,r,d){return t(),a("div",null,s[0]||(s[0]=[h(`

仓库

Hits

Hits

融合怪测评项目

(GO版本除非必须的环境安装使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖也可全测项目)

如有问题请 issues 反馈。

Go 版本:https://github.com/oneclickvirt/ecs

Shell 版本:https://github.com/spiritLHLS/ecs


适配系统和架构

编译与测试支持情况

编译支持的架构测试支持的架构编译支持的系统测试支持的系统
amd64amd64LinuxLinux
armarmWindowsWindows
arm64arm64FreeBSDFreeBSD
386386OpenBSD
mipsMacOS
mipsle
s390xs390x
riscv64

功能

本项目初次使用建议查看说明:跳转


使用说明

Linux/FreeBSD/OpenBSD/MacOS

一键命令

一键命令默认安装依赖默认更新包管理器默认非互动模式

详细说明

详细说明中的命令可控制是否安装依赖是否更新包管理器默认互动模式可进行选择

  1. 下载脚本

    国际用户无加速:

    bash
    curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国际/国内使用 CDN 加速:

    bash
    curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国内用户使用 CNB 加速:

    bash
    curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
  2. 更新包管理器(可选择)并安装环境

    bash
    ./goecs.sh env

    非互动模式:

    bash
    export noninteractive=true && ./goecs.sh env
  3. 安装 goecs

    bash
    ./goecs.sh install
  4. 升级 goecs

    bash
    ./goecs.sh upgrade
  5. 卸载 goecs

    bash
    ./goecs.sh uninstall
  6. 帮助命令

    bash
    ./goecs.sh -h
  7. 唤起菜单

    bash
    goecs

命令参数化

bash
Usage: goecs [options]
+  -backtrace
+        Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
+  -basic
+        Enable/Disable basic test (default true)
+  -comm
+        Enable/Disable common media test (default true)
+  -cpu
+        Enable/Disable CPU test (default true)
+  -cpum string
+        Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
+  -cput string
+        Set CPU test thread mode (supported: single, multi) (default "multi")
+  -disk
+        Enable/Disable disk test (default true)
+  -diskm string
+        Set disk test method (supported: fio, dd, winsat) (default "fio")
+  -diskmc
+        Enable/Disable multiple disk checks, e.g., -diskmc=false
+  -diskp string
+        Set disk test path, e.g., -diskp /root
+  -email
+        Enable/Disable email port test (default true)
+  -h    Show help information
+  -l string
+        Set language (supported: en, zh) (default "zh")
+  -log
+        Enable/Disable logging in the current path
+  -memory
+        Enable/Disable memory test (default true)
+  -memorym string
+        Set memory test method (supported: sysbench, dd, winsat) (default "sysbench")
+  -menu
+        Enable/Disable menu mode, disable example: -menu=false (default true)
+  -nt3
+        Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
+  -nt3loc string
+        Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
+  -nt3t string
+        Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
+  -security
+        Enable/Disable security test (default true)
+  -speed
+        Enable/Disable speed test (default true)
+  -spnum int
+        Set the number of servers per operator for speed test (default 2)
+  -upload
+        Enable/Disable upload the result (default true)
+  -ut
+        Enable/Disable unlock media test (default true)
+  -v    Display version information

Windows

  1. 下载带 exe 文件的压缩包:Releases
  2. 解压后,右键以管理员模式运行。

Docker

国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm spiritlhl/goecs:latest -menu=false -l zh

使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。

国内镜像地址:https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

从源码进行编译

  1. 克隆仓库的 public 分支(不含私有依赖)
bash
git clone -b public https://github.com/oneclickvirt/ecs.git
+cd ecs
  1. 安装 Go 环境(如已安装可跳过)
bash
# 下载并安装 Go
+wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
+rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
+export PATH=$PATH:/usr/local/go/bin
  1. 编译
bash
go build -o goecs
  1. 运行测试
bash
./goecs -menu=false -l zh

支持的编译参数:

跨平台编译示例:

bash
# 编译 Windows 版本
+GOOS=windows GOARCH=amd64 go build -o goecs.exe
+# 编译 MacOS 版本
+GOOS=darwin GOARCH=amd64 go build -o goecs_darwin

QA

Q: 为什么默认使用sysbench而不是geekbench

A: 比较二者特点

比较项sysbenchgeekbench
适用范围轻量级,几乎可在任何服务器上运行重量级,小型机器无法运行
测试要求无需网络,无特殊硬件需求需联网,IPV4环境,至少1G内存
开源情况基于LUA,开源,可自行编译各架构版本官方二进制闭源代码,不支持自行编译
测试稳定性核心测试组件10年以上未变每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU)
测试内容仅测试计算性能覆盖多种性能测试,分数加权计算,但部分测试实际不常用
适用场景适合快速测试,仅测试计算性能适合综合全面的测试

goecs测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求

Q: 为什么使用Golang而不是Rust重构

A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,我懒得搞我没那个技术力

Q: 为什么不继续开发Shell版本而是选择重构

A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)

Q: 每个测试项目的说明有吗?

A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明

Q: 测试进行到一半如何手动终止?

A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。

Q: 非Root环境如何进行测试?

A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。

致谢

感谢 he.net bgp.tools ipinfo.io ip.sb cheervision.co scamalytics.com abuseipdb.com virustotal.com ip2location.com ip-api.com ipregistry.co ipdata.co ipgeolocation.io ipwhois.io ipapi.com ipapi.is ipqualityscore.com bigdatacloud.com 等网站提供的API进行检测,感谢互联网各网站提供的查询资源

感谢

h501

提供的免费托管支持本开源项目的共享测试结果存储

同时感谢以下平台提供编辑和测试支持

golandibm`,84)]))}const o=i(e,[["render",n]]);export{g as __pageData,o as default}; diff --git a/assets/case_case1.md.URFLodrr.lean.js b/assets/case_case1.md.URFLodrr.lean.js new file mode 100644 index 0000000000..a039670cb9 --- /dev/null +++ b/assets/case_case1.md.URFLodrr.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case1.md","filePath":"case/case1.md","lastUpdated":1747984962000}'),e={name:"case/case1.md"};function n(l,s,k,p,r,d){return t(),a("div",null,s[0]||(s[0]=[h("",84)]))}const o=i(e,[["render",n]]);export{g as __pageData,o as default}; diff --git a/assets/case_case2.md.CDLx6tKM.js b/assets/case_case2.md.CDLx6tKM.js new file mode 100644 index 0000000000..0b2a669960 --- /dev/null +++ b/assets/case_case2.md.CDLx6tKM.js @@ -0,0 +1,36 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const F=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case2.md","filePath":"case/case2.md","lastUpdated":1747984962000}'),h={name:"case/case2.md"};function l(e,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[n(`

仓库

https://github.com/spiritLHLS/one-click-installation-script

Hits

所有脚本如需在国内服务器使用,请在链接前加上https://ghproxy.com/确保命令可以下载本仓库的shell脚本执行

一键修复脚本

运行所有一键修复脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键尝试修复apt源

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/package.sh -o package.sh && chmod +x package.sh && bash package.sh

一键尝试修复系统时间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/modify_time.sh -o modify_time.sh && chmod +x modify_time.sh && bash modify_time.sh

一键尝试修复sudo警告

不要在生产环境上使用该脚本,否则容易造成网络hosts配置错误,配置的host名字不在外网IP上反而在内网IP(127.0.0.1)上

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/check_sudo.sh -o check_sudo.sh && chmod +x check_sudo.sh && bash check_sudo.sh

一键修改系统自带的journal日志记录大小释放系统盘空间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/resize_journal.sh -o resize_journal.sh && chmod +x resize_journal.sh && bash resize_journal.sh

一键尝试修复网络

该脚本轻易勿要使用,请确保运行时服务器无重要文件或程序,出现运行bug后续可能需要重装系统

一定要在screen中执行该脚本,否则可能导致修改过程中ssh断链接而修改失败卡住最终SSH无法连接!不在screen中执行后果自负!

bash
curl -L https://cdn.spiritlhl.workers.dev/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/network.sh -o network.sh && chmod +x network.sh && bash network.sh

如果是纯V6的也可以不使用上面脚本的nat64,使用warp添加V4网络

比如:https://github.com/fscarmen/warp

bash
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh [option] [lisence]

非纯V6的,带V4切换优先级到IPV4可用以下命令

bash
sudo sed -i 's/.*precedence ::ffff:0:0\\/96.*/precedence ::ffff:0:0\\/96  100/g' /etc/gai.conf && sudo systemctl restart networking

一键环境安装脚本

只推荐在新服务器上安装,环境不纯净不保证不出bug

运行所有一键环境安装脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键安装jupyter环境

原始用途是方便快捷的在按小时计费的超大型服务器上部署python环境进行科学计算,充分利用时间别浪费在构建环境上。

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/jupyter.sh -o jupyter.sh && chmod +x jupyter.sh && bash jupyter.sh

一键安装R语言环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/R.sh -o R.sh && chmod +x R.sh && bash R.sh

一键安装rust环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/rust.sh -o rust.sh && chmod +x rust.sh && bash rust.sh

一键安装C环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/cplusplus.sh -o cplusplus.sh && chmod +x cplusplus.sh && bash cplusplus.sh

一键安装vnstat环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/vnstat.sh -o vnstat.sh && chmod +x vnstat.sh && bash vnstat.sh

一键升级低版本debian为debian11

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/todebian11.sh -o todebian11.sh && chmod +x todebian11.sh && bash todebian11.sh

一键升级低版本ubuntu为ubuntu22

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/toubuntu22.sh -o toubuntu22.sh && chmod +x toubuntu22.sh && bash toubuntu22.sh

一键安装zipline平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/zipline.sh -o zipline.sh && chmod +x zipline.sh && bash zipline.sh

如果需要删除0字节文件,打开/root/zipline文件夹,执行

docker-compose exec zipline yarn scripts:clear-zero-byte

按照提示操作

一键安装filebrowser平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/filebrowser.sh -o filebrowser.sh && chmod +x filebrowser.sh && bash filebrowser.sh

一键删除平台监控

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/dlm.sh -o dlm.sh && chmod +x dlm.shh && bash dlm.sh

部分手动命令

一键开启root登陆并替换密码

bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

一键屏蔽邮件端口避免被恶意程序使用

bash
iptables -A INPUT -p tcp --dport 25 -j DROP
+iptables -A OUTPUT -p tcp --dport 25 -j DROP
+/sbin/iptables-save

设置语言包

bash
sudo apt-get update
+sudo apt-get install language-pack-en-base
+sudo locale-gen en_US.UTF-8

下载UTF-8的环境,生成UTF-8的包,然后重启服务器

bash
locale -a
+export LC_ALL=en_US.UTF-8

查看并设置语言包

language-pack-en-base 在debian中好像没有,只有Ubuntu有好像,不知道是不是个例,有问题再说

ubuntu更新源被锁

bash
sudo rm -rf /var/cache/apt/archives/lock
+sudo pkill apt
+sudo rm /var/lib/dpkg/lock-frontend
+sudo rm /var/lib/apt/lists/lock
+sudo rm /var/cache/apt/archives/lock
+sudo rm /var/lib/dpkg/lock
+sudo dpkg --configure -a

然后重启系统

debian缺失公钥

bash
apt-get install debian-keyring debian-archive-keyring -y

ubuntu或debian缺失公钥

后续这块有计划整理为一个一键脚本

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 公钥

centos换源

bash
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
+sudo sed -i 's/^mirrorlist=http/mirrorlist=https/' /etc/yum.repos.d/CentOS-Base.repo

安装gitea

Ubuntu 20无问题,Ubuntu 22好像不行

https://gitlab.com/packaging/gitea

卸载aapanel

bash
apt install sysv-rc-conf -y && service bt stop && sysv-rc-conf bt off && rm -f /etc/init.d/bt && rm -rf /www/server/panel

安装docker和docker-compose

bash
curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

卸载所有docker镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

通过docker安装code-server

安装

shell
mkdir -p ~/.config
+docker run --restart=always --name code-server -p 0.0.0.0:8886:8080 \\
+  -v "$HOME/.config:/home/coder/.config" \\
+  -v "$PWD:/home/coder/project" \\
+  -u "$(id -u):$(id -g)" \\
+  -e "DOCKER_USER=$USER" \\
+  codercom/code-server:latest

新窗口

shell
docker exec code-server cat /root/.config/code-server/config.yaml

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
+sudo systemctl enable --now code-server@root
+sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
+sudo systemctl restart code-server@root
+cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
+sudo systemctl disable code-server@root
+rm -rf ~/.cache/coder
+sudo apt remove coder -y

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
+sudo systemctl enable --now code-server@root
+sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
+sudo systemctl restart code-server@root
+cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
+sudo systemctl disable code-server@root
+rm -rf ~/.cache/coder
+sudo apt remove coder -y
`,109)]))}const c=i(h,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/case_case2.md.CDLx6tKM.lean.js b/assets/case_case2.md.CDLx6tKM.lean.js new file mode 100644 index 0000000000..70bbb6800a --- /dev/null +++ b/assets/case_case2.md.CDLx6tKM.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const F=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case2.md","filePath":"case/case2.md","lastUpdated":1747984962000}'),h={name:"case/case2.md"};function l(e,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[n("",109)]))}const c=i(h,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/case_case2.md.d9673a40.js b/assets/case_case2.md.d9673a40.js deleted file mode 100644 index 2e8ce75bc8..0000000000 --- a/assets/case_case2.md.d9673a40.js +++ /dev/null @@ -1,36 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case2.md","filePath":"case/case2.md","lastUpdated":1747972048000}'),o={name:"case/case2.md"},p=n(`

仓库

https://github.com/spiritLHLS/one-click-installation-script

Hits

所有脚本如需在国内服务器使用,请在链接前加上https://ghproxy.com/确保命令可以下载本仓库的shell脚本执行

一键修复脚本

运行所有一键修复脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键尝试修复apt源

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/package.sh -o package.sh && chmod +x package.sh && bash package.sh

一键尝试修复系统时间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/modify_time.sh -o modify_time.sh && chmod +x modify_time.sh && bash modify_time.sh

一键尝试修复sudo警告

不要在生产环境上使用该脚本,否则容易造成网络hosts配置错误,配置的host名字不在外网IP上反而在内网IP(127.0.0.1)上

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/check_sudo.sh -o check_sudo.sh && chmod +x check_sudo.sh && bash check_sudo.sh

一键修改系统自带的journal日志记录大小释放系统盘空间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/resize_journal.sh -o resize_journal.sh && chmod +x resize_journal.sh && bash resize_journal.sh

一键尝试修复网络

该脚本轻易勿要使用,请确保运行时服务器无重要文件或程序,出现运行bug后续可能需要重装系统

一定要在screen中执行该脚本,否则可能导致修改过程中ssh断链接而修改失败卡住最终SSH无法连接!不在screen中执行后果自负!

bash
curl -L https://cdn.spiritlhl.workers.dev/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/network.sh -o network.sh && chmod +x network.sh && bash network.sh

如果是纯V6的也可以不使用上面脚本的nat64,使用warp添加V4网络

比如:https://github.com/fscarmen/warp

bash
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh [option] [lisence]

非纯V6的,带V4切换优先级到IPV4可用以下命令

bash
sudo sed -i 's/.*precedence ::ffff:0:0\\/96.*/precedence ::ffff:0:0\\/96  100/g' /etc/gai.conf && sudo systemctl restart networking

一键环境安装脚本

只推荐在新服务器上安装,环境不纯净不保证不出bug

运行所有一键环境安装脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键安装jupyter环境

原始用途是方便快捷的在按小时计费的超大型服务器上部署python环境进行科学计算,充分利用时间别浪费在构建环境上。

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/jupyter.sh -o jupyter.sh && chmod +x jupyter.sh && bash jupyter.sh

一键安装R语言环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/R.sh -o R.sh && chmod +x R.sh && bash R.sh

一键安装rust环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/rust.sh -o rust.sh && chmod +x rust.sh && bash rust.sh

一键安装C环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/cplusplus.sh -o cplusplus.sh && chmod +x cplusplus.sh && bash cplusplus.sh

一键安装vnstat环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/vnstat.sh -o vnstat.sh && chmod +x vnstat.sh && bash vnstat.sh

一键升级低版本debian为debian11

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/todebian11.sh -o todebian11.sh && chmod +x todebian11.sh && bash todebian11.sh

一键升级低版本ubuntu为ubuntu22

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/toubuntu22.sh -o toubuntu22.sh && chmod +x toubuntu22.sh && bash toubuntu22.sh

一键安装zipline平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/zipline.sh -o zipline.sh && chmod +x zipline.sh && bash zipline.sh

如果需要删除0字节文件,打开/root/zipline文件夹,执行

docker-compose exec zipline yarn scripts:clear-zero-byte

按照提示操作

一键安装filebrowser平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/filebrowser.sh -o filebrowser.sh && chmod +x filebrowser.sh && bash filebrowser.sh

一键删除平台监控

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/dlm.sh -o dlm.sh && chmod +x dlm.shh && bash dlm.sh

部分手动命令

一键开启root登陆并替换密码

bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

一键屏蔽邮件端口避免被恶意程序使用

bash
iptables -A INPUT -p tcp --dport 25 -j DROP
-iptables -A OUTPUT -p tcp --dport 25 -j DROP
-/sbin/iptables-save

设置语言包

bash
sudo apt-get update
-sudo apt-get install language-pack-en-base
-sudo locale-gen en_US.UTF-8

下载UTF-8的环境,生成UTF-8的包,然后重启服务器

bash
locale -a
-export LC_ALL=en_US.UTF-8

查看并设置语言包

language-pack-en-base 在debian中好像没有,只有Ubuntu有好像,不知道是不是个例,有问题再说

ubuntu更新源被锁

bash
sudo rm -rf /var/cache/apt/archives/lock
-sudo pkill apt
-sudo rm /var/lib/dpkg/lock-frontend
-sudo rm /var/lib/apt/lists/lock
-sudo rm /var/cache/apt/archives/lock
-sudo rm /var/lib/dpkg/lock
-sudo dpkg --configure -a

然后重启系统

debian缺失公钥

bash
apt-get install debian-keyring debian-archive-keyring -y

ubuntu或debian缺失公钥

后续这块有计划整理为一个一键脚本

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 公钥

centos换源

bash
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
-sudo sed -i 's/^mirrorlist=http/mirrorlist=https/' /etc/yum.repos.d/CentOS-Base.repo

安装gitea

Ubuntu 20无问题,Ubuntu 22好像不行

https://gitlab.com/packaging/gitea

卸载aapanel

bash
apt install sysv-rc-conf -y && service bt stop && sysv-rc-conf bt off && rm -f /etc/init.d/bt && rm -rf /www/server/panel

安装docker和docker-compose

bash
curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

卸载所有docker镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

通过docker安装code-server

安装

shell
mkdir -p ~/.config
-docker run --restart=always --name code-server -p 0.0.0.0:8886:8080 \\
-  -v "$HOME/.config:/home/coder/.config" \\
-  -v "$PWD:/home/coder/project" \\
-  -u "$(id -u):$(id -g)" \\
-  -e "DOCKER_USER=$USER" \\
-  codercom/code-server:latest

新窗口

shell
docker exec code-server cat /root/.config/code-server/config.yaml

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y
`,109),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/case_case2.md.d9673a40.lean.js b/assets/case_case2.md.d9673a40.lean.js deleted file mode 100644 index 2e8ce75bc8..0000000000 --- a/assets/case_case2.md.d9673a40.lean.js +++ /dev/null @@ -1,36 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case2.md","filePath":"case/case2.md","lastUpdated":1747972048000}'),o={name:"case/case2.md"},p=n(`

仓库

https://github.com/spiritLHLS/one-click-installation-script

Hits

所有脚本如需在国内服务器使用,请在链接前加上https://ghproxy.com/确保命令可以下载本仓库的shell脚本执行

一键修复脚本

运行所有一键修复脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键尝试修复apt源

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/package.sh -o package.sh && chmod +x package.sh && bash package.sh

一键尝试修复系统时间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/modify_time.sh -o modify_time.sh && chmod +x modify_time.sh && bash modify_time.sh

一键尝试修复sudo警告

不要在生产环境上使用该脚本,否则容易造成网络hosts配置错误,配置的host名字不在外网IP上反而在内网IP(127.0.0.1)上

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/check_sudo.sh -o check_sudo.sh && chmod +x check_sudo.sh && bash check_sudo.sh

一键修改系统自带的journal日志记录大小释放系统盘空间

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/resize_journal.sh -o resize_journal.sh && chmod +x resize_journal.sh && bash resize_journal.sh

一键尝试修复网络

该脚本轻易勿要使用,请确保运行时服务器无重要文件或程序,出现运行bug后续可能需要重装系统

一定要在screen中执行该脚本,否则可能导致修改过程中ssh断链接而修改失败卡住最终SSH无法连接!不在screen中执行后果自负!

bash
curl -L https://cdn.spiritlhl.workers.dev/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/network.sh -o network.sh && chmod +x network.sh && bash network.sh

如果是纯V6的也可以不使用上面脚本的nat64,使用warp添加V4网络

比如:https://github.com/fscarmen/warp

bash
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh [option] [lisence]

非纯V6的,带V4切换优先级到IPV4可用以下命令

bash
sudo sed -i 's/.*precedence ::ffff:0:0\\/96.*/precedence ::ffff:0:0\\/96  100/g' /etc/gai.conf && sudo systemctl restart networking

一键环境安装脚本

只推荐在新服务器上安装,环境不纯净不保证不出bug

运行所有一键环境安装脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键安装jupyter环境

原始用途是方便快捷的在按小时计费的超大型服务器上部署python环境进行科学计算,充分利用时间别浪费在构建环境上。

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/jupyter.sh -o jupyter.sh && chmod +x jupyter.sh && bash jupyter.sh

一键安装R语言环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/R.sh -o R.sh && chmod +x R.sh && bash R.sh

一键安装rust环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/rust.sh -o rust.sh && chmod +x rust.sh && bash rust.sh

一键安装C环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/cplusplus.sh -o cplusplus.sh && chmod +x cplusplus.sh && bash cplusplus.sh

一键安装vnstat环境

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/vnstat.sh -o vnstat.sh && chmod +x vnstat.sh && bash vnstat.sh

一键升级低版本debian为debian11

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/todebian11.sh -o todebian11.sh && chmod +x todebian11.sh && bash todebian11.sh

一键升级低版本ubuntu为ubuntu22

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/toubuntu22.sh -o toubuntu22.sh && chmod +x toubuntu22.sh && bash toubuntu22.sh

一键安装zipline平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/zipline.sh -o zipline.sh && chmod +x zipline.sh && bash zipline.sh

如果需要删除0字节文件,打开/root/zipline文件夹,执行

docker-compose exec zipline yarn scripts:clear-zero-byte

按照提示操作

一键安装filebrowser平台

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/filebrowser.sh -o filebrowser.sh && chmod +x filebrowser.sh && bash filebrowser.sh

一键删除平台监控

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/dlm.sh -o dlm.sh && chmod +x dlm.shh && bash dlm.sh

部分手动命令

一键开启root登陆并替换密码

bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

一键屏蔽邮件端口避免被恶意程序使用

bash
iptables -A INPUT -p tcp --dport 25 -j DROP
-iptables -A OUTPUT -p tcp --dport 25 -j DROP
-/sbin/iptables-save

设置语言包

bash
sudo apt-get update
-sudo apt-get install language-pack-en-base
-sudo locale-gen en_US.UTF-8

下载UTF-8的环境,生成UTF-8的包,然后重启服务器

bash
locale -a
-export LC_ALL=en_US.UTF-8

查看并设置语言包

language-pack-en-base 在debian中好像没有,只有Ubuntu有好像,不知道是不是个例,有问题再说

ubuntu更新源被锁

bash
sudo rm -rf /var/cache/apt/archives/lock
-sudo pkill apt
-sudo rm /var/lib/dpkg/lock-frontend
-sudo rm /var/lib/apt/lists/lock
-sudo rm /var/cache/apt/archives/lock
-sudo rm /var/lib/dpkg/lock
-sudo dpkg --configure -a

然后重启系统

debian缺失公钥

bash
apt-get install debian-keyring debian-archive-keyring -y

ubuntu或debian缺失公钥

后续这块有计划整理为一个一键脚本

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 公钥

centos换源

bash
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
-sudo sed -i 's/^mirrorlist=http/mirrorlist=https/' /etc/yum.repos.d/CentOS-Base.repo

安装gitea

Ubuntu 20无问题,Ubuntu 22好像不行

https://gitlab.com/packaging/gitea

卸载aapanel

bash
apt install sysv-rc-conf -y && service bt stop && sysv-rc-conf bt off && rm -f /etc/init.d/bt && rm -rf /www/server/panel

安装docker和docker-compose

bash
curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

卸载所有docker镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

通过docker安装code-server

安装

shell
mkdir -p ~/.config
-docker run --restart=always --name code-server -p 0.0.0.0:8886:8080 \\
-  -v "$HOME/.config:/home/coder/.config" \\
-  -v "$PWD:/home/coder/project" \\
-  -u "$(id -u):$(id -g)" \\
-  -e "DOCKER_USER=$USER" \\
-  codercom/code-server:latest

新窗口

shell
docker exec code-server cat /root/.config/code-server/config.yaml

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y
`,109),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/case_case3.md.8bd8db2f.js b/assets/case_case3.md.8bd8db2f.js deleted file mode 100644 index 65561442aa..0000000000 --- a/assets/case_case3.md.8bd8db2f.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case3.md","filePath":"case/case3.md","lastUpdated":1747972048000}'),p={name:"case/case3.md"},n=a('

仓库

https://github.com/spiritLHLS/ecsspeed

Hits

ecsspeed

自动更新测速服务器节点列表的网络基准测试脚本

Network benchmarking script that automatically updates the list of speed measurement server nodes

说明

所有组件以及数据均来源于平台或已有的开源项目,无非开源部分,放心食用

对应 speedtest.net 的自动更新测速服务器ID的测速脚本

日常推荐使用

bash <(wget -qO- bash.spiritlhl.net/ecs-net)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-net.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-net.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表大概每7天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

当官方CLI安装失败(如罕见的架构或者官方网站访问失败时)自动使用 speedtest-go 作为替代品测速

对应 speedtest.cn 的自动更新测速服务器ID的测速脚本

单线程测速

bash <(wget -qO- bash.spiritlhl.net/ecs-cn)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-cn.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-cn.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表每天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

自动更新测试服务器列表的三网延迟测试脚本

平均耗时10~15秒

bash <(wget -qO- bash.spiritlhl.net/ecs-ping)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-ping.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-ping.sh)

效果图

图片

功能

.cn数据

仓库:https://github.com/spiritLHLS/speedtest.cn-CN-ID

.net数据

仓库:https://github.com/spiritLHLS/speedtest.net-CN-ID

',44),i=[n];function r(c,l,o,h,d,g){return t(),s("div",null,i)}const m=e(p,[["render",r]]);export{u as __pageData,m as default}; diff --git a/assets/case_case3.md.8bd8db2f.lean.js b/assets/case_case3.md.8bd8db2f.lean.js deleted file mode 100644 index 65561442aa..0000000000 --- a/assets/case_case3.md.8bd8db2f.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case3.md","filePath":"case/case3.md","lastUpdated":1747972048000}'),p={name:"case/case3.md"},n=a('

仓库

https://github.com/spiritLHLS/ecsspeed

Hits

ecsspeed

自动更新测速服务器节点列表的网络基准测试脚本

Network benchmarking script that automatically updates the list of speed measurement server nodes

说明

所有组件以及数据均来源于平台或已有的开源项目,无非开源部分,放心食用

对应 speedtest.net 的自动更新测速服务器ID的测速脚本

日常推荐使用

bash <(wget -qO- bash.spiritlhl.net/ecs-net)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-net.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-net.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表大概每7天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

当官方CLI安装失败(如罕见的架构或者官方网站访问失败时)自动使用 speedtest-go 作为替代品测速

对应 speedtest.cn 的自动更新测速服务器ID的测速脚本

单线程测速

bash <(wget -qO- bash.spiritlhl.net/ecs-cn)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-cn.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-cn.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表每天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

自动更新测试服务器列表的三网延迟测试脚本

平均耗时10~15秒

bash <(wget -qO- bash.spiritlhl.net/ecs-ping)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-ping.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-ping.sh)

效果图

图片

功能

.cn数据

仓库:https://github.com/spiritLHLS/speedtest.cn-CN-ID

.net数据

仓库:https://github.com/spiritLHLS/speedtest.net-CN-ID

',44),i=[n];function r(c,l,o,h,d,g){return t(),s("div",null,i)}const m=e(p,[["render",r]]);export{u as __pageData,m as default}; diff --git a/assets/case_case3.md.Dr71EzwR.js b/assets/case_case3.md.Dr71EzwR.js new file mode 100644 index 0000000000..40c747c190 --- /dev/null +++ b/assets/case_case3.md.Dr71EzwR.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as a,ag as p}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case3.md","filePath":"case/case3.md","lastUpdated":1747984962000}'),i={name:"case/case3.md"};function n(c,e,r,h,l,d){return a(),s("div",null,e[0]||(e[0]=[p('

仓库

https://github.com/spiritLHLS/ecsspeed

Hits

ecsspeed

自动更新测速服务器节点列表的网络基准测试脚本

Network benchmarking script that automatically updates the list of speed measurement server nodes

说明

所有组件以及数据均来源于平台或已有的开源项目,无非开源部分,放心食用

对应 speedtest.net 的自动更新测速服务器ID的测速脚本

日常推荐使用

bash <(wget -qO- bash.spiritlhl.net/ecs-net)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-net.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-net.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表大概每7天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

当官方CLI安装失败(如罕见的架构或者官方网站访问失败时)自动使用 speedtest-go 作为替代品测速

对应 speedtest.cn 的自动更新测速服务器ID的测速脚本

单线程测速

bash <(wget -qO- bash.spiritlhl.net/ecs-cn)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-cn.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-cn.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表每天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

自动更新测试服务器列表的三网延迟测试脚本

平均耗时10~15秒

bash <(wget -qO- bash.spiritlhl.net/ecs-ping)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-ping.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-ping.sh)

效果图

图片

功能

.cn数据

仓库:https://github.com/spiritLHLS/speedtest.cn-CN-ID

.net数据

仓库:https://github.com/spiritLHLS/speedtest.net-CN-ID

',44)]))}const b=t(i,[["render",n]]);export{g as __pageData,b as default}; diff --git a/assets/case_case3.md.Dr71EzwR.lean.js b/assets/case_case3.md.Dr71EzwR.lean.js new file mode 100644 index 0000000000..09562a140f --- /dev/null +++ b/assets/case_case3.md.Dr71EzwR.lean.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as a,ag as p}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case3.md","filePath":"case/case3.md","lastUpdated":1747984962000}'),i={name:"case/case3.md"};function n(c,e,r,h,l,d){return a(),s("div",null,e[0]||(e[0]=[p("",44)]))}const b=t(i,[["render",n]]);export{g as __pageData,b as default}; diff --git a/assets/case_case4.md.14b56d9f.js b/assets/case_case4.md.14b56d9f.js deleted file mode 100644 index 234d7aa59a..0000000000 --- a/assets/case_case4.md.14b56d9f.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as r}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case4.md","filePath":"case/case4.md","lastUpdated":1747972048000}'),c={name:"case/case4.md"},s=r('

仓库

https://github.com/oneclickvirt/backtrace

Hits

backtrace

三网回程路由线路测试

基于 https://github.com/zhanghanyun/backtrace 的重构和优化,与原版存在很大不同

路由的线路判断最终还是得人工判断的才准确,本项目测试结果仅供参考

功能

使用

shell
curl https://raw.githubusercontent.com/oneclickvirt/backtrace/main/backtrace_install.sh -sSf | sh

更多架构请查看 https://github.com/oneclickvirt/backtrace/releases/tag/output

概览图

图片

图片

图片

',16),n=[s];function l(o,h,i,p,b,d){return e(),t("div",null,n)}const f=a(c,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/case_case4.md.14b56d9f.lean.js b/assets/case_case4.md.14b56d9f.lean.js deleted file mode 100644 index 234d7aa59a..0000000000 --- a/assets/case_case4.md.14b56d9f.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as r}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case4.md","filePath":"case/case4.md","lastUpdated":1747972048000}'),c={name:"case/case4.md"},s=r('

仓库

https://github.com/oneclickvirt/backtrace

Hits

backtrace

三网回程路由线路测试

基于 https://github.com/zhanghanyun/backtrace 的重构和优化,与原版存在很大不同

路由的线路判断最终还是得人工判断的才准确,本项目测试结果仅供参考

功能

使用

shell
curl https://raw.githubusercontent.com/oneclickvirt/backtrace/main/backtrace_install.sh -sSf | sh

更多架构请查看 https://github.com/oneclickvirt/backtrace/releases/tag/output

概览图

图片

图片

图片

',16),n=[s];function l(o,h,i,p,b,d){return e(),t("div",null,n)}const f=a(c,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/case_case4.md.BCt0xHGw.js b/assets/case_case4.md.BCt0xHGw.js new file mode 100644 index 0000000000..1af8c44197 --- /dev/null +++ b/assets/case_case4.md.BCt0xHGw.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,ag as c}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case4.md","filePath":"case/case4.md","lastUpdated":1747984962000}'),i={name:"case/case4.md"};function s(h,a,l,n,o,b){return r(),t("div",null,a[0]||(a[0]=[c('

仓库

https://github.com/oneclickvirt/backtrace

Hits

backtrace

三网回程路由线路测试

基于 https://github.com/zhanghanyun/backtrace 的重构和优化,与原版存在很大不同

路由的线路判断最终还是得人工判断的才准确,本项目测试结果仅供参考

功能

使用

shell
curl https://raw.githubusercontent.com/oneclickvirt/backtrace/main/backtrace_install.sh -sSf | sh

更多架构请查看 https://github.com/oneclickvirt/backtrace/releases/tag/output

概览图

图片

图片

图片

',16)]))}const d=e(i,[["render",s]]);export{k as __pageData,d as default}; diff --git a/assets/case_case4.md.BCt0xHGw.lean.js b/assets/case_case4.md.BCt0xHGw.lean.js new file mode 100644 index 0000000000..13c008b974 --- /dev/null +++ b/assets/case_case4.md.BCt0xHGw.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,ag as c}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case4.md","filePath":"case/case4.md","lastUpdated":1747984962000}'),i={name:"case/case4.md"};function s(h,a,l,n,o,b){return r(),t("div",null,a[0]||(a[0]=[c("",16)]))}const d=e(i,[["render",s]]);export{k as __pageData,d as default}; diff --git a/assets/case_case5.md.991f7ced.js b/assets/case_case5.md.991f7ced.js deleted file mode 100644 index 52ccce75a0..0000000000 --- a/assets/case_case5.md.991f7ced.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as s,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case5.md","filePath":"case/case5.md","lastUpdated":1747972048000}'),i={name:"case/case5.md"},l=t('

仓库

https://github.com/spiritLHLS/Oracle-server-keep-alive-script

Hits

Oracle-server-keep-alive-script

实际不止可以在甲骨文服务器上使用,也可以使用在任意ARM或X86_64架构的系统,用作资源占用

甲骨文服务器保活脚本

适配系统:已在Ubuntu 20+,Debian 10+, Centos 7+, Oracle linux 8+,AlmaLinux 8.5+

上述系统验证无问题,别的主流系统应该也没有问题

可选占用:CPU,内存,带宽

安装完毕后如果有问题请卸载脚本反馈问题(重复卸载也没问题)

所有资源(除了CPU)可选默认配置则动态占用,实时调整,避免服务器有别的任何资源已经超过限额了仍然再占用资源

为避免GitHub的CDN抽风加载不了新内容,所有新更新已使用Gitlab仓库

由于speedtest-go的release依赖于GitHub,所以请检查 www.githubstatus.com ,有问题时无法安装带宽占用

基础开发完毕,测试中,有问题请在issues中反馈

选项1安装,选项2卸载,选项3更新安装引导脚本,选项4退出脚本

安装过程中无脑回车则全部可选的占用都占用,不需要什么占用输入n再回车

如果选择带宽占用,会询问使用speedtest-go占用还是使用wget占用,按照提示进行选择即可

有询问是否需要带宽占用的参数自定义,这时候默认选项就是n,回车就使用默认配置,输入y再回车则需要按照提示自定义参数

curl -L https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh -o oalive.sh && chmod +x oalive.sh && bash oalive.sh

bash oalive.sh

bash <(wget -qO- --no-check-certificate https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh)

说明

如若不希望一键的,希望自定义设置时间的,请查看README_CRON.md自行设置定时任务

',26),r=[l];function p(c,o,n,h,d,u){return a(),s("div",null,r)}const v=e(i,[["render",p]]);export{m as __pageData,v as default}; diff --git a/assets/case_case5.md.991f7ced.lean.js b/assets/case_case5.md.991f7ced.lean.js deleted file mode 100644 index 52ccce75a0..0000000000 --- a/assets/case_case5.md.991f7ced.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as s,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case5.md","filePath":"case/case5.md","lastUpdated":1747972048000}'),i={name:"case/case5.md"},l=t('

仓库

https://github.com/spiritLHLS/Oracle-server-keep-alive-script

Hits

Oracle-server-keep-alive-script

实际不止可以在甲骨文服务器上使用,也可以使用在任意ARM或X86_64架构的系统,用作资源占用

甲骨文服务器保活脚本

适配系统:已在Ubuntu 20+,Debian 10+, Centos 7+, Oracle linux 8+,AlmaLinux 8.5+

上述系统验证无问题,别的主流系统应该也没有问题

可选占用:CPU,内存,带宽

安装完毕后如果有问题请卸载脚本反馈问题(重复卸载也没问题)

所有资源(除了CPU)可选默认配置则动态占用,实时调整,避免服务器有别的任何资源已经超过限额了仍然再占用资源

为避免GitHub的CDN抽风加载不了新内容,所有新更新已使用Gitlab仓库

由于speedtest-go的release依赖于GitHub,所以请检查 www.githubstatus.com ,有问题时无法安装带宽占用

基础开发完毕,测试中,有问题请在issues中反馈

选项1安装,选项2卸载,选项3更新安装引导脚本,选项4退出脚本

安装过程中无脑回车则全部可选的占用都占用,不需要什么占用输入n再回车

如果选择带宽占用,会询问使用speedtest-go占用还是使用wget占用,按照提示进行选择即可

有询问是否需要带宽占用的参数自定义,这时候默认选项就是n,回车就使用默认配置,输入y再回车则需要按照提示自定义参数

curl -L https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh -o oalive.sh && chmod +x oalive.sh && bash oalive.sh

bash oalive.sh

bash <(wget -qO- --no-check-certificate https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh)

说明

如若不希望一键的,希望自定义设置时间的,请查看README_CRON.md自行设置定时任务

',26),r=[l];function p(c,o,n,h,d,u){return a(),s("div",null,r)}const v=e(i,[["render",p]]);export{m as __pageData,v as default}; diff --git a/assets/case_case5.md.D0hZllGZ.js b/assets/case_case5.md.D0hZllGZ.js new file mode 100644 index 0000000000..737f4a2050 --- /dev/null +++ b/assets/case_case5.md.D0hZllGZ.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case5.md","filePath":"case/case5.md","lastUpdated":1747984962000}'),r={name:"case/case5.md"};function l(p,e,c,o,n,h){return s(),t("div",null,e[0]||(e[0]=[i('

仓库

https://github.com/spiritLHLS/Oracle-server-keep-alive-script

Hits

Oracle-server-keep-alive-script

实际不止可以在甲骨文服务器上使用,也可以使用在任意ARM或X86_64架构的系统,用作资源占用

甲骨文服务器保活脚本

适配系统:已在Ubuntu 20+,Debian 10+, Centos 7+, Oracle linux 8+,AlmaLinux 8.5+

上述系统验证无问题,别的主流系统应该也没有问题

可选占用:CPU,内存,带宽

安装完毕后如果有问题请卸载脚本反馈问题(重复卸载也没问题)

所有资源(除了CPU)可选默认配置则动态占用,实时调整,避免服务器有别的任何资源已经超过限额了仍然再占用资源

为避免GitHub的CDN抽风加载不了新内容,所有新更新已使用Gitlab仓库

由于speedtest-go的release依赖于GitHub,所以请检查 www.githubstatus.com ,有问题时无法安装带宽占用

基础开发完毕,测试中,有问题请在issues中反馈

选项1安装,选项2卸载,选项3更新安装引导脚本,选项4退出脚本

安装过程中无脑回车则全部可选的占用都占用,不需要什么占用输入n再回车

如果选择带宽占用,会询问使用speedtest-go占用还是使用wget占用,按照提示进行选择即可

有询问是否需要带宽占用的参数自定义,这时候默认选项就是n,回车就使用默认配置,输入y再回车则需要按照提示自定义参数

curl -L https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh -o oalive.sh && chmod +x oalive.sh && bash oalive.sh

bash oalive.sh

bash <(wget -qO- --no-check-certificate https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh)

说明

如若不希望一键的,希望自定义设置时间的,请查看README_CRON.md自行设置定时任务

',26)]))}const b=a(r,[["render",l]]);export{u as __pageData,b as default}; diff --git a/assets/case_case5.md.D0hZllGZ.lean.js b/assets/case_case5.md.D0hZllGZ.lean.js new file mode 100644 index 0000000000..81479dc09a --- /dev/null +++ b/assets/case_case5.md.D0hZllGZ.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case5.md","filePath":"case/case5.md","lastUpdated":1747984962000}'),r={name:"case/case5.md"};function l(p,e,c,o,n,h){return s(),t("div",null,e[0]||(e[0]=[i("",26)]))}const b=a(r,[["render",l]]);export{u as __pageData,b as default}; diff --git a/assets/case_case6.md.DBcKFtJZ.js b/assets/case_case6.md.DBcKFtJZ.js new file mode 100644 index 0000000000..58a0c0a044 --- /dev/null +++ b/assets/case_case6.md.DBcKFtJZ.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case6.md","filePath":"case/case6.md","lastUpdated":1747984962000}'),e={name:"case/case6.md"};function h(n,s,l,r,k,d){return t(),i("div",null,s[0]||(s[0]=[p('

仓库

https://github.com/spiritLHLS/addswap

addswap

为openvz、kvm虚拟化的linux服务器增加swap分区(虚拟内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

已增加openvz架构重启swap自动添加的

openvz这个添加=掩耳盗铃,实际受到虚拟化限制应该是无法添加的,只能由虚拟化的宿主机控制,同理LXC虚拟化的也只能由宿主机控制,都无法自主添加虚拟内存SWAP

因此,该项目不再更新,除非另有需求

单位换算:输入 1024 产生 1G SWAP内存

致谢

kvm分区原版脚本源自 https://www.moerats.com/

bash
curl -L https://www.moerats.com/usr/shell/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

openVZ分区原版脚本源自

http://linux-problem-solver.blogspot.com/2013/08/create-fake-swap-in-openvz-vps-if-you-get-swapon-failed-operation-not-permitted-error.html

感谢 @fscarmen 提供优化建议

',18)]))}const F=a(e,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/case_case6.md.DBcKFtJZ.lean.js b/assets/case_case6.md.DBcKFtJZ.lean.js new file mode 100644 index 0000000000..bdb92d2a19 --- /dev/null +++ b/assets/case_case6.md.DBcKFtJZ.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case6.md","filePath":"case/case6.md","lastUpdated":1747984962000}'),e={name:"case/case6.md"};function h(n,s,l,r,k,d){return t(),i("div",null,s[0]||(s[0]=[p("",18)]))}const F=a(e,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/case_case6.md.d14d2ac7.js b/assets/case_case6.md.d14d2ac7.js deleted file mode 100644 index 116ca97582..0000000000 --- a/assets/case_case6.md.d14d2ac7.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as p,R as o}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case6.md","filePath":"case/case6.md","lastUpdated":1747972048000}'),n={name:"case/case6.md"},l=o('

仓库

https://github.com/spiritLHLS/addswap

addswap

为openvz、kvm虚拟化的linux服务器增加swap分区(虚拟内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

已增加openvz架构重启swap自动添加的

openvz这个添加=掩耳盗铃,实际受到虚拟化限制应该是无法添加的,只能由虚拟化的宿主机控制,同理LXC虚拟化的也只能由宿主机控制,都无法自主添加虚拟内存SWAP

因此,该项目不再更新,除非另有需求

单位换算:输入 1024 产生 1G SWAP内存

致谢

kvm分区原版脚本源自 https://www.moerats.com/

bash
curl -L https://www.moerats.com/usr/shell/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

openVZ分区原版脚本源自

http://linux-problem-solver.blogspot.com/2013/08/create-fake-swap-in-openvz-vps-if-you-get-swapon-failed-operation-not-permitted-error.html

感谢 @fscarmen 提供优化建议

',18),e=[l];function t(r,c,C,d,i,h){return a(),p("div",null,e)}const D=s(n,[["render",t]]);export{A as __pageData,D as default}; diff --git a/assets/case_case6.md.d14d2ac7.lean.js b/assets/case_case6.md.d14d2ac7.lean.js deleted file mode 100644 index 116ca97582..0000000000 --- a/assets/case_case6.md.d14d2ac7.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as p,R as o}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case6.md","filePath":"case/case6.md","lastUpdated":1747972048000}'),n={name:"case/case6.md"},l=o('

仓库

https://github.com/spiritLHLS/addswap

addswap

为openvz、kvm虚拟化的linux服务器增加swap分区(虚拟内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

已增加openvz架构重启swap自动添加的

openvz这个添加=掩耳盗铃,实际受到虚拟化限制应该是无法添加的,只能由虚拟化的宿主机控制,同理LXC虚拟化的也只能由宿主机控制,都无法自主添加虚拟内存SWAP

因此,该项目不再更新,除非另有需求

单位换算:输入 1024 产生 1G SWAP内存

致谢

kvm分区原版脚本源自 https://www.moerats.com/

bash
curl -L https://www.moerats.com/usr/shell/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

openVZ分区原版脚本源自

http://linux-problem-solver.blogspot.com/2013/08/create-fake-swap-in-openvz-vps-if-you-get-swapon-failed-operation-not-permitted-error.html

感谢 @fscarmen 提供优化建议

',18),e=[l];function t(r,c,C,d,i,h){return a(),p("div",null,e)}const D=s(n,[["render",t]]);export{A as __pageData,D as default}; diff --git a/assets/case_case7.md.Ca88kvzN.js b/assets/case_case7.md.Ca88kvzN.js new file mode 100644 index 0000000000..ef1cba9079 --- /dev/null +++ b/assets/case_case7.md.Ca88kvzN.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case7.md","filePath":"case/case7.md","lastUpdated":1747984962000}'),e={name:"case/case7.md"};function p(l,a,r,n,d,k){return t(),i("div",null,a[0]||(a[0]=[h('

仓库

https://github.com/spiritLHLS/addzram

addzram

为linux服务器启用zram(压缩内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

类同前面的addswap项目

同样是给机器优化内存占用的东西,只不过zram是压缩内存占用,swap是附加虚拟内存增加内存空间,二者都会占用CPU资源,zram在CPU性能冗余的机器上使用更优

(理论上zram会比swap的性能占用低,但未实际测试过)

单位换算:输入 1024 产生 1G 的 zram 设备压缩内存,zram 设备大小不能大于实际内存大小

致谢

感谢 @Ella-Alinda 提供优化建议

',14)]))}const m=s(e,[["render",p]]);export{c as __pageData,m as default}; diff --git a/assets/case_case7.md.Ca88kvzN.lean.js b/assets/case_case7.md.Ca88kvzN.lean.js new file mode 100644 index 0000000000..166ca98254 --- /dev/null +++ b/assets/case_case7.md.Ca88kvzN.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case7.md","filePath":"case/case7.md","lastUpdated":1747984962000}'),e={name:"case/case7.md"};function p(l,a,r,n,d,k){return t(),i("div",null,a[0]||(a[0]=[h("",14)]))}const m=s(e,[["render",p]]);export{c as __pageData,m as default}; diff --git a/assets/case_case7.md.b84f4c02.js b/assets/case_case7.md.b84f4c02.js deleted file mode 100644 index d35ac360cf..0000000000 --- a/assets/case_case7.md.b84f4c02.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as p,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case7.md","filePath":"case/case7.md","lastUpdated":1747972048000}'),n={name:"case/case7.md"},o=l('

仓库

https://github.com/spiritLHLS/addzram

addzram

为linux服务器启用zram(压缩内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

类同前面的addswap项目

同样是给机器优化内存占用的东西,只不过zram是压缩内存占用,swap是附加虚拟内存增加内存空间,二者都会占用CPU资源,zram在CPU性能冗余的机器上使用更优

(理论上zram会比swap的性能占用低,但未实际测试过)

单位换算:输入 1024 产生 1G 的 zram 设备压缩内存,zram 设备大小不能大于实际内存大小

致谢

感谢 @Ella-Alinda 提供优化建议

',14),e=[o];function t(r,c,d,C,i,h){return s(),p("div",null,e)}const A=a(n,[["render",t]]);export{y as __pageData,A as default}; diff --git a/assets/case_case7.md.b84f4c02.lean.js b/assets/case_case7.md.b84f4c02.lean.js deleted file mode 100644 index d35ac360cf..0000000000 --- a/assets/case_case7.md.b84f4c02.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as p,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"仓库","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"case/case7.md","filePath":"case/case7.md","lastUpdated":1747972048000}'),n={name:"case/case7.md"},o=l('

仓库

https://github.com/spiritLHLS/addzram

addzram

为linux服务器启用zram(压缩内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

类同前面的addswap项目

同样是给机器优化内存占用的东西,只不过zram是压缩内存占用,swap是附加虚拟内存增加内存空间,二者都会占用CPU资源,zram在CPU性能冗余的机器上使用更优

(理论上zram会比swap的性能占用低,但未实际测试过)

单位换算:输入 1024 产生 1G 的 zram 设备压缩内存,zram 设备大小不能大于实际内存大小

致谢

感谢 @Ella-Alinda 提供优化建议

',14),e=[o];function t(r,c,d,C,i,h){return s(),p("div",null,e)}const A=a(n,[["render",t]]);export{y as __pageData,A as default}; diff --git a/assets/case_index.md.259f5ee0.js b/assets/case_index.md.D_IkUok9.js similarity index 78% rename from assets/case_index.md.259f5ee0.js rename to assets/case_index.md.D_IkUok9.js index c11b7b158b..3828b7abc2 100644 --- a/assets/case_index.md.259f5ee0.js +++ b/assets/case_index.md.D_IkUok9.js @@ -1 +1 @@ -import{_ as e,v as t,b as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","description":"","frontmatter":{"layout":"home","title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","hero":{"name":"其他实用项目","text":"与Linux相关的其他实用项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/case/case1"}]},"features":[{"title":"实用性","details":"仁者见仁智者见智。"}]},"headers":[],"relativePath":"case/index.md","filePath":"case/index.md","lastUpdated":1747972048000}'),s={name:"case/index.md"};function i(n,r,o,c,d,l){return t(),a("div")}const h=e(s,[["render",i]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","description":"","frontmatter":{"layout":"home","title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","hero":{"name":"其他实用项目","text":"与Linux相关的其他实用项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/case/case1"}]},"features":[{"title":"实用性","details":"仁者见仁智者见智。"}]},"headers":[],"relativePath":"case/index.md","filePath":"case/index.md","lastUpdated":1747984962000}'),n={name:"case/index.md"};function s(i,o,r,c,l,p){return a(),t("div")}const h=e(n,[["render",s]]);export{m as __pageData,h as default}; diff --git a/assets/case_index.md.259f5ee0.lean.js b/assets/case_index.md.D_IkUok9.lean.js similarity index 78% rename from assets/case_index.md.259f5ee0.lean.js rename to assets/case_index.md.D_IkUok9.lean.js index c11b7b158b..3828b7abc2 100644 --- a/assets/case_index.md.259f5ee0.lean.js +++ b/assets/case_index.md.D_IkUok9.lean.js @@ -1 +1 @@ -import{_ as e,v as t,b as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","description":"","frontmatter":{"layout":"home","title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","hero":{"name":"其他实用项目","text":"与Linux相关的其他实用项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/case/case1"}]},"features":[{"title":"实用性","details":"仁者见仁智者见智。"}]},"headers":[],"relativePath":"case/index.md","filePath":"case/index.md","lastUpdated":1747972048000}'),s={name:"case/index.md"};function i(n,r,o,c,d,l){return t(),a("div")}const h=e(s,[["render",i]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","description":"","frontmatter":{"layout":"home","title":"其他实用项目","titleTemplate":"与Linux相关的其他实用项目","hero":{"name":"其他实用项目","text":"与Linux相关的其他实用项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/case/case1"}]},"features":[{"title":"实用性","details":"仁者见仁智者见智。"}]},"headers":[],"relativePath":"case/index.md","filePath":"case/index.md","lastUpdated":1747984962000}'),n={name:"case/index.md"};function s(i,o,r,c,l,p){return a(),t("div")}const h=e(n,[["render",s]]);export{m as __pageData,h as default}; diff --git a/assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js b/assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js new file mode 100644 index 0000000000..f904cfee6c --- /dev/null +++ b/assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js @@ -0,0 +1,12 @@ +import{d as pi,ah as vi,J as hi,v as di,q as yi,P as _i,c as gi,o as bi}from"./framework.CSeR4K32.js";import{u as Si}from"./theme.DJQtrHna.js";/*! @docsearch/js 3.8.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */function Hr(){return Hr=Object.assign?Object.assign.bind():function(e){for(var t=1;t2&&(a.children=arguments.length>3?Wt.call(arguments,2):r),typeof e=="function"&&e.defaultProps!=null)for(i in e.defaultProps)a[i]===void 0&&(a[i]=e.defaultProps[i]);return Et(e,a,n,o,null)}function Et(e,t,r,n,o){var i={type:e,props:t,key:r,ref:n,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:o??++So,__i:-1,__u:0};return o==null&&H.vnode!=null&&H.vnode(i),i}function Re(e){return e.children}function Ce(e,t){this.props=e,this.context=t}function ct(e,t){if(t==null)return e.__?ct(e.__,e.__i+1):null;for(var r;tt&&Ge.sort(Ur));dr.__r=0}function Io(e,t,r,n,o,i,a,c,f,m,b){var l,v,s,S,g,y=n&&n.__k||Eo,_=t.length;for(r.__d=f,function(h,p,d){var P,E,C,N,I,x=p.length,k=d.length,U=k,z=0;for(h.__k=[],P=0;P0?Et(E.type,E.props,E.key,E.ref?E.ref:null,E.__v):E).__=h,E.__b=h.__b+1,C=null,(I=E.__i=wi(E,d,N,U))!==-1&&(U--,(C=d[I])&&(C.__u|=131072)),C==null||C.__v===null?(I==-1&&z--,typeof E.type!="function"&&(E.__u|=65536)):I!==N&&(I==N-1?z--:I==N+1?z++:(I>N?z--:z++,E.__u|=65536))):E=h.__k[P]=null;if(U)for(P=0;P(f==null||131072&f.__u?0:1))for(;a>=0||c=0){if((f=t[a])&&!(131072&f.__u)&&o==f.key&&i===f.type)return a;a--}if(c2&&(c.children=arguments.length>3?Wt.call(arguments,2):r),Et(e.type,c,n||e.key,o||e.ref,null)}Wt=Eo.slice,H={__e:function(e,t,r,n){for(var o,i,a;t=t.__;)if((o=t.__c)&&!o.__)try{if((i=o.constructor)&&i.getDerivedStateFromError!=null&&(o.setState(i.getDerivedStateFromError(e)),a=o.__d),o.componentDidCatch!=null&&(o.componentDidCatch(e,n||{}),a=o.__d),a)return o.__E=o}catch(c){e=c}throw e}},So=0,Ce.prototype.setState=function(e,t){var r;r=this.__s!=null&&this.__s!==this.state?this.__s:this.__s=Te({},this.state),typeof e=="function"&&(e=e(Te({},r),this.props)),e&&Te(r,e),e!=null&&this.__v&&(t&&this._sb.push(t),Vr(this))},Ce.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),Vr(this))},Ce.prototype.render=Re,Ge=[],Oo=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Ur=function(e,t){return e.__v.__b-t.__v.__b},dr.__r=0,en=0,Fr=bn(!1),Br=bn(!0),wo=0;var Be,Z,Dr,Sn,lt=0,Ao=[],Y=H,On=Y.__b,wn=Y.__r,En=Y.diffed,jn=Y.__c,Pn=Y.unmount,In=Y.__;function st(e,t){Y.__h&&Y.__h(Z,e,lt||t),lt=0;var r=Z.__H||(Z.__H={__:[],__h:[]});return e>=r.__.length&&r.__.push({}),r.__[e]}function zt(e){return lt=1,nn(Ho,e)}function nn(e,t,r){var n=st(Be++,2);if(n.t=e,!n.__c&&(n.__=[r?r(t):Ho(void 0,t),function(c){var f=n.__N?n.__N[0]:n.__[0],m=n.t(f,c);f!==m&&(n.__N=[m,n.__[1]],n.__c.setState({}))}],n.__c=Z,!Z.u)){var o=function(c,f,m){if(!n.__c.__H)return!0;var b=n.__c.__H.__.filter(function(v){return!!v.__c});if(b.every(function(v){return!v.__N}))return!i||i.call(this,c,f,m);var l=!1;return b.forEach(function(v){if(v.__N){var s=v.__[0];v.__=v.__N,v.__N=void 0,s!==v.__[0]&&(l=!0)}}),!(!l&&n.__c.props===c)&&(!i||i.call(this,c,f,m))};Z.u=!0;var i=Z.shouldComponentUpdate,a=Z.componentWillUpdate;Z.componentWillUpdate=function(c,f,m){if(this.__e){var b=i;i=void 0,o(c,f,m),i=b}a&&a.call(this,c,f,m)},Z.shouldComponentUpdate=o}return n.__N||n.__}function Jt(e,t){var r=st(Be++,3);!Y.__s&&on(r.__H,t)&&(r.__=e,r.i=t,Z.__H.__h.push(r))}function Qt(e,t){var r=st(Be++,4);!Y.__s&&on(r.__H,t)&&(r.__=e,r.i=t,Z.__h.push(r))}function No(e){return lt=5,_r(function(){return{current:e}},[])}function To(e,t,r){lt=6,Qt(function(){return typeof e=="function"?(e(t()),function(){return e(null)}):e?(e.current=t(),function(){return e.current=null}):void 0},r==null?r:r.concat(e))}function _r(e,t){var r=st(Be++,7);return on(r.__H,t)&&(r.__=e(),r.__H=t,r.__h=e),r.__}function Ro(e,t){return lt=8,_r(function(){return e},t)}function Lo(e){var t=Z.context[e.__c],r=st(Be++,9);return r.c=e,t?(r.__==null&&(r.__=!0,t.sub(Z)),t.props.value):e.__}function qo(e,t){Y.useDebugValue&&Y.useDebugValue(t?t(e):e)}function Mo(){var e=st(Be++,11);if(!e.__){for(var t=Z.__v;t!==null&&!t.__m&&t.__!==null;)t=t.__;var r=t.__m||(t.__m=[0,0]);e.__="P"+r[0]+"-"+r[1]++}return e.__}function Ii(){for(var e;e=Ao.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(mr),e.__H.__h.forEach(Kr),e.__H.__h=[]}catch(t){e.__H.__h=[],Y.__e(t,e.__v)}}Y.__b=function(e){Z=null,On&&On(e)},Y.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),In&&In(e,t)},Y.__r=function(e){wn&&wn(e),Be=0;var t=(Z=e.__c).__H;t&&(Dr===Z?(t.__h=[],Z.__h=[],t.__.forEach(function(r){r.__N&&(r.__=r.__N),r.i=r.__N=void 0})):(t.__h.forEach(mr),t.__h.forEach(Kr),t.__h=[],Be=0)),Dr=Z},Y.diffed=function(e){En&&En(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Ao.push(t)!==1&&Sn===Y.requestAnimationFrame||((Sn=Y.requestAnimationFrame)||ki)(Ii)),t.__H.__.forEach(function(r){r.i&&(r.__H=r.i),r.i=void 0})),Dr=Z=null},Y.__c=function(e,t){t.some(function(r){try{r.__h.forEach(mr),r.__h=r.__h.filter(function(n){return!n.__||Kr(n)})}catch(n){t.some(function(o){o.__h&&(o.__h=[])}),t=[],Y.__e(n,r.__v)}}),jn&&jn(e,t)},Y.unmount=function(e){Pn&&Pn(e);var t,r=e.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{mr(n)}catch(o){t=o}}),r.__H=void 0,t&&Y.__e(t,r.__v))};var kn=typeof requestAnimationFrame=="function";function ki(e){var t,r=function(){clearTimeout(n),kn&&cancelAnimationFrame(t),setTimeout(e)},n=setTimeout(r,100);kn&&(t=requestAnimationFrame(r))}function mr(e){var t=Z,r=e.__c;typeof r=="function"&&(e.__c=void 0,r()),Z=t}function Kr(e){var t=Z;e.__c=e.__(),Z=t}function on(e,t){return!e||e.length!==t.length||t.some(function(r,n){return r!==e[n]})}function Ho(e,t){return typeof t=="function"?t(e):t}function Wr(e,t){for(var r in e)if(r!=="__source"&&!(r in t))return!0;for(var n in t)if(n!=="__source"&&e[n]!==t[n])return!0;return!1}function zr(e,t){this.props=e,this.context=t}(zr.prototype=new Ce).isPureReactComponent=!0,zr.prototype.shouldComponentUpdate=function(e,t){return Wr(this.props,e)||Wr(this.state,t)};var Dn=H.__b;H.__b=function(e){e.type&&e.type.__f&&e.ref&&(e.props.ref=e.ref,e.ref=null),Dn&&Dn(e)};var Di=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911,Cn=function(e,t){return e==null?null:Le(Le(e).map(t))},Ci={map:Cn,forEach:Cn,count:function(e){return e?Le(e).length:0},only:function(e){var t=Le(e);if(t.length!==1)throw"Children.only";return t[0]},toArray:Le},xi=H.__e;H.__e=function(e,t,r,n){if(e.then){for(var o,i=t;i=i.__;)if((o=i.__c)&&o.__c)return t.__e==null&&(t.__e=r.__e,t.__k=r.__k),o.__c(e,t)}xi(e,t,r,n)};var xn=H.unmount;function Uo(e,t,r){return e&&(e.__c&&e.__c.__H&&(e.__c.__H.__.forEach(function(n){typeof n.__c=="function"&&n.__c()}),e.__c.__H=null),(e=function(n,o){for(var i in o)n[i]=o[i];return n}({},e)).__c!=null&&(e.__c.__P===r&&(e.__c.__P=t),e.__c=null),e.__k=e.__k&&e.__k.map(function(n){return Uo(n,t,r)})),e}function Fo(e,t,r){return e&&r&&(e.__v=null,e.__k=e.__k&&e.__k.map(function(n){return Fo(n,t,r)}),e.__c&&e.__c.__P===t&&(e.__e&&r.appendChild(e.__e),e.__c.__e=!0,e.__c.__P=r)),e}function pr(){this.__u=0,this.t=null,this.__b=null}function Bo(e){var t=e.__.__c;return t&&t.__a&&t.__a(e)}function Ot(){this.u=null,this.o=null}H.unmount=function(e){var t=e.__c;t&&t.__R&&t.__R(),t&&32&e.__u&&(e.type=null),xn&&xn(e)},(pr.prototype=new Ce).__c=function(e,t){var r=t.__c,n=this;n.t==null&&(n.t=[]),n.t.push(r);var o=Bo(n.__v),i=!1,a=function(){i||(i=!0,r.__R=null,o?o(c):c())};r.__R=a;var c=function(){if(!--n.__u){if(n.state.__a){var f=n.state.__a;n.__v.__k[0]=Fo(f,f.__c.__P,f.__c.__O)}var m;for(n.setState({__a:n.__b=null});m=n.t.pop();)m.forceUpdate()}};n.__u++||32&t.__u||n.setState({__a:n.__b=n.__v.__k[0]}),e.then(a,a)},pr.prototype.componentWillUnmount=function(){this.t=[]},pr.prototype.render=function(e,t){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),n=this.__v.__k[0].__c;this.__v.__k[0]=Uo(this.__b,r,n.__O=n.__P)}this.__b=null}var o=t.__a&&De(Re,null,e.fallback);return o&&(o.__u&=-33),[De(Re,null,t.__a?null:e.children),o]};var An=function(e,t,r){if(++r[1]===r[0]&&e.o.delete(t),e.props.revealOrder&&(e.props.revealOrder[0]!=="t"||!e.o.size))for(r=e.u;r;){for(;r.length>3;)r.pop()();if(r[1]>>1,1),t.i.removeChild(n)}}),Ft(De(Ai,{context:t.context},e.__v),t.l)}function Vo(e,t){var r=De(Ni,{__v:e,i:t});return r.containerInfo=t,r}(Ot.prototype=new Ce).__a=function(e){var t=this,r=Bo(t.__v),n=t.o.get(e);return n[0]++,function(o){var i=function(){t.props.revealOrder?(n.push(o),An(t,e,n)):o()};r?r(i):i()}},Ot.prototype.render=function(e){this.u=null,this.o=new Map;var t=Le(e.children);e.revealOrder&&e.revealOrder[0]==="b"&&t.reverse();for(var r=t.length;r--;)this.o.set(t[r],this.u=[1,0,this.u]);return e.children},Ot.prototype.componentDidUpdate=Ot.prototype.componentDidMount=function(){var e=this;this.o.forEach(function(t,r){An(e,r,t)})};var Ko=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,Ti=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,Ri=/^on(Ani|Tra|Tou|BeforeInp|Compo)/,Li=/[A-Z0-9]/g,qi=typeof document<"u",Mi=function(e){return(typeof Symbol<"u"&&A(Symbol())=="symbol"?/fil|che|rad/:/fil|che|ra/).test(e)};function Wo(e,t,r){return t.__k==null&&(t.textContent=""),Ft(e,t),typeof r=="function"&&r(),e?e.__c:null}Ce.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(e){Object.defineProperty(Ce.prototype,e,{configurable:!0,get:function(){return this["UNSAFE_"+e]},set:function(t){Object.defineProperty(this,e,{configurable:!0,writable:!0,value:t})}})});var Nn=H.event;function Hi(){}function Ui(){return this.cancelBubble}function Fi(){return this.defaultPrevented}H.event=function(e){return Nn&&(e=Nn(e)),e.persist=Hi,e.isPropagationStopped=Ui,e.isDefaultPrevented=Fi,e.nativeEvent=e};var an,Bi={enumerable:!1,configurable:!0,get:function(){return this.class}},Tn=H.vnode;H.vnode=function(e){typeof e.type=="string"&&function(t){var r=t.props,n=t.type,o={},i=n.indexOf("-")===-1;for(var a in r){var c=r[a];if(!(a==="value"&&"defaultValue"in r&&c==null||qi&&a==="children"&&n==="noscript"||a==="class"||a==="className")){var f=a.toLowerCase();a==="defaultValue"&&"value"in r&&r.value==null?a="value":a==="download"&&c===!0?c="":f==="translate"&&c==="no"?c=!1:f[0]==="o"&&f[1]==="n"?f==="ondoubleclick"?a="ondblclick":f!=="onchange"||n!=="input"&&n!=="textarea"||Mi(r.type)?f==="onfocus"?a="onfocusin":f==="onblur"?a="onfocusout":Ri.test(a)&&(a=f):f=a="oninput":i&&Ti.test(a)?a=a.replace(Li,"-$&").toLowerCase():c===null&&(c=void 0),f==="oninput"&&o[a=f]&&(a="oninputCapture"),o[a]=c}}n=="select"&&o.multiple&&Array.isArray(o.value)&&(o.value=Le(r.children).forEach(function(m){m.props.selected=o.value.indexOf(m.props.value)!=-1})),n=="select"&&o.defaultValue!=null&&(o.value=Le(r.children).forEach(function(m){m.props.selected=o.multiple?o.defaultValue.indexOf(m.props.value)!=-1:o.defaultValue==m.props.value})),r.class&&!r.className?(o.class=r.class,Object.defineProperty(o,"className",Bi)):(r.className&&!r.class||r.class&&r.className)&&(o.class=o.className=r.className),t.props=o}(e),e.$$typeof=Ko,Tn&&Tn(e)};var Rn=H.__r;H.__r=function(e){Rn&&Rn(e),an=e.__c};var Ln=H.diffed;H.diffed=function(e){Ln&&Ln(e);var t=e.props,r=e.__e;r!=null&&e.type==="textarea"&&"value"in t&&t.value!==r.value&&(r.value=t.value==null?"":t.value),an=null};var Vi={ReactCurrentDispatcher:{current:{readContext:function(e){return an.__n[e.__c].props.value},useCallback:Ro,useContext:Lo,useDebugValue:qo,useDeferredValue:Jo,useEffect:Jt,useId:Mo,useImperativeHandle:To,useInsertionEffect:$o,useLayoutEffect:Qt,useMemo:_r,useReducer:nn,useRef:No,useState:zt,useSyncExternalStore:Zo,useTransition:Qo}}};function rr(e){return!!e&&e.$$typeof===Ko}function zo(e){e()}function Jo(e){return e}function Qo(){return[!1,zo]}var $o=Qt;function Zo(e,t){var r=t(),n=zt({h:{__:r,v:t}}),o=n[0].h,i=n[1];return Qt(function(){o.__=r,o.v=t,Cr(o)&&i({h:o})},[e,r,t]),Jt(function(){return Cr(o)&&i({h:o}),e(function(){Cr(o)&&i({h:o})})},[e]),r}function Cr(e){var t,r,n=e.v,o=e.__;try{var i=n();return!((t=o)===(r=i)&&(t!==0||1/t==1/r)||t!=t&&r!=r)}catch{return!0}}var u={useState:zt,useId:Mo,useReducer:nn,useEffect:Jt,useLayoutEffect:Qt,useInsertionEffect:$o,useTransition:Qo,useDeferredValue:Jo,useSyncExternalStore:Zo,startTransition:zo,useRef:No,useImperativeHandle:To,useMemo:_r,useCallback:Ro,useContext:Lo,useDebugValue:qo,version:"18.3.1",Children:Ci,render:Wo,hydrate:function(e,t,r){return xo(e,t),typeof r=="function"&&r(),e?e.__c:null},unmountComponentAtNode:function(e){return!!e.__k&&(Ft(null,e),!0)},createPortal:Vo,createElement:De,createContext:function(e,t){var r={__c:t="__cC"+wo++,__:e,Consumer:function(n,o){return n.children(o)},Provider:function(n){var o,i;return this.getChildContext||(o=new Set,(i={})[t]=this,this.getChildContext=function(){return i},this.componentWillUnmount=function(){o=null},this.shouldComponentUpdate=function(a){this.props.value!==a.value&&o.forEach(function(c){c.__e=!0,Vr(c)})},this.sub=function(a){o.add(a);var c=a.componentWillUnmount;a.componentWillUnmount=function(){o&&o.delete(a),c&&c.call(a)}}),n.children}};return r.Provider.__=r.Consumer.contextType=r},createFactory:function(e){return De.bind(null,e)},cloneElement:function(e){return rr(e)?Pi.apply(null,arguments):e},createRef:function(){return{current:null}},Fragment:Re,isValidElement:rr,isElement:rr,isFragment:function(e){return rr(e)&&e.type===Re},isMemo:function(e){return!!e&&!!e.displayName&&(typeof e.displayName=="string"||e.displayName instanceof String)&&e.displayName.startsWith("Memo(")},findDOMNode:function(e){return e&&(e.base||e.nodeType===1&&e)||null},Component:Ce,PureComponent:zr,memo:function(e,t){function r(o){var i=this.props.ref,a=i==o.ref;return!a&&i&&(i.call?i(null):i.current=null),t?!t(this.props,o)||!a:Wr(this.props,o)}function n(o){return this.shouldComponentUpdate=r,De(e,o)}return n.displayName="Memo("+(e.displayName||e.name)+")",n.prototype.isReactComponent=!0,n.__f=!0,n},forwardRef:function(e){function t(r){if(!("ref"in r))return e(r,null);var n=r.ref;delete r.ref;var o=e(r,n);return r.ref=n,o}return t.$$typeof=Di,t.render=t,t.prototype.isReactComponent=t.__f=!0,t.displayName="ForwardRef("+(e.displayName||e.name)+")",t},flushSync:function(e,t){return e(t)},unstable_batchedUpdates:function(e,t){return e(t)},StrictMode:Re,Suspense:pr,SuspenseList:Ot,lazy:function(e){var t,r,n;function o(i){if(t||(t=e()).then(function(a){r=a.default||a},function(a){n=a}),n)throw n;if(!r)throw t;return De(r,i)}return o.displayName="Lazy",o.__f=!0,o},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:Vi};function Jr(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r=0;--R){var D=this.tryEntries[R],L=D.completion;if(D.tryLoc==="root")return j("end");if(D.tryLoc<=this.prev){var W=n.call(D,"catchLoc"),K=n.call(D,"finallyLoc");if(W&&K){if(this.prev=0;--j){var R=this.tryEntries[j];if(R.tryLoc<=this.prev&&n.call(R,"finallyLoc")&&this.prev=0;--w){var j=this.tryEntries[w];if(j.finallyLoc===O)return this.complete(j.completion,j.afterLoc),z(j),y}},catch:function(O){for(var w=this.tryEntries.length-1;w>=0;--w){var j=this.tryEntries[w];if(j.tryLoc===O){var R=j.completion;if(R.type==="throw"){var D=R.arg;z(j)}return D}}throw Error("illegal catch attempt")},delegateYield:function(O,w,j){return this.delegate={iterator:oe(O),resultName:w,nextLoc:j},this.method==="next"&&(this.arg=e),y}},t}function Vt(e,t){return Vt=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(r,n){return r.__proto__=n,r},Vt(e,t)}function he(e,t){return function(r){if(Array.isArray(r))return r}(e)||function(r,n){var o=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(o!=null){var i,a,c,f,m=[],b=!0,l=!1;try{if(c=(o=o.call(r)).next,n===0){if(Object(o)!==o)return;b=!1}else for(;!(b=(i=c.call(o)).done)&&(m.push(i.value),m.length!==n);b=!0);}catch(v){l=!0,a=v}finally{try{if(!b&&o.return!=null&&(f=o.return(),Object(f)!==f))return}finally{if(l)throw a}}return m}}(e,t)||Go(e,t)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function jt(e){return function(t){if(Array.isArray(t))return Jr(t)}(e)||function(t){if(typeof Symbol<"u"&&t[Symbol.iterator]!=null||t["@@iterator"]!=null)return Array.from(t)}(e)||Go(e)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function Go(e,t){if(e){if(typeof e=="string")return Jr(e,t);var r={}.toString.call(e).slice(8,-1);return r==="Object"&&e.constructor&&(r=e.constructor.name),r==="Map"||r==="Set"?Array.from(e):r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?Jr(e,t):void 0}}function Qr(e){var t=typeof Map=="function"?new Map:void 0;return Qr=function(r){if(r===null||!function(o){try{return Function.toString.call(o).indexOf("[native code]")!==-1}catch{return typeof o=="function"}}(r))return r;if(typeof r!="function")throw new TypeError("Super expression must either be null or a function");if(t!==void 0){if(t.has(r))return t.get(r);t.set(r,n)}function n(){return function(o,i,a){if(un())return Reflect.construct.apply(null,arguments);var c=[null];c.push.apply(c,i);var f=new(o.bind.apply(o,c));return a&&Vt(f,a.prototype),f}(r,arguments,Bt(this).constructor)}return n.prototype=Object.create(r.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),Vt(n,r)},Qr(e)}function Ki(){return u.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},u.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}function Yo(){return u.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20","aria-hidden":"true"},u.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var Wi=["translations"],Ar="Ctrl",zi=u.forwardRef(function(e,t){var r=e.translations,n=r===void 0?{}:r,o=xe(e,Wi),i=n.buttonText,a=i===void 0?"Search":i,c=n.buttonAriaLabel,f=c===void 0?"Search":c,m=he(zt(null),2),b=m[0],l=m[1];Jt(function(){typeof navigator<"u"&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?l("⌘"):l(Ar))},[]);var v=he(b===Ar?[Ar,"Ctrl",u.createElement(Ki,null)]:["Meta","Command",b],3),s=v[0],S=v[1],g=v[2];return u.createElement("button",le({type:"button",className:"DocSearch DocSearch-Button","aria-label":"".concat(f," (").concat(S,"+K)")},o,{ref:t}),u.createElement("span",{className:"DocSearch-Button-Container"},u.createElement(Yo,null),u.createElement("span",{className:"DocSearch-Button-Placeholder"},a)),u.createElement("span",{className:"DocSearch-Button-Keys"},b!==null&&u.createElement(u.Fragment,null,u.createElement(Hn,{reactsToKey:s},g),u.createElement(Hn,{reactsToKey:"k"},"K"))))});function Hn(e){var t=e.reactsToKey,r=e.children,n=he(zt(!1),2),o=n[0],i=n[1];return Jt(function(){if(t)return window.addEventListener("keydown",a),window.addEventListener("keyup",c),function(){window.removeEventListener("keydown",a),window.removeEventListener("keyup",c)};function a(f){f.key===t&&i(!0)}function c(f){f.key!==t&&f.key!=="Meta"||i(!1)}},[t]),u.createElement("kbd",{className:o?"DocSearch-Button-Key DocSearch-Button-Key--pressed":"DocSearch-Button-Key"},r)}function Xo(e,t){var r=void 0;return function(){for(var n=arguments.length,o=new Array(n),i=0;ie.length)&&(t=e.length);for(var r=0,n=new Array(t);re.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(b[f]=a[f]);return b}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Vn(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function at(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=3||S===2&&g>=4||S===1&&g>=10);function _(h,p,d){if(y&&d!==void 0){var P=d[0].__autocomplete_algoliaCredentials,E={"X-Algolia-Application-Id":P.appId,"X-Algolia-API-Key":P.apiKey};v.apply(void 0,[h].concat(nr(p),[{headers:E}]))}else v.apply(void 0,[h].concat(nr(p)))}return{init:function(h,p){v("init",{appId:h,apiKey:p})},setAuthenticatedUserToken:function(h){v("setAuthenticatedUserToken",h)},setUserToken:function(h){v("setUserToken",h)},clickedObjectIDsAfterSearch:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&_("clickedObjectIDsAfterSearch",or(p),p[0].items)},clickedObjectIDs:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&_("clickedObjectIDs",or(p),p[0].items)},clickedFilters:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&v.apply(void 0,["clickedFilters"].concat(p))},convertedObjectIDsAfterSearch:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&_("convertedObjectIDsAfterSearch",or(p),p[0].items)},convertedObjectIDs:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&_("convertedObjectIDs",or(p),p[0].items)},convertedFilters:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&v.apply(void 0,["convertedFilters"].concat(p))},viewedObjectIDs:function(){for(var h=arguments.length,p=new Array(h),d=0;d0&&p.reduce(function(P,E){var C=E.items,N=ti(E,Zi);return[].concat(nr(P),nr(function(I){for(var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:20,k=[],U=0;U0&&v.apply(void 0,["viewedFilters"].concat(p))}}}(f),b={current:[]},l=Xo(function(v){var s=v.state;if(s.isOpen){var S=s.collections.reduce(function(g,y){return[].concat(ut(g),ut(y.items))},[]).filter(bt);ei(b.current.map(function(g){return g.objectID}),S.map(function(g){return g.objectID}))||(b.current=S,S.length>0&&ta({onItemsChange:o,items:S,insights:m,state:s}))}},0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(v){var s=v.setContext,S=v.onSelect,g=v.onActive,y=!1;function _(h){s({algoliaInsightsPlugin:{__algoliaSearchParameters:we(we({},c?{clickAnalytics:!0}:{}),h?{userToken:ra(h)}:{}),insights:m}})}f("addAlgoliaAgent","insights-plugin"),_(),f("onUserTokenChange",function(h){y||_(h)}),f("getUserToken",null,function(h,p){y||_(p)}),f("onAuthenticatedUserTokenChange",function(h){h?(y=!0,_(h)):(y=!1,f("getUserToken",null,function(p,d){return _(d)}))}),f("getAuthenticatedUserToken",null,function(h,p){p&&(y=!0,_(p))}),S(function(h){var p=h.item,d=h.state,P=h.event,E=h.source;bt(p)&&i({state:d,event:P,insights:m,item:p,insightsEvents:[we({eventName:"Item Selected"},Fn({item:p,items:E.getItems().filter(bt)}))]})}),g(function(h){var p=h.item,d=h.source,P=h.state,E=h.event;bt(p)&&a({state:P,event:E,insights:m,item:p,insightsEvents:[we({eventName:"Item Active"},Fn({item:p,items:d.getItems().filter(bt)}))]})})},onStateChange:function(v){var s=v.state;l({state:s})},__autocomplete_pluginOptions:e}}function zn(){var e,t=arguments.length>1?arguments[1]:void 0;return[].concat(ut(arguments.length>0&&arguments[0]!==void 0?arguments[0]:[]),["autocomplete-internal"],ut((e=t.algoliaInsightsPlugin)!==null&&e!==void 0&&e.__automaticInsights?["autocomplete-automatic"]:[]))}function ra(e){return typeof e=="number"?e.toString():e}function hr(e,t){var r=t;return{then:function(n,o){return hr(e.then(ir(n,r,e),ir(o,r,e)),r)},catch:function(n){return hr(e.catch(ir(n,r,e)),r)},finally:function(n){return n&&r.onCancelList.push(n),hr(e.finally(ir(n&&function(){return r.onCancelList=[],n()},r,e)),r)},cancel:function(){r.isCanceled=!0;var n=r.onCancelList;r.onCancelList=[],n.forEach(function(o){o()})},isCanceled:function(){return r.isCanceled===!0}}}function Jn(e){return hr(e,{isCanceled:!1,onCancelList:[]})}function ir(e,t,r){return e?function(n){return t.isCanceled?n:e(n)}:r}function Qn(e,t,r,n){if(!r)return null;if(e<0&&(t===null||n!==null&&t===0))return r+e;var o=(t===null?-1:t)+e;return o<=-1||o>=r?n===null?null:0:o}function $n(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function Zn(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);re.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(z[k]=I[k]);return z}(p,d);if(Object.getOwnPropertySymbols){var N=Object.getOwnPropertySymbols(p);for(E=0;E=0||Object.prototype.propertyIsEnumerable.call(p,P)&&(C[P]=p[P])}return C}(e,sa);St&&o.environment.clearTimeout(St);var m=f.setCollections,b=f.setIsOpen,l=f.setQuery,v=f.setActiveItemId,s=f.setStatus,S=f.setContext;if(l(i),v(o.defaultActiveItemId),!i&&o.openOnFocus===!1){var g,y=c.getState().collections.map(function(p){return ze(ze({},p),{},{items:[]})});s("idle"),m(y),b((g=n.isOpen)!==null&&g!==void 0?g:o.shouldPanelOpen({state:c.getState()}));var _=Jn(io(y).then(function(){return Promise.resolve()}));return c.pendingRequests.add(_)}s("loading"),St=o.environment.setTimeout(function(){s("stalled")},o.stallThreshold);var h=Jn(io(o.getSources(ze({query:i,refresh:a,state:c.getState()},f)).then(function(p){return Promise.all(p.map(function(d){return Promise.resolve(d.getItems(ze({query:i,refresh:a,state:c.getState()},f))).then(function(P){return function(E,C,N){if(x=E,!!(x!=null&&x.execute)){var I=E.requesterId==="algolia"?Object.assign.apply(Object,[{}].concat(oi(Object.keys(N.context).map(function(k){var U;return(U=N.context[k])===null||U===void 0?void 0:U.__algoliaSearchParameters})))):{};return nt(nt({},E),{},{requests:E.queries.map(function(k){return{query:E.requesterId==="algolia"?nt(nt({},k),{},{params:nt(nt({},I),k.params)}):k,sourceId:C,transformResponse:E.transformResponse}})})}var x;return{items:E,sourceId:C}}(P,d.sourceId,c.getState())})})).then(la).then(function(d){var P,E=d.some(function(C){return function(N){return!Array.isArray(N)&&!!(N!=null&&N._automaticInsights)}(C.items)});return E&&S({algoliaInsightsPlugin:ze(ze({},((P=c.getState().context)===null||P===void 0?void 0:P.algoliaInsightsPlugin)||{}),{},{__automaticInsights:E})}),function(C,N,I){return N.map(function(x){var k,U=C.filter(function(O){return O.sourceId===x.sourceId}),z=U.map(function(O){return O.items}),q=U[0].transformResponse,oe=q?q({results:k=z,hits:k.map(function(O){return O.hits}).filter(Boolean),facetHits:k.map(function(O){var w;return(w=O.facetHits)===null||w===void 0?void 0:w.map(function(j){return{label:j.value,count:j.count,_highlightResult:{label:{value:j.highlighted}}}})}).filter(Boolean)}):z;return x.onResolve({source:x,results:z,items:oe,state:I.getState()}),oe.every(Boolean),'The `getItems` function from source "'.concat(x.sourceId,'" must return an array of items but returned ').concat(JSON.stringify(void 0),`. + +Did you forget to return items? + +See: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems`),{source:x,items:oe}})}(d,p,c)}).then(function(d){return function(P){var E=P.props,C=P.state,N=P.collections.reduce(function(x,k){return ur(ur({},x),{},ni({},k.source.sourceId,ur(ur({},k.source),{},{getItems:function(){return Kt(k.items)}})))},{}),I=E.plugins.reduce(function(x,k){return k.reshape?k.reshape(x):x},{sourcesBySourceId:N,state:C}).sourcesBySourceId;return Kt(E.reshape({sourcesBySourceId:I,sources:Object.values(I),state:C})).filter(Boolean).map(function(x){return{source:x,items:x.getItems()}})}({collections:d,props:o,state:c.getState()})})}))).then(function(p){var d;s("idle"),m(p);var P=o.shouldPanelOpen({state:c.getState()});b((d=n.isOpen)!==null&&d!==void 0?d:o.openOnFocus&&!i&&P||P);var E=Ye(c.getState());if(c.getState().activeItemId!==null&&E){var C=E.item,N=E.itemInputValue,I=E.itemUrl,x=E.source;x.onActive(ze({event:t,item:C,itemInputValue:N,itemUrl:I,refresh:a,source:x,state:c.getState()},f))}}).finally(function(){s("idle"),St&&o.environment.clearTimeout(St)});return c.pendingRequests.add(h)}function Rt(e){return Rt=typeof Symbol=="function"&&A(Symbol.iterator)=="symbol"?function(t){return A(t)}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":A(t)},Rt(e)}var ma=["event","props","refresh","store"];function ao(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function Qe(e){for(var t=1;t=0||(b[f]=a[f]);return b}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function qt(e){return qt=typeof Symbol=="function"&&A(Symbol.iterator)=="symbol"?function(t){return A(t)}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":A(t)},qt(e)}function co(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function Sa(e){for(var t=1;t0},reshape:function(g){return g.sources}},b),{},{id:(v=b.id)!==null&&v!==void 0?v:"autocomplete-".concat(Ji++),plugins:S,initialState:rt({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},b.initialState),onStateChange:function(g){var y;(y=b.onStateChange)===null||y===void 0||y.call(b,g),S.forEach(function(_){var h;return(h=_.onStateChange)===null||h===void 0?void 0:h.call(_,g)})},onSubmit:function(g){var y;(y=b.onSubmit)===null||y===void 0||y.call(b,g),S.forEach(function(_){var h;return(h=_.onSubmit)===null||h===void 0?void 0:h.call(_,g)})},onReset:function(g){var y;(y=b.onReset)===null||y===void 0||y.call(b,g),S.forEach(function(_){var h;return(h=_.onReset)===null||h===void 0?void 0:h.call(_,g)})},getSources:function(g){return Promise.all([].concat(function(y){return function(_){if(Array.isArray(_))return Rr(_)}(y)||function(_){if(typeof Symbol<"u"&&_[Symbol.iterator]!=null||_["@@iterator"]!=null)return Array.from(_)}(y)||function(_,h){if(_){if(typeof _=="string")return Rr(_,h);var p=Object.prototype.toString.call(_).slice(8,-1);return p==="Object"&&_.constructor&&(p=_.constructor.name),p==="Map"||p==="Set"?Array.from(_):p==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(p)?Rr(_,h):void 0}}(y)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}(S.map(function(y){return y.getSources})),[b.getSources]).filter(Boolean).map(function(y){return function(_,h){var p=[];return Promise.resolve(_(h)).then(function(d){return Promise.all(d.filter(function(P){return!!P}).map(function(P){if(P.sourceId,p.includes(P.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(P.sourceId)," is not unique."));p.push(P.sourceId);var E={getItemInputValue:function(N){return N.state.query},getItemUrl:function(){},onSelect:function(N){(0,N.setIsOpen)(!1)},onActive:vr,onResolve:vr};Object.keys(E).forEach(function(N){E[N].__default=!0});var C=Zn(Zn({},E),P);return Promise.resolve(C)}))})}(y,g)})).then(function(y){return Kt(y)}).then(function(y){return y.map(function(_){return rt(rt({},_),{},{onSelect:function(h){_.onSelect(h),l.forEach(function(p){var d;return(d=p.onSelect)===null||d===void 0?void 0:d.call(p,h)})},onActive:function(h){_.onActive(h),l.forEach(function(p){var d;return(d=p.onActive)===null||d===void 0?void 0:d.call(p,h)})},onResolve:function(h){_.onResolve(h),l.forEach(function(p){var d;return(d=p.onResolve)===null||d===void 0?void 0:d.call(p,h)})}})})})},navigator:rt({navigate:function(g){var y=g.itemUrl;s.location.assign(y)},navigateNewTab:function(g){var y=g.itemUrl,_=s.open(y,"_blank","noopener");_==null||_.focus()},navigateNewWindow:function(g){var y=g.itemUrl;s.open(y,"_blank","noopener")}},b.navigator)})}(e,t),n=function(b,l,v){var s,S=l.initialState;return{getState:function(){return S},dispatch:function(g,y){var _=function(h){for(var p=1;p=0||(qe[je]=Ee[je]);return qe}(K,J);if(Object.getOwnPropertySymbols){var dt=Object.getOwnPropertySymbols(K);for(se=0;se=0||Object.prototype.propertyIsEnumerable.call(K,G)&&(ee[G]=K[G])}return ee}(x,ma);if(k.key==="ArrowUp"||k.key==="ArrowDown"){var O=function(){var K=Ye(q.getState()),J=U.environment.document.getElementById(be(U.id,"item-".concat(q.getState().activeItemId),K==null?void 0:K.source));J&&(J.scrollIntoViewIfNeeded?J.scrollIntoViewIfNeeded(!1):J.scrollIntoView(!1))},w=function(){var K=Ye(q.getState());if(q.getState().activeItemId!==null&&K){var J=K.item,G=K.itemInputValue,se=K.itemUrl,ee=K.source;ee.onActive(Qe({event:k,item:J,itemInputValue:G,itemUrl:se,refresh:z,source:ee,state:q.getState()},oe))}};k.preventDefault(),q.getState().isOpen===!1&&(U.openOnFocus||q.getState().query)?Je(Qe({event:k,props:U,query:q.getState().query,refresh:z,store:q},oe)).then(function(){q.dispatch(k.key,{nextActiveItemId:U.defaultActiveItemId}),w(),setTimeout(O,0)}):(q.dispatch(k.key,{}),w(),O())}else if(k.key==="Escape")k.preventDefault(),q.dispatch(k.key,null),q.pendingRequests.cancelAll();else if(k.key==="Tab")q.dispatch("blur",null),q.pendingRequests.cancelAll();else if(k.key==="Enter"){if(q.getState().activeItemId===null||q.getState().collections.every(function(K){return K.items.length===0}))return void(U.debug||q.pendingRequests.cancelAll());k.preventDefault();var j=Ye(q.getState()),R=j.item,D=j.itemInputValue,L=j.itemUrl,W=j.source;if(k.metaKey||k.ctrlKey)L!==void 0&&(W.onSelect(Qe({event:k,item:R,itemInputValue:D,itemUrl:L,refresh:z,source:W,state:q.getState()},oe)),U.navigator.navigateNewTab({itemUrl:L,item:R,state:q.getState()}));else if(k.shiftKey)L!==void 0&&(W.onSelect(Qe({event:k,item:R,itemInputValue:D,itemUrl:L,refresh:z,source:W,state:q.getState()},oe)),U.navigator.navigateNewWindow({itemUrl:L,item:R,state:q.getState()}));else if(!k.altKey){if(L!==void 0)return W.onSelect(Qe({event:k,item:R,itemInputValue:D,itemUrl:L,refresh:z,source:W,state:q.getState()},oe)),void U.navigator.navigate({itemUrl:L,item:R,state:q.getState()});Je(Qe({event:k,nextState:{isOpen:!1},props:U,query:D,refresh:z,store:q},oe)).then(function(){W.onSelect(Qe({event:k,item:R,itemInputValue:D,itemUrl:L,refresh:z,source:W,state:q.getState()},oe))})}}}(ie({event:I,props:l,refresh:v,store:s},S))},onFocus:_,onBlur:vr,onClick:function(I){g.inputElement!==l.environment.document.activeElement||s.getState().isOpen||_(I)}},P)},getPanelProps:function(g){return ie({onMouseDown:function(y){y.preventDefault()},onMouseLeave:function(){s.dispatch("mouseleave",null)}},g)},getListProps:function(g){var y=g||{},_=y.source,h=ot(y,_a);return ie({role:"listbox","aria-labelledby":be(l.id,"label"),id:be(l.id,"list",_)},h)},getItemProps:function(g){var y=g.item,_=g.source,h=ot(g,ga);return ie({id:be(l.id,"item-".concat(y.__autocomplete_id),_),role:"option","aria-selected":s.getState().activeItemId===y.__autocomplete_id,onMouseMove:function(p){if(y.__autocomplete_id!==s.getState().activeItemId){s.dispatch("mousemove",y.__autocomplete_id);var d=Ye(s.getState());if(s.getState().activeItemId!==null&&d){var P=d.item,E=d.itemInputValue,C=d.itemUrl,N=d.source;N.onActive(ie({event:p,item:P,itemInputValue:E,itemUrl:C,refresh:v,source:N,state:s.getState()},S))}}},onMouseDown:function(p){p.preventDefault()},onClick:function(p){var d=_.getItemInputValue({item:y,state:s.getState()}),P=_.getItemUrl({item:y,state:s.getState()});(P?Promise.resolve():Je(ie({event:p,nextState:{isOpen:!1},props:l,query:d,refresh:v,store:s},S))).then(function(){_.onSelect(ie({event:p,item:y,itemInputValue:d,itemUrl:P,refresh:v,source:_,state:s.getState()},S))})}},h)}}}($e({props:r,refresh:a,store:n,navigator:r.navigator},o));function a(){return Je($e({event:new Event("input"),nextState:{isOpen:n.getState().isOpen},props:r,navigator:r.navigator,query:n.getState().query,refresh:a,store:n},o))}function c(b){b.forEach(function(l){var v;return(v=l.subscribe)===null||v===void 0?void 0:v.call(l,$e($e({},o),{},{navigator:r.navigator,refresh:a,onSelect:function(s){t.push({onSelect:s})},onActive:function(s){t.push({onActive:s})},onResolve:function(s){t.push({onResolve:s})}}))})}function f(){return r.plugins.some(function(b){return b.name==="aa.algoliaInsightsPlugin"})}if(r.insights&&!f()){var m=typeof r.insights=="boolean"?{}:r.insights;r.plugins.push(Wn(m))}return c(r.plugins),function(b){var l,v,s=b.metadata,S=b.environment;if(!((l=S.navigator)===null||l===void 0||(v=l.userAgent)===null||v===void 0)&&v.includes("Algolia Crawler")){var g=S.document.createElement("meta"),y=S.document.querySelector("head");g.name="algolia:metadata",setTimeout(function(){g.content=JSON.stringify(s),y.appendChild(g)},0)}}({metadata:Oa({plugins:r.plugins,options:e}),environment:r.environment}),$e($e({refresh:a,navigator:r.navigator},i),o)}function Ia(e){var t=e.translations,r=(t===void 0?{}:t).searchByText,n=r===void 0?"Search by":r;return u.createElement("a",{href:"https://www.algolia.com/ref/docsearch/?utm_source=".concat(window.location.hostname,"&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch"),target:"_blank",rel:"noopener noreferrer"},u.createElement("span",{className:"DocSearch-Label"},n),u.createElement("svg",{width:"77",height:"19","aria-label":"Algolia",role:"img",id:"Layer_1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 2196.2 500"},u.createElement("defs",null,u.createElement("style",null,".cls-1,.cls-2{fill:#003dff;}.cls-2{fill-rule:evenodd;}")),u.createElement("path",{className:"cls-2",d:"M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),u.createElement("rect",{className:"cls-1",x:"1845.88",y:"104.73",width:"62.58",height:"277.9",rx:"5.9",ry:"5.9"}),u.createElement("path",{className:"cls-2",d:"M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z"}),u.createElement("path",{className:"cls-2",d:"M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z"}),u.createElement("path",{className:"cls-2",d:"M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z"}),u.createElement("path",{className:"cls-2",d:"M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),u.createElement("path",{className:"cls-2",d:"M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z"}),u.createElement("path",{className:"cls-2",d:"M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z"}),u.createElement("path",{className:"cls-1",d:"M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z"})))}function sr(e){return u.createElement("svg",{width:"15",height:"15","aria-label":e.ariaLabel,role:"img"},u.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"1.2"},e.children))}function ka(e){var t=e.translations,r=t===void 0?{}:t,n=r.selectText,o=n===void 0?"to select":n,i=r.selectKeyAriaLabel,a=i===void 0?"Enter key":i,c=r.navigateText,f=c===void 0?"to navigate":c,m=r.navigateUpKeyAriaLabel,b=m===void 0?"Arrow up":m,l=r.navigateDownKeyAriaLabel,v=l===void 0?"Arrow down":l,s=r.closeText,S=s===void 0?"to close":s,g=r.closeKeyAriaLabel,y=g===void 0?"Escape key":g,_=r.searchByText,h=_===void 0?"Search by":_;return u.createElement(u.Fragment,null,u.createElement("div",{className:"DocSearch-Logo"},u.createElement(Ia,{translations:{searchByText:h}})),u.createElement("ul",{className:"DocSearch-Commands"},u.createElement("li",null,u.createElement("kbd",{className:"DocSearch-Commands-Key"},u.createElement(sr,{ariaLabel:a},u.createElement("path",{d:"M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"}))),u.createElement("span",{className:"DocSearch-Label"},o)),u.createElement("li",null,u.createElement("kbd",{className:"DocSearch-Commands-Key"},u.createElement(sr,{ariaLabel:v},u.createElement("path",{d:"M7.5 3.5v8M10.5 8.5l-3 3-3-3"}))),u.createElement("kbd",{className:"DocSearch-Commands-Key"},u.createElement(sr,{ariaLabel:b},u.createElement("path",{d:"M7.5 11.5v-8M10.5 6.5l-3-3-3 3"}))),u.createElement("span",{className:"DocSearch-Label"},f)),u.createElement("li",null,u.createElement("kbd",{className:"DocSearch-Commands-Key"},u.createElement(sr,{ariaLabel:y},u.createElement("path",{d:"M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"}))),u.createElement("span",{className:"DocSearch-Label"},S))))}function Da(e){var t=e.hit,r=e.children;return u.createElement("a",{href:t.url},r)}function Ca(){return u.createElement("svg",{viewBox:"0 0 38 38",stroke:"currentColor",strokeOpacity:".5"},u.createElement("g",{fill:"none",fillRule:"evenodd"},u.createElement("g",{transform:"translate(1 1)",strokeWidth:"2"},u.createElement("circle",{strokeOpacity:".3",cx:"18",cy:"18",r:"18"}),u.createElement("path",{d:"M36 18c0-9.94-8.06-18-18-18"},u.createElement("animateTransform",{attributeName:"transform",type:"rotate",from:"0 18 18",to:"360 18 18",dur:"1s",repeatCount:"indefinite"})))))}function xa(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},u.createElement("path",{d:"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0"}),u.createElement("path",{d:"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13"})))}function Zr(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("path",{d:"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Aa(){return u.createElement("svg",{className:"DocSearch-Hit-Select-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},u.createElement("path",{d:"M18 3v4c0 2-2 4-4 4H2"}),u.createElement("path",{d:"M8 17l-6-6 6-6"})))}var Na=function(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("path",{d:"M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))};function Ta(e){switch(e.type){case"lvl1":return u.createElement(Na,null);case"content":return u.createElement(La,null);default:return u.createElement(Ra,null)}}function Ra(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("path",{d:"M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function La(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("path",{d:"M17 5H3h14zm0 5H3h14zm0 5H3h14z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function mo(){return u.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},u.createElement("path",{d:"M10 14.2L5 17l1-5.6-4-4 5.5-.7 2.5-5 2.5 5 5.6.8-4 4 .9 5.5z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function qa(){return u.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},u.createElement("path",{d:"M19 4.8a16 16 0 00-2-1.2m-3.3-1.2A16 16 0 001.1 4.7M16.7 8a12 12 0 00-2.8-1.4M10 6a12 12 0 00-6.7 2M12.3 14.7a4 4 0 00-4.5 0M14.5 11.4A8 8 0 0010 10M3 16L18 2M10 18h0"}))}function Ma(){return u.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},u.createElement("path",{d:"M15.5 4.8c2 3 1.7 7-1 9.7h0l4.3 4.3-4.3-4.3a7.8 7.8 0 01-9.8 1m-2.2-2.2A7.8 7.8 0 0113.2 2.4M2 18L18 2"}))}function Ha(e){var t=e.translations,r=t===void 0?{}:t,n=r.titleText,o=n===void 0?"Unable to fetch results":n,i=r.helpText,a=i===void 0?"You might want to check your network connection.":i;return u.createElement("div",{className:"DocSearch-ErrorScreen"},u.createElement("div",{className:"DocSearch-Screen-Icon"},u.createElement(qa,null)),u.createElement("p",{className:"DocSearch-Title"},o),u.createElement("p",{className:"DocSearch-Help"},a))}var Ua=["translations"];function Fa(e){var t=e.translations,r=t===void 0?{}:t,n=xe(e,Ua),o=r.noResultsText,i=o===void 0?"No results for":o,a=r.suggestedQueryText,c=a===void 0?"Try searching for":a,f=r.reportMissingResultsText,m=f===void 0?"Believe this query should return results?":f,b=r.reportMissingResultsLinkText,l=b===void 0?"Let us know.":b,v=n.state.context.searchSuggestions;return u.createElement("div",{className:"DocSearch-NoResults"},u.createElement("div",{className:"DocSearch-Screen-Icon"},u.createElement(Ma,null)),u.createElement("p",{className:"DocSearch-Title"},i,' "',u.createElement("strong",null,n.state.query),'"'),v&&v.length>0&&u.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},u.createElement("p",{className:"DocSearch-Help"},c,":"),u.createElement("ul",null,v.slice(0,3).reduce(function(s,S){return[].concat(jt(s),[u.createElement("li",{key:S},u.createElement("button",{className:"DocSearch-Prefill",key:S,type:"button",onClick:function(){n.setQuery(S.toLowerCase()+" "),n.refresh(),n.inputRef.current.focus()}},S))])},[]))),n.getMissingResultsUrl&&u.createElement("p",{className:"DocSearch-Help"},"".concat(m," "),u.createElement("a",{href:n.getMissingResultsUrl({query:n.state.query}),target:"_blank",rel:"noopener noreferrer"},l)))}var Ba=["hit","attribute","tagName"];function po(e,t){return t.split(".").reduce(function(r,n){return r!=null&&r[n]?r[n]:null},e)}function it(e){var t=e.hit,r=e.attribute,n=e.tagName;return De(n===void 0?"span":n,B(B({},xe(e,Ba)),{},{dangerouslySetInnerHTML:{__html:po(t,"_snippetResult.".concat(r,".value"))||po(t,r)}}))}function Gr(e){return e.collection&&e.collection.items.length!==0?u.createElement("section",{className:"DocSearch-Hits"},u.createElement("div",{className:"DocSearch-Hit-source"},e.title),u.createElement("ul",e.getListProps(),e.collection.items.map(function(t,r){return u.createElement(Va,le({key:[e.title,t.objectID].join(":"),item:t,index:r},e))}))):null}function Va(e){var t=e.item,r=e.index,n=e.renderIcon,o=e.renderAction,i=e.getItemProps,a=e.onItemClick,c=e.collection,f=e.hitComponent,m=he(u.useState(!1),2),b=m[0],l=m[1],v=he(u.useState(!1),2),s=v[0],S=v[1],g=u.useRef(null),y=f;return u.createElement("li",le({className:["DocSearch-Hit",t.__docsearch_parent&&"DocSearch-Hit--Child",b&&"DocSearch-Hit--deleting",s&&"DocSearch-Hit--favoriting"].filter(Boolean).join(" "),onTransitionEnd:function(){g.current&&g.current()}},i({item:t,source:c.source,onClick:function(_){a(t,_)}})),u.createElement(y,{hit:t},u.createElement("div",{className:"DocSearch-Hit-Container"},n({item:t,index:r}),t.hierarchy[t.type]&&t.type==="lvl1"&&u.createElement("div",{className:"DocSearch-Hit-content-wrapper"},u.createElement(it,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.lvl1"}),t.content&&u.createElement(it,{className:"DocSearch-Hit-path",hit:t,attribute:"content"})),t.hierarchy[t.type]&&(t.type==="lvl2"||t.type==="lvl3"||t.type==="lvl4"||t.type==="lvl5"||t.type==="lvl6")&&u.createElement("div",{className:"DocSearch-Hit-content-wrapper"},u.createElement(it,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.".concat(t.type)}),u.createElement(it,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),t.type==="content"&&u.createElement("div",{className:"DocSearch-Hit-content-wrapper"},u.createElement(it,{className:"DocSearch-Hit-title",hit:t,attribute:"content"}),u.createElement(it,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),o({item:t,runDeleteTransition:function(_){l(!0),g.current=_},runFavoriteTransition:function(_){S(!0),g.current=_}}))))}function vo(e,t,r){return e.reduce(function(n,o){var i=t(o);return n.hasOwnProperty(i)||(n[i]=[]),n[i].length<(r||5)&&n[i].push(o),n},{})}function ho(e){return e}function fr(e){return e.button===1||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}function Ka(){}var ai=/(|<\/mark>)/g,Wa=RegExp(ai.source);function ui(e){var t,r,n=e;if(!n.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var o=n.__docsearch_parent?(t=n.__docsearch_parent)===null||t===void 0||(t=t._highlightResult)===null||t===void 0||(t=t.hierarchy)===null||t===void 0?void 0:t.lvl0:(r=e._highlightResult)===null||r===void 0||(r=r.hierarchy)===null||r===void 0?void 0:r.lvl0;return o?o.value&&Wa.test(o.value)?o.value.replace(ai,""):o.value:e.hierarchy.lvl0}function za(e){return u.createElement("div",{className:"DocSearch-Dropdown-Container"},e.state.collections.map(function(t){if(t.items.length===0)return null;var r=ui(t.items[0]);return u.createElement(Gr,le({},e,{key:t.source.sourceId,title:r,collection:t,renderIcon:function(n){var o,i=n.item,a=n.index;return u.createElement(u.Fragment,null,i.__docsearch_parent&&u.createElement("svg",{className:"DocSearch-Hit-Tree",viewBox:"0 0 24 54"},u.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},i.__docsearch_parent!==((o=t.items[a+1])===null||o===void 0?void 0:o.__docsearch_parent)?u.createElement("path",{d:"M8 6v21M20 27H8.3"}):u.createElement("path",{d:"M8 6v42M20 27H8.3"}))),u.createElement("div",{className:"DocSearch-Hit-icon"},u.createElement(Ta,{type:i.type})))},renderAction:function(){return u.createElement("div",{className:"DocSearch-Hit-action"},u.createElement(Aa,null))}}))}),e.resultsFooterComponent&&u.createElement("section",{className:"DocSearch-HitsFooter"},u.createElement(e.resultsFooterComponent,{state:e.state})))}var Ja=["translations"];function Qa(e){var t=e.translations,r=t===void 0?{}:t,n=xe(e,Ja),o=r.recentSearchesTitle,i=o===void 0?"Recent":o,a=r.noRecentSearchesText,c=a===void 0?"No recent searches":a,f=r.saveRecentSearchButtonTitle,m=f===void 0?"Save this search":f,b=r.removeRecentSearchButtonTitle,l=b===void 0?"Remove this search from history":b,v=r.favoriteSearchesTitle,s=v===void 0?"Favorite":v,S=r.removeFavoriteSearchButtonTitle,g=S===void 0?"Remove this search from favorites":S;return n.state.status==="idle"&&n.hasCollections===!1?n.disableUserPersonalization?null:u.createElement("div",{className:"DocSearch-StartScreen"},u.createElement("p",{className:"DocSearch-Help"},c)):n.hasCollections===!1?null:u.createElement("div",{className:"DocSearch-Dropdown-Container"},u.createElement(Gr,le({},n,{title:i,collection:n.state.collections[0],renderIcon:function(){return u.createElement("div",{className:"DocSearch-Hit-icon"},u.createElement(xa,null))},renderAction:function(y){var _=y.item,h=y.runFavoriteTransition,p=y.runDeleteTransition;return u.createElement(u.Fragment,null,u.createElement("div",{className:"DocSearch-Hit-action"},u.createElement("button",{className:"DocSearch-Hit-action-button",title:m,type:"submit",onClick:function(d){d.preventDefault(),d.stopPropagation(),h(function(){n.favoriteSearches.add(_),n.recentSearches.remove(_),n.refresh()})}},u.createElement(mo,null))),u.createElement("div",{className:"DocSearch-Hit-action"},u.createElement("button",{className:"DocSearch-Hit-action-button",title:l,type:"submit",onClick:function(d){d.preventDefault(),d.stopPropagation(),p(function(){n.recentSearches.remove(_),n.refresh()})}},u.createElement(Zr,null))))}})),u.createElement(Gr,le({},n,{title:s,collection:n.state.collections[1],renderIcon:function(){return u.createElement("div",{className:"DocSearch-Hit-icon"},u.createElement(mo,null))},renderAction:function(y){var _=y.item,h=y.runDeleteTransition;return u.createElement("div",{className:"DocSearch-Hit-action"},u.createElement("button",{className:"DocSearch-Hit-action-button",title:g,type:"submit",onClick:function(p){p.preventDefault(),p.stopPropagation(),h(function(){n.favoriteSearches.remove(_),n.refresh()})}},u.createElement(Zr,null)))}})))}var $a=["translations"],Za=u.memo(function(e){var t=e.translations,r=t===void 0?{}:t,n=xe(e,$a);if(n.state.status==="error")return u.createElement(Ha,{translations:r==null?void 0:r.errorScreen});var o=n.state.collections.some(function(i){return i.items.length>0});return n.state.query?o===!1?u.createElement(Fa,le({},n,{translations:r==null?void 0:r.noResultsScreen})):u.createElement(za,n):u.createElement(Qa,le({},n,{hasCollections:o,translations:r==null?void 0:r.startScreen}))},function(e,t){return t.state.status==="loading"||t.state.status==="stalled"}),Ga=["translations"];function Ya(e){var t=e.translations,r=t===void 0?{}:t,n=xe(e,Ga),o=r.resetButtonTitle,i=o===void 0?"Clear the query":o,a=r.resetButtonAriaLabel,c=a===void 0?"Clear the query":a,f=r.cancelButtonText,m=f===void 0?"Cancel":f,b=r.cancelButtonAriaLabel,l=b===void 0?"Cancel":b,v=r.searchInputLabel,s=v===void 0?"Search":v,S=n.getFormProps({inputElement:n.inputRef.current}).onReset;return u.useEffect(function(){n.autoFocus&&n.inputRef.current&&n.inputRef.current.focus()},[n.autoFocus,n.inputRef]),u.useEffect(function(){n.isFromSelection&&n.inputRef.current&&n.inputRef.current.select()},[n.isFromSelection,n.inputRef]),u.createElement(u.Fragment,null,u.createElement("form",{className:"DocSearch-Form",onSubmit:function(g){g.preventDefault()},onReset:S},u.createElement("label",le({className:"DocSearch-MagnifierLabel"},n.getLabelProps()),u.createElement(Yo,null),u.createElement("span",{className:"DocSearch-VisuallyHiddenForAccessibility"},s)),u.createElement("div",{className:"DocSearch-LoadingIndicator"},u.createElement(Ca,null)),u.createElement("input",le({className:"DocSearch-Input",ref:n.inputRef},n.getInputProps({inputElement:n.inputRef.current,autoFocus:n.autoFocus,maxLength:64}))),u.createElement("button",{type:"reset",title:i,className:"DocSearch-Reset","aria-label":c,hidden:!n.state.query},u.createElement(Zr,null))),u.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":l,onClick:n.onClose},m))}var Xa=["_highlightResult","_snippetResult"];function yo(e){var t=e.key,r=e.limit,n=r===void 0?5:r,o=function(a){return function(){var c="__TEST_KEY__";try{return localStorage.setItem(c,""),localStorage.removeItem(c),!0}catch{return!1}}()===!1?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(c){return window.localStorage.setItem(a,JSON.stringify(c))},getItem:function(){var c=window.localStorage.getItem(a);return c?JSON.parse(c):[]}}}(t),i=o.getItem().slice(0,n);return{add:function(a){var c=a;c._highlightResult,c._snippetResult;var f=xe(c,Xa),m=i.findIndex(function(b){return b.objectID===f.objectID});m>-1&&i.splice(m,1),i.unshift(f),i=i.slice(0,n),o.setItem(i)},remove:function(a){i=i.filter(function(c){return c.objectID!==a.objectID}),o.setItem(i)},getAll:function(){return i}}}function eu(e){var t,r="algolia-client-js-".concat(e.key);function n(){return t===void 0&&(t=e.localStorage||window.localStorage),t}function o(){return JSON.parse(n().getItem(r)||"{}")}function i(a){n().setItem(r,JSON.stringify(a))}return{get:function(a,c){var f=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then(function(){var m,b,l;return m=e.timeToLive?1e3*e.timeToLive:null,b=o(),i(l=Object.fromEntries(Object.entries(b).filter(function(v){return he(v,2)[1].timestamp!==void 0}))),m&&i(Object.fromEntries(Object.entries(l).filter(function(v){var s=he(v,2)[1],S=new Date().getTime();return!(s.timestamp+m2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return o().then(function(a){return Promise.all([a,i.miss(a)])}).then(function(a){return he(a,1)[0]})},set:function(n,o){return Promise.resolve(o)},delete:function(n){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(n,o){var i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(n,o,i).catch(function(){return wt({caches:t}).get(n,o,i)})},set:function(n,o){return r.set(n,o).catch(function(){return wt({caches:t}).set(n,o)})},delete:function(n){return r.delete(n).catch(function(){return wt({caches:t}).delete(n)})},clear:function(){return r.clear().catch(function(){return wt({caches:t}).clear()})}}}function Mr(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}},i=JSON.stringify(r);if(i in t)return Promise.resolve(e.serializable?JSON.parse(t[i]):t[i]);var a=n();return a.then(function(c){return o.miss(c)}).then(function(){return a})},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function tu(e){var t=e.algoliaAgents,r=e.client,n=e.version,o=function(i){var a={value:"Algolia for JavaScript (".concat(i,")"),add:function(c){var f="; ".concat(c.segment).concat(c.version!==void 0?" (".concat(c.version,")"):"");return a.value.indexOf(f)===-1&&(a.value="".concat(a.value).concat(f)),a}};return a}(n).add({segment:r,version:n});return t.forEach(function(i){return o.add(i)}),o}var _o=12e4;function go(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"up",r=Date.now();return B(B({},e),{},{status:t,lastUpdate:r,isUp:function(){return t==="up"||Date.now()-r>_o},isTimedOut:function(){return t==="timed out"&&Date.now()-r<=_o}})}var ci=function(){function e(t,r){var n;return mt(this,e),vt(n=ft(this,e,[t]),"name","AlgoliaError"),r&&(n.name=r),n}return ht(e,Qr(Error)),pt(e)}(),li=function(){function e(t,r,n){var o;return mt(this,e),vt(o=ft(this,e,[t,n]),"stackTrace",void 0),o.stackTrace=r,o}return ht(e,ci),pt(e)}(),ru=function(){function e(t){return mt(this,e),ft(this,e,["Unreachable hosts - your application id may be incorrect. If the error persists, please reach out to the Algolia Support team: https://alg.li/support.",t,"RetryError"])}return ht(e,li),pt(e)}(),Yr=function(){function e(t,r,n){var o,i=arguments.length>3&&arguments[3]!==void 0?arguments[3]:"ApiError";return mt(this,e),vt(o=ft(this,e,[t,n,i]),"status",void 0),o.status=r,o}return ht(e,li),pt(e)}(),nu=function(){function e(t,r){var n;return mt(this,e),vt(n=ft(this,e,[t,"DeserializationError"]),"response",void 0),n.response=r,n}return ht(e,ci),pt(e)}(),ou=function(){function e(t,r,n,o){var i;return mt(this,e),vt(i=ft(this,e,[t,r,o,"DetailedApiError"]),"error",void 0),i.error=n,i}return ht(e,Yr),pt(e)}();function iu(e,t,r){var n,o=(n=r,Object.keys(n).filter(function(a){return n[a]!==void 0}).sort().map(function(a){return"".concat(a,"=").concat(encodeURIComponent(Object.prototype.toString.call(n[a])==="[object Array]"?n[a].join(","):n[a]).replace(/\+/g,"%20"))}).join("&")),i="".concat(e.protocol,"://").concat(e.url).concat(e.port?":".concat(e.port):"","/").concat(t.charAt(0)==="/"?t.substring(1):t);return o.length&&(i+="?".concat(o)),i}function au(e,t){if(e.method!=="GET"&&(e.data!==void 0||t.data!==void 0)){var r=Array.isArray(e.data)?e.data:B(B({},e.data),t.data);return JSON.stringify(r)}}function uu(e,t,r){var n=B(B(B({Accept:"application/json"},e),t),r),o={};return Object.keys(n).forEach(function(i){var a=n[i];o[i.toLowerCase()]=a}),o}function cu(e){try{return JSON.parse(e.content)}catch(t){throw new nu(t.message,e)}}function lu(e,t){var r=e.content,n=e.status;try{var o=JSON.parse(r);return"error"in o?new ou(o.message,n,o.error,t):new Yr(o.message,n,t)}catch{}return new Yr(r,n,t)}function su(e){return e.map(function(t){return si(t)})}function si(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return B(B({},e),{},{request:B(B({},e.request),{},{headers:B(B({},e.request.headers),t)})})}var fu=["appId","apiKey","authMode","algoliaAgents"],mu=["params"],bo="5.14.2";function pu(e){return[{url:"".concat(e,"-dsn.algolia.net"),accept:"read",protocol:"https"},{url:"".concat(e,".algolia.net"),accept:"write",protocol:"https"}].concat(function(t){for(var r=t,n=t.length-1;n>0;n--){var o=Math.floor(Math.random()*(n+1)),i=t[n];r[n]=t[o],r[o]=i}return r}([{url:"".concat(e,"-1.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-2.algolianet.com"),accept:"readWrite",protocol:"https"},{url:"".concat(e,"-3.algolianet.com"),accept:"readWrite",protocol:"https"}]))}var Xr="3.8.2",vu=["footer","searchBox"];function hu(e){var t=e.appId,r=e.apiKey,n=e.indexName,o=e.placeholder,i=o===void 0?"Search docs":o,a=e.searchParameters,c=e.maxResultsPerGroup,f=e.onClose,m=f===void 0?Ka:f,b=e.transformItems,l=b===void 0?ho:b,v=e.hitComponent,s=v===void 0?Da:v,S=e.resultsFooterComponent,g=S===void 0?function(){return null}:S,y=e.navigator,_=e.initialScrollY,h=_===void 0?0:_,p=e.transformSearchClient,d=p===void 0?ho:p,P=e.disableUserPersonalization,E=P!==void 0&&P,C=e.initialQuery,N=C===void 0?"":C,I=e.translations,x=I===void 0?{}:I,k=e.getMissingResultsUrl,U=e.insights,z=U!==void 0&&U,q=x.footer,oe=x.searchBox,O=xe(x,vu),w=he(u.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),j=w[0],R=w[1],D=u.useRef(null),L=u.useRef(null),W=u.useRef(null),K=u.useRef(null),J=u.useRef(null),G=u.useRef(10),se=u.useRef(typeof window<"u"?window.getSelection().toString().slice(0,64):"").current,ee=u.useRef(N||se).current,dt=function(F,Q,ae){return u.useMemo(function(){var me=function(de,_e){if(!de||typeof de!="string")throw new Error("`appId` is missing.");if(!_e||typeof _e!="string")throw new Error("`apiKey` is missing.");return function(M){var te=M.appId,X=M.apiKey,Pe=M.authMode,Me=M.algoliaAgents,Ie=xe(M,fu),Se=function(T,$){var re=arguments.length>2&&arguments[2]!==void 0?arguments[2]:"WithinHeaders",ye={"x-algolia-api-key":$,"x-algolia-application-id":T};return{headers:function(){return re==="WithinHeaders"?ye:{}},queryParameters:function(){return re==="WithinQueryParameters"?ye:{}}}}(te,X,Pe),pe=function(T){var $=T.hosts,re=T.hostsCache,ye=T.baseHeaders,ke=T.logger,He=T.baseQueryParameters,Ke=T.algoliaAgent,ln=T.timeouts,sn=T.requester,yt=T.requestsCache,gr=T.responsesCache;function mi(ge){return fn.apply(this,arguments)}function fn(){return(fn=xr(Ze().mark(function ge(ue){var ne,Ae,ce,ve,Ue;return Ze().wrap(function(Ne){for(;;)switch(Ne.prev=Ne.next){case 0:return Ne.next=2,Promise.all(ue.map(function(fe){return re.get(fe,function(){return Promise.resolve(go(fe))})}));case 2:return ne=Ne.sent,Ae=ne.filter(function(fe){return fe.isUp()}),ce=ne.filter(function(fe){return fe.isTimedOut()}),ve=[].concat(jt(Ae),jt(ce)),Ue=ve.length>0?ve:ue,Ne.abrupt("return",{hosts:Ue,getTimeout:function(fe,et){return(ce.length===0&&fe===0?1:ce.length+3+fe)*et}});case 8:case"end":return Ne.stop()}},ge)}))).apply(this,arguments)}function mn(ge,ue){return br.apply(this,arguments)}function br(){return br=xr(Ze().mark(function ge(ue,ne){var Ae,ce,ve,Ue,Ne,fe,et,Sr,We,Zt,Or,pn,wr,Er=arguments;return Ze().wrap(function(tt){for(;;)switch(tt.prev=tt.next){case 0:if(Ae=!(Er.length>2&&Er[2]!==void 0)||Er[2],ce=[],ve=au(ue,ne),Ue=uu(ye,ue.headers,ne.headers),Ne=ue.method==="GET"?B(B({},ue.data),ne.data):{},fe=B(B(B({},He),ue.queryParameters),Ne),Ke.value&&(fe["x-algolia-agent"]=Ke.value),ne&&ne.queryParameters)for(et=0,Sr=Object.keys(ne.queryParameters);et1&&arguments[1]!==void 0?arguments[1]:{},ne=ge.useReadTransporter||ge.method==="GET";if(!ne)return mn(ge,ue,ne);var Ae=function(){return mn(ge,ue)};if((ue.cacheable||ge.cacheable)!==!0)return Ae();var ce={request:ge,requestOptions:ue,transporter:{queryParameters:He,headers:ye}};return gr.get(ce,function(){return yt.get(ce,function(){return yt.set(ce,Ae()).then(function(ve){return Promise.all([yt.delete(ce),ve])},function(ve){return Promise.all([yt.delete(ce),Promise.reject(ve)])}).then(function(ve){var Ue=he(ve,2);return Ue[0],Ue[1]})})},{miss:function(ve){return gr.set(ce,ve)}})},requestsCache:yt,responsesCache:gr}}(B(B({hosts:pu(te)},Ie),{},{algoliaAgent:tu({algoliaAgents:Me,client:"Lite",version:bo}),baseHeaders:B(B({"content-type":"text/plain"},Se.headers()),Ie.baseHeaders),baseQueryParameters:B(B({},Se.queryParameters()),Ie.baseQueryParameters)}));return{transporter:pe,appId:te,clearCache:function(){return Promise.all([pe.requestsCache.clear(),pe.responsesCache.clear()]).then(function(){})},get _ua(){return pe.algoliaAgent.value},addAlgoliaAgent:function(T,$){pe.algoliaAgent.add({segment:T,version:$})},setClientApiKey:function(T){var $=T.apiKey;Pe&&Pe!=="WithinHeaders"?pe.baseQueryParameters["x-algolia-api-key"]=$:pe.baseHeaders["x-algolia-api-key"]=$},searchForHits:function(T,$){return this.search(T,$)},searchForFacets:function(T,$){return this.search(T,$)},customPost:function(T,$){var re=T.path,ye=T.parameters,ke=T.body;if(!re)throw new Error("Parameter `path` is required when calling `customPost`.");var He={method:"POST",path:"/{path}".replace("{path}",re),queryParameters:ye||{},headers:{},data:ke||{}};return pe.request(He,$)},getRecommendations:function(T,$){if(T&&Array.isArray(T)&&(T={requests:T}),!T)throw new Error("Parameter `getRecommendationsParams` is required when calling `getRecommendations`.");if(!T.requests)throw new Error("Parameter `getRecommendationsParams.requests` is required when calling `getRecommendations`.");var re={method:"POST",path:"/1/indexes/*/recommendations",queryParameters:{},headers:{},data:T,useReadTransporter:!0,cacheable:!0};return pe.request(re,$)},search:function(T,$){if(T&&Array.isArray(T)){var re={requests:T.map(function(ke){var He=ke.params,Ke=xe(ke,mu);return Ke.type==="facet"?B(B(B({},Ke),He),{},{type:"facet"}):B(B(B({},Ke),He),{},{facet:void 0,maxFacetHits:void 0,facetQuery:void 0})})};T=re}if(!T)throw new Error("Parameter `searchMethodParams` is required when calling `search`.");if(!T.requests)throw new Error("Parameter `searchMethodParams.requests` is required when calling `search`.");var ye={method:"POST",path:"/1/indexes/*/queries",queryParameters:{},headers:{},data:T,useReadTransporter:!0,cacheable:!0};return pe.request(ye,$)}}}(B({appId:de,apiKey:_e,timeouts:{connect:1e3,read:2e3,write:3e4},logger:{debug:function(M,te){return Promise.resolve()},info:function(M,te){return Promise.resolve()},error:function(M,te){return Promise.resolve()}},requester:{send:function(M){return new Promise(function(te){var X=new XMLHttpRequest;X.open(M.method,M.url,!0),Object.keys(M.headers).forEach(function(Se){return X.setRequestHeader(Se,M.headers[Se])});var Pe,Me=function(Se,pe){return setTimeout(function(){X.abort(),te({status:0,content:pe,isTimedOut:!0})},Se)},Ie=Me(M.connectTimeout,"Connection timeout");X.onreadystatechange=function(){X.readyState>X.OPENED&&Pe===void 0&&(clearTimeout(Ie),Pe=Me(M.responseTimeout,"Socket timeout"))},X.onerror=function(){X.status===0&&(clearTimeout(Ie),clearTimeout(Pe),te({content:X.responseText||"Network request failed",status:X.status,isTimedOut:!1}))},X.onload=function(){clearTimeout(Ie),clearTimeout(Pe),te({content:X.responseText,status:X.status,isTimedOut:!1})},X.send(M.data)})}},algoliaAgents:[{segment:"Browser"}],authMode:"WithinQueryParameters",responsesCache:Mr(),requestsCache:Mr({serializable:!1}),hostsCache:wt({caches:[eu({key:"".concat(bo,"-").concat(de)}),Mr()]})},void 0))}(F,Q);return me.addAlgoliaAgent("docsearch",Xr),/docsearch.js \(.*\)/.test(me.transporter.algoliaAgent.value)===!1&&me.addAlgoliaAgent("docsearch-react",Xr),ae(me)},[F,Q,ae])}(t,r,d),Ee=u.useRef(yo({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(n),limit:10})).current,Ve=u.useRef(yo({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(n),limit:Ee.getAll().length===0?7:4})).current,je=u.useCallback(function(F){if(!E){var Q=F.type==="content"?F.__docsearch_parent:F;Q&&Ee.getAll().findIndex(function(ae){return ae.objectID===Q.objectID})===-1&&Ve.add(Q)}},[Ee,Ve,E]),Xe=u.useCallback(function(F){if(j.context.algoliaInsightsPlugin&&F.__autocomplete_id){var Q=F,ae={eventName:"Item Selected",index:Q.__autocomplete_indexName,items:[Q],positions:[F.__autocomplete_id],queryID:Q.__autocomplete_queryID};j.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(ae)}},[j.context.algoliaInsightsPlugin]),qe=u.useMemo(function(){return Pa({id:"docsearch",defaultActiveItemId:0,placeholder:i,openOnFocus:!0,initialState:{query:ee,context:{searchSuggestions:[]}},insights:z,navigator:y,onStateChange:function(F){R(F.state)},getSources:function(F){var Q=F.query,ae=F.state,me=F.setContext,de=F.setStatus;if(!Q)return E?[]:[{sourceId:"recentSearches",onSelect:function(M){var te=M.item,X=M.event;je(te),fr(X)||m()},getItemUrl:function(M){return M.item.url},getItems:function(){return Ve.getAll()}},{sourceId:"favoriteSearches",onSelect:function(M){var te=M.item,X=M.event;je(te),fr(X)||m()},getItemUrl:function(M){return M.item.url},getItems:function(){return Ee.getAll()}}];var _e=!!z;return dt.search({requests:[B({query:Q,indexName:n,attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(G.current),"hierarchy.lvl2:".concat(G.current),"hierarchy.lvl3:".concat(G.current),"hierarchy.lvl4:".concat(G.current),"hierarchy.lvl5:".concat(G.current),"hierarchy.lvl6:".concat(G.current),"content:".concat(G.current)],snippetEllipsisText:"…",highlightPreTag:"",highlightPostTag:"",hitsPerPage:20,clickAnalytics:_e},a)]}).catch(function(M){throw M.name==="RetryError"&&de("error"),M}).then(function(M){var te=M.results[0],X=te.hits,Pe=te.nbHits,Me=vo(X,function(Se){return ui(Se)},c);ae.context.searchSuggestions.length0&&(cn(),J.current&&J.current.focus())},[ee,cn]),u.useEffect(function(){function F(){if(L.current){var Q=.01*window.innerHeight;L.current.style.setProperty("--docsearch-vh","".concat(Q,"px"))}}return F(),window.addEventListener("resize",F),function(){window.removeEventListener("resize",F)}},[]),u.createElement("div",le({ref:D},fi({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container",j.status==="stalled"&&"DocSearch-Container--Stalled",j.status==="error"&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(F){F.target===F.currentTarget&&m()}}),u.createElement("div",{className:"DocSearch-Modal",ref:L},u.createElement("header",{className:"DocSearch-SearchBar",ref:W},u.createElement(Ya,le({},qe,{state:j,autoFocus:ee.length===0,inputRef:J,isFromSelection:!!ee&&ee===se,translations:oe,onClose:m}))),u.createElement("div",{className:"DocSearch-Dropdown",ref:K},u.createElement(Za,le({},qe,{indexName:n,state:j,hitComponent:s,resultsFooterComponent:g,disableUserPersonalization:E,recentSearches:Ve,favoriteSearches:Ee,inputRef:J,translations:O,getMissingResultsUrl:k,onItemClick:function(F,Q){Xe(F),je(F),fr(Q)||m()}}))),u.createElement("footer",{className:"DocSearch-Footer"},u.createElement(ka,{translations:q}))))}function du(e){var t,r,n=u.useRef(null),o=he(u.useState(!1),2),i=o[0],a=o[1],c=he(u.useState((e==null?void 0:e.initialQuery)||void 0),2),f=c[0],m=c[1],b=u.useCallback(function(){a(!0)},[a]),l=u.useCallback(function(){a(!1),m(e==null?void 0:e.initialQuery)},[a,e.initialQuery]);return function(v){var s=v.isOpen,S=v.onOpen,g=v.onClose,y=v.onInput,_=v.searchButtonRef;u.useEffect(function(){function h(p){var d;if(p.code==="Escape"&&s||((d=p.key)===null||d===void 0?void 0:d.toLowerCase())==="k"&&(p.metaKey||p.ctrlKey)||!function(P){var E=P.target,C=E.tagName;return E.isContentEditable||C==="INPUT"||C==="SELECT"||C==="TEXTAREA"}(p)&&p.key==="/"&&!s)return p.preventDefault(),void(s?g():document.body.classList.contains("DocSearch--active")||S());_&&_.current===document.activeElement&&y&&/[a-zA-Z0-9]/.test(String.fromCharCode(p.keyCode))&&y(p)}return window.addEventListener("keydown",h),function(){window.removeEventListener("keydown",h)}},[s,S,g,y,_])}({isOpen:i,onOpen:b,onClose:l,onInput:u.useCallback(function(v){a(!0),m(v.key)},[a,m]),searchButtonRef:n}),u.createElement(u.Fragment,null,u.createElement(zi,{ref:n,translations:e==null||(t=e.translations)===null||t===void 0?void 0:t.button,onClick:b}),i&&Vo(u.createElement(hu,le({},e,{initialScrollY:window.scrollY,initialQuery:f,translations:e==null||(r=e.translations)===null||r===void 0?void 0:r.modal,onClose:l})),document.body))}function yu(e){Wo(u.createElement(du,Hr({},e,{transformSearchClient:function(t){return t.addAlgoliaAgent("docsearch.js",Xr),e.transformSearchClient?e.transformSearchClient(t):t}})),function(t){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:window;return typeof t=="string"?r.document.querySelector(t):t}(e.container,e.environment))}const _u={id:"docsearch"},Su=pi({__name:"VPAlgoliaSearchBox",props:{algolia:{}},setup(e){const t=e,r=vi(),n=hi(),{site:o,localeIndex:i,lang:a}=Si();di(c),yi(i,c);async function c(){var s,S;await _i();const b={...t.algolia,...(s=t.algolia.locales)==null?void 0:s[i.value]},l=((S=b.searchParameters)==null?void 0:S.facetFilters)??[],v=[...(Array.isArray(l)?l:[l]).filter(g=>!g.startsWith("lang:")),`lang:${a.value}`];f({...b,searchParameters:{...b.searchParameters,facetFilters:v}})}function f(b){const l=Object.assign({},b,{container:"#docsearch",navigator:{navigate({itemUrl:v}){const{pathname:s}=new URL(window.location.origin+v);n.path===s?window.location.assign(window.location.origin+v):r.go(v)}},transformItems(v){return v.map(s=>Object.assign({},s,{url:m(s.url)}))},hitComponent({hit:v,children:s}){return{__v:null,type:"a",ref:void 0,constructor:void 0,key:void 0,props:{href:v.url,children:s}}}});yu(l)}function m(b){const{pathname:l,hash:v}=new URL(b,location.origin);return l.replace(/\.html$/,o.value.cleanUrls?"":".html")+v}return(b,l)=>(bi(),gi("div",_u))}});export{Su as default}; diff --git a/assets/chunks/VPAlgoliaSearchBox.faa390b4.js b/assets/chunks/VPAlgoliaSearchBox.faa390b4.js deleted file mode 100644 index d7f189f7e9..0000000000 --- a/assets/chunks/VPAlgoliaSearchBox.faa390b4.js +++ /dev/null @@ -1,17 +0,0 @@ -import{u as fo,ag as mo,k as po,A as vo,q as ho,v as yo,b as go}from"./framework.70afa331.js";import{u as bo}from"./theme.b9d97670.js";/*! @docsearch/js 3.5.1 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */function cn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function I(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function st(t,e){return function(n){if(Array.isArray(n))return n}(t)||function(n,r){var o=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(o!=null){var i,a,u=[],c=!0,s=!1;try{for(o=o.call(n);!(c=(i=o.next()).done)&&(u.push(i.value),!r||u.length!==r);c=!0);}catch(l){s=!0,a=l}finally{try{c||o.return==null||o.return()}finally{if(s)throw a}}return u}}(t,e)||yr(t,e)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function ft(t){return function(e){if(Array.isArray(e))return Lt(e)}(t)||function(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}(t)||yr(t)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function yr(t,e){if(t){if(typeof t=="string")return Lt(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return n==="Object"&&t.constructor&&(n=t.constructor.name),n==="Map"||n==="Set"?Array.from(t):n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Lt(t,e):void 0}}function Lt(t,e){(e==null||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n3)for(n=[n],i=3;i0?Pe(v.type,v.props,v.key,null,v.__v):v)!=null){if(v.__=n,v.__b=n.__b+1,(p=b[l])===null||p&&v.key==p.key&&v.type===p.type)b[l]=void 0;else for(m=0;m<_;m++){if((p=b[m])&&v.key==p.key&&v.type===p.type){b[m]=void 0;break}p=null}Zt(t,v,p=p||mt,o,i,a,u,c,s),d=v.__e,(m=v.ref)&&p.ref!=m&&(y||(y=[]),p.ref&&y.push(p.ref,null,v),y.push(m,v.__c||d,v)),d!=null?(h==null&&(h=d),typeof v.type=="function"&&v.__k!=null&&v.__k===p.__k?v.__d=c=wr(v,c,t):c=jr(t,v,p,b,d,c),s||n.type!=="option"?typeof n.type=="function"&&(n.__d=c):t.value=""):c&&p.__e==c&&c.parentNode!=t&&(c=Ve(p))}for(n.__e=h,l=_;l--;)b[l]!=null&&(typeof n.type=="function"&&b[l].__e!=null&&b[l].__e==n.__d&&(n.__d=Ve(r,l+1)),Ir(b[l],b[l]));if(y)for(l=0;l3)for(n=[n],i=3;i=n.__.length&&n.__.push({}),n.__[t]}function kr(t){return pe=1,Ar(xr,t)}function Ar(t,e,n){var r=ze(de++,2);return r.t=t,r.__c||(r.__=[n?n(e):xr(void 0,e),function(o){var i=r.t(r.__[0],o);r.__[0]!==i&&(r.__=[i,r.__[1]],r.__c.setState({}))}],r.__c=q),r.__}function Cr(t,e){var n=ze(de++,3);!w.__s&&Yt(n.__H,e)&&(n.__=t,n.__H=e,q.__H.__h.push(n))}function gn(t,e){var n=ze(de++,4);!w.__s&&Yt(n.__H,e)&&(n.__=t,n.__H=e,q.__h.push(n))}function Pt(t,e){var n=ze(de++,7);return Yt(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function Po(){Ht.forEach(function(t){if(t.__P)try{t.__H.__h.forEach(at),t.__H.__h.forEach(Ut),t.__H.__h=[]}catch(e){t.__H.__h=[],w.__e(e,t.__v)}}),Ht=[]}w.__b=function(t){q=null,pn&&pn(t)},w.__r=function(t){vn&&vn(t),de=0;var e=(q=t.__c).__H;e&&(e.__h.forEach(at),e.__h.forEach(Ut),e.__h=[])},w.diffed=function(t){dn&&dn(t);var e=t.__c;e&&e.__H&&e.__H.__h.length&&(Ht.push(e)!==1&&mn===w.requestAnimationFrame||((mn=w.requestAnimationFrame)||function(n){var r,o=function(){clearTimeout(i),bn&&cancelAnimationFrame(r),setTimeout(n)},i=setTimeout(o,100);bn&&(r=requestAnimationFrame(o))})(Po)),q=void 0},w.__c=function(t,e){e.some(function(n){try{n.__h.forEach(at),n.__h=n.__h.filter(function(r){return!r.__||Ut(r)})}catch(r){e.some(function(o){o.__h&&(o.__h=[])}),e=[],w.__e(r,n.__v)}}),hn&&hn(t,e)},w.unmount=function(t){yn&&yn(t);var e=t.__c;if(e&&e.__H)try{e.__H.__.forEach(at)}catch(n){w.__e(n,e.__v)}};var bn=typeof requestAnimationFrame=="function";function at(t){var e=q;typeof t.__c=="function"&&t.__c(),q=e}function Ut(t){var e=q;t.__c=t.__(),q=e}function Yt(t,e){return!t||t.length!==e.length||e.some(function(n,r){return n!==t[r]})}function xr(t,e){return typeof e=="function"?e(t):e}function Nr(t,e){for(var n in e)t[n]=e[n];return t}function Ft(t,e){for(var n in t)if(n!=="__source"&&!(n in e))return!0;for(var r in e)if(r!=="__source"&&t[r]!==e[r])return!0;return!1}function Bt(t){this.props=t}(Bt.prototype=new W).isPureReactComponent=!0,Bt.prototype.shouldComponentUpdate=function(t,e){return Ft(this.props,t)||Ft(this.state,e)};var _n=w.__b;w.__b=function(t){t.type&&t.type.__f&&t.ref&&(t.props.ref=t.ref,t.ref=null),_n&&_n(t)};var Io=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911,On=function(t,e){return t==null?null:J(J(t).map(e))},Do={map:On,forEach:On,count:function(t){return t?J(t).length:0},only:function(t){var e=J(t);if(e.length!==1)throw"Children.only";return e[0]},toArray:J},ko=w.__e;function ct(){this.__u=0,this.t=null,this.__b=null}function Tr(t){var e=t.__.__c;return e&&e.__e&&e.__e(t)}function we(){this.u=null,this.o=null}w.__e=function(t,e,n){if(t.then){for(var r,o=e;o=o.__;)if((r=o.__c)&&r.__c)return e.__e==null&&(e.__e=n.__e,e.__k=n.__k),r.__c(t,e)}ko(t,e,n)},(ct.prototype=new W).__c=function(t,e){var n=e.__c,r=this;r.t==null&&(r.t=[]),r.t.push(n);var o=Tr(r.__v),i=!1,a=function(){i||(i=!0,n.componentWillUnmount=n.__c,o?o(u):u())};n.__c=n.componentWillUnmount,n.componentWillUnmount=function(){a(),n.__c&&n.__c()};var u=function(){if(!--r.__u){if(r.state.__e){var s=r.state.__e;r.__v.__k[0]=function m(p,v,d){return p&&(p.__v=null,p.__k=p.__k&&p.__k.map(function(h){return m(h,v,d)}),p.__c&&p.__c.__P===v&&(p.__e&&d.insertBefore(p.__e,p.__d),p.__c.__e=!0,p.__c.__P=d)),p}(s,s.__c.__P,s.__c.__O)}var l;for(r.setState({__e:r.__b=null});l=r.t.pop();)l.forceUpdate()}},c=e.__h===!0;r.__u++||c||r.setState({__e:r.__b=r.__v.__k[0]}),t.then(a,a)},ct.prototype.componentWillUnmount=function(){this.t=[]},ct.prototype.render=function(t,e){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),r=this.__v.__k[0].__c;this.__v.__k[0]=function i(a,u,c){return a&&(a.__c&&a.__c.__H&&(a.__c.__H.__.forEach(function(s){typeof s.__c=="function"&&s.__c()}),a.__c.__H=null),(a=Nr({},a)).__c!=null&&(a.__c.__P===c&&(a.__c.__P=u),a.__c=null),a.__k=a.__k&&a.__k.map(function(s){return i(s,u,c)})),a}(this.__b,n,r.__O=r.__P)}this.__b=null}var o=e.__e&&V(X,null,t.fallback);return o&&(o.__h=null),[V(X,null,e.__e?null:t.children),o]};var Sn=function(t,e,n){if(++n[1]===n[0]&&t.o.delete(e),t.props.revealOrder&&(t.props.revealOrder[0]!=="t"||!t.o.size))for(n=t.u;n;){for(;n.length>3;)n.pop()();if(n[1]>>1,1),e.i.removeChild(r)}}),We(V(Ao,{context:e.context},t.__v),e.l)):e.l&&e.componentWillUnmount()}function Rr(t,e){return V(Co,{__v:t,i:e})}(we.prototype=new W).__e=function(t){var e=this,n=Tr(e.__v),r=e.o.get(t);return r[0]++,function(o){var i=function(){e.props.revealOrder?(r.push(o),Sn(e,t,r)):o()};n?n(i):i()}},we.prototype.render=function(t){this.u=null,this.o=new Map;var e=J(t.children);t.revealOrder&&t.revealOrder[0]==="b"&&e.reverse();for(var n=e.length;n--;)this.o.set(e[n],this.u=[1,0,this.u]);return t.children},we.prototype.componentDidUpdate=we.prototype.componentDidMount=function(){var t=this;this.o.forEach(function(e,n){Sn(t,n,e)})};var qr=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,xo=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,No=function(t){return(typeof Symbol<"u"&&Be(Symbol())=="symbol"?/fil|che|rad/i:/fil|che|ra/i).test(t)};function Lr(t,e,n){return e.__k==null&&(e.textContent=""),We(t,e),typeof n=="function"&&n(),t?t.__c:null}W.prototype.isReactComponent={},["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(W.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(e){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:e})}})});var wn=w.event;function To(){}function Ro(){return this.cancelBubble}function qo(){return this.defaultPrevented}w.event=function(t){return wn&&(t=wn(t)),t.persist=To,t.isPropagationStopped=Ro,t.isDefaultPrevented=qo,t.nativeEvent=t};var Mr,jn={configurable:!0,get:function(){return this.class}},En=w.vnode;w.vnode=function(t){var e=t.type,n=t.props,r=n;if(typeof e=="string"){for(var o in r={},n){var i=n[o];o==="value"&&"defaultValue"in n&&i==null||(o==="defaultValue"&&"value"in n&&n.value==null?o="value":o==="download"&&i===!0?i="":/ondoubleclick/i.test(o)?o="ondblclick":/^onchange(textarea|input)/i.test(o+e)&&!No(n.type)?o="oninput":/^on(Ani|Tra|Tou|BeforeInp)/.test(o)?o=o.toLowerCase():xo.test(o)?o=o.replace(/[A-Z0-9]/,"-$&").toLowerCase():i===null&&(i=void 0),r[o]=i)}e=="select"&&r.multiple&&Array.isArray(r.value)&&(r.value=J(n.children).forEach(function(a){a.props.selected=r.value.indexOf(a.props.value)!=-1})),e=="select"&&r.defaultValue!=null&&(r.value=J(n.children).forEach(function(a){a.props.selected=r.multiple?r.defaultValue.indexOf(a.props.value)!=-1:r.defaultValue==a.props.value})),t.props=r}e&&n.class!=n.className&&(jn.enumerable="className"in n,n.className!=null&&(r.class=n.className),Object.defineProperty(r,"className",jn)),t.$$typeof=qr,En&&En(t)};var Pn=w.__r;w.__r=function(t){Pn&&Pn(t),Mr=t.__c};var Lo={ReactCurrentDispatcher:{current:{readContext:function(t){return Mr.__n[t.__c].props.value}}}};(typeof performance>"u"?"undefined":Be(performance))=="object"&&typeof performance.now=="function"&&performance.now.bind(performance);function In(t){return!!t&&t.$$typeof===qr}var f={useState:kr,useReducer:Ar,useEffect:Cr,useLayoutEffect:gn,useRef:function(t){return pe=5,Pt(function(){return{current:t}},[])},useImperativeHandle:function(t,e,n){pe=6,gn(function(){typeof t=="function"?t(e()):t&&(t.current=e())},n==null?n:n.concat(t))},useMemo:Pt,useCallback:function(t,e){return pe=8,Pt(function(){return t},e)},useContext:function(t){var e=q.context[t.__c],n=ze(de++,9);return n.__c=t,e?(n.__==null&&(n.__=!0,e.sub(q)),e.props.value):t.__},useDebugValue:function(t,e){w.useDebugValue&&w.useDebugValue(e?e(t):t)},version:"16.8.0",Children:Do,render:Lr,hydrate:function(t,e,n){return Dr(t,e),typeof n=="function"&&n(),t?t.__c:null},unmountComponentAtNode:function(t){return!!t.__k&&(We(null,t),!0)},createPortal:Rr,createElement:V,createContext:function(t,e){var n={__c:e="__cC"+br++,__:t,Consumer:function(r,o){return r.children(o)},Provider:function(r){var o,i;return this.getChildContext||(o=[],(i={})[e]=this,this.getChildContext=function(){return i},this.shouldComponentUpdate=function(a){this.props.value!==a.value&&o.some(Mt)},this.sub=function(a){o.push(a);var u=a.componentWillUnmount;a.componentWillUnmount=function(){o.splice(o.indexOf(a),1),u&&u.call(a)}}),r.children}};return n.Provider.__=n.Consumer.contextType=n},createFactory:function(t){return V.bind(null,t)},cloneElement:function(t){return In(t)?Eo.apply(null,arguments):t},createRef:function(){return{current:null}},Fragment:X,isValidElement:In,findDOMNode:function(t){return t&&(t.base||t.nodeType===1&&t)||null},Component:W,PureComponent:Bt,memo:function(t,e){function n(o){var i=this.props.ref,a=i==o.ref;return!a&&i&&(i.call?i(null):i.current=null),e?!e(this.props,o)||!a:Ft(this.props,o)}function r(o){return this.shouldComponentUpdate=n,V(t,o)}return r.displayName="Memo("+(t.displayName||t.name)+")",r.prototype.isReactComponent=!0,r.__f=!0,r},forwardRef:function(t){function e(n,r){var o=Nr({},n);return delete o.ref,t(o,(r=n.ref||r)&&(Be(r)!="object"||"current"in r)?r:null)}return e.$$typeof=Io,e.render=e,e.prototype.isReactComponent=e.__f=!0,e.displayName="ForwardRef("+(t.displayName||t.name)+")",e},unstable_batchedUpdates:function(t,e){return t(e)},StrictMode:X,Suspense:ct,SuspenseList:we,lazy:function(t){var e,n,r;function o(i){if(e||(e=t()).then(function(a){n=a.default||a},function(a){r=a}),r)throw r;if(!n)throw e;return V(n,i)}return o.displayName="Lazy",o.__f=!0,o},__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:Lo};function Mo(){return f.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},f.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}function Hr(){return f.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},f.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var Ho=["translations"];function Vt(){return Vt=Object.assign||function(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var Bo=f.forwardRef(function(t,e){var n=t.translations,r=n===void 0?{}:n,o=Fo(t,Ho),i=r.buttonText,a=i===void 0?"Search":i,u=r.buttonAriaLabel,c=u===void 0?"Search":u,s=Uo(kr(null),2),l=s[0],m=s[1];return Cr(function(){typeof navigator<"u"&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?m("⌘"):m("Ctrl"))},[]),f.createElement("button",Vt({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:e}),f.createElement("span",{className:"DocSearch-Button-Container"},f.createElement(Hr,null),f.createElement("span",{className:"DocSearch-Button-Placeholder"},a)),f.createElement("span",{className:"DocSearch-Button-Keys"},l!==null&&f.createElement(f.Fragment,null,f.createElement("kbd",{className:"DocSearch-Button-Key"},l==="Ctrl"?f.createElement(Mo,null):l),f.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))});function Ur(t,e){var n=void 0;return function(){for(var r=arguments.length,o=new Array(r),i=0;it.length)&&(e=t.length);for(var n=0,r=new Array(e);nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function xn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function ve(t){for(var e=1;e1&&arguments[1]!==void 0?arguments[1]:20,n=[],r=0;r=3||n===2&&r>=4||n===1&&r>=10);function i(a,u,c){if(o&&c!==void 0){var s=c[0].__autocomplete_algoliaCredentials,l={"X-Algolia-Application-Id":s.appId,"X-Algolia-API-Key":s.apiKey};t.apply(void 0,[a].concat(Ye(u),[{headers:l}]))}else t.apply(void 0,[a].concat(Ye(u)))}return{init:function(a,u){t("init",{appId:a,apiKey:u})},setUserToken:function(a){t("setUserToken",a)},clickedObjectIDsAfterSearch:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&i("clickedObjectIDsAfterSearch",Ge(u),u[0].items)},clickedObjectIDs:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&i("clickedObjectIDs",Ge(u),u[0].items)},clickedFilters:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&t.apply(void 0,["clickedFilters"].concat(u))},convertedObjectIDsAfterSearch:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&i("convertedObjectIDsAfterSearch",Ge(u),u[0].items)},convertedObjectIDs:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&i("convertedObjectIDs",Ge(u),u[0].items)},convertedFilters:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&t.apply(void 0,["convertedFilters"].concat(u))},viewedObjectIDs:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&u.reduce(function(s,l){var m=l.items,p=Br(l,$o);return[].concat(Ye(s),Ye(Qo(ve(ve({},p),{},{objectIDs:(m==null?void 0:m.map(function(v){return v.objectID}))||p.objectIDs})).map(function(v){return{items:m,payload:v}})))},[]).forEach(function(s){var l=s.items;return i("viewedObjectIDs",[s.payload],l)})},viewedFilters:function(){for(var a=arguments.length,u=new Array(a),c=0;c0&&t.apply(void 0,["viewedFilters"].concat(u))}}}function Yo(t){var e=t.items.reduce(function(n,r){var o;return n[r.__autocomplete_indexName]=((o=n[r.__autocomplete_indexName])!==null&&o!==void 0?o:[]).concat(r),n},{});return Object.keys(e).map(function(n){return{index:n,items:e[n],algoliaSource:["autocomplete"]}})}function Dt(t){return t.objectID&&t.__autocomplete_indexName&&t.__autocomplete_queryID}function De(t){return De=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},De(t)}function ae(t){return function(e){if(Array.isArray(e))return kt(e)}(t)||function(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}(t)||function(e,n){if(e){if(typeof e=="string")return kt(e,n);var r=Object.prototype.toString.call(e).slice(8,-1);if(r==="Object"&&e.constructor&&(r=e.constructor.name),r==="Map"||r==="Set")return Array.from(e);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return kt(e,n)}}(t)||function(){throw new TypeError(`Invalid attempt to spread non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function kt(t,e){(e==null||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n0&&ei({onItemsChange:r,items:p,insights:u,state:m}))}},0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(l){var m=l.setContext,p=l.onSelect,v=l.onActive;a("addAlgoliaAgent","insights-plugin"),m({algoliaInsightsPlugin:{__algoliaSearchParameters:{clickAnalytics:!0},insights:u}}),p(function(d){var h=d.item,y=d.state,b=d.event;Dt(h)&&o({state:y,event:b,insights:u,item:h,insightsEvents:[G({eventName:"Item Selected"},An({item:h,items:c.current}))]})}),v(function(d){var h=d.item,y=d.state,b=d.event;Dt(h)&&i({state:y,event:b,insights:u,item:h,insightsEvents:[G({eventName:"Item Active"},An({item:h,items:c.current}))]})})},onStateChange:function(l){var m=l.state;s({state:m})},__autocomplete_pluginOptions:t}}function ut(t,e){var n=e;return{then:function(r,o){return ut(t.then(Xe(r,n,t),Xe(o,n,t)),n)},catch:function(r){return ut(t.catch(Xe(r,n,t)),n)},finally:function(r){return r&&n.onCancelList.push(r),ut(t.finally(Xe(r&&function(){return n.onCancelList=[],r()},n,t)),n)},cancel:function(){n.isCanceled=!0;var r=n.onCancelList;n.onCancelList=[],r.forEach(function(o){o()})},isCanceled:function(){return n.isCanceled===!0}}}function Tn(t){return ut(t,{isCanceled:!1,onCancelList:[]})}function Xe(t,e,n){return t?function(r){return e.isCanceled?r:t(r)}:n}function Rn(t,e,n,r){if(!n)return null;if(t<0&&(e===null||r!==null&&e===0))return n+t;var o=(e===null?-1:e)+t;return o<=-1||o>=n?r===null?null:0:o}function qn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function Ln(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n0},reshape:function(i){return i.sources}},t),{},{id:(n=t.id)!==null&&n!==void 0?n:"autocomplete-".concat(Vo++),plugins:o,initialState:ce({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},t.initialState),onStateChange:function(i){var a;(a=t.onStateChange)===null||a===void 0||a.call(t,i),o.forEach(function(u){var c;return(c=u.onStateChange)===null||c===void 0?void 0:c.call(u,i)})},onSubmit:function(i){var a;(a=t.onSubmit)===null||a===void 0||a.call(t,i),o.forEach(function(u){var c;return(c=u.onSubmit)===null||c===void 0?void 0:c.call(u,i)})},onReset:function(i){var a;(a=t.onReset)===null||a===void 0||a.call(t,i),o.forEach(function(u){var c;return(c=u.onReset)===null||c===void 0?void 0:c.call(u,i)})},getSources:function(i){return Promise.all([].concat(ci(o.map(function(a){return a.getSources})),[t.getSources]).filter(Boolean).map(function(a){return function(u,c){var s=[];return Promise.resolve(u(c)).then(function(l){return Promise.all(l.filter(function(m){return!!m}).map(function(m){if(m.sourceId,s.includes(m.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(m.sourceId)," is not unique."));s.push(m.sourceId);var p={getItemInputValue:function(d){return d.state.query},getItemUrl:function(){},onSelect:function(d){(0,d.setIsOpen)(!1)},onActive:vt,onResolve:vt};Object.keys(p).forEach(function(d){p[d].__default=!0});var v=Ln(Ln({},p),m);return Promise.resolve(v)}))})}(a,i)})).then(function(a){return Ke(a)}).then(function(a){return a.map(function(u){return ce(ce({},u),{},{onSelect:function(c){u.onSelect(c),e.forEach(function(s){var l;return(l=s.onSelect)===null||l===void 0?void 0:l.call(s,c)})},onActive:function(c){u.onActive(c),e.forEach(function(s){var l;return(l=s.onActive)===null||l===void 0?void 0:l.call(s,c)})},onResolve:function(c){u.onResolve(c),e.forEach(function(s){var l;return(l=s.onResolve)===null||l===void 0?void 0:l.call(s,c)})}})})})},navigator:ce({navigate:function(i){var a=i.itemUrl;r.location.assign(a)},navigateNewTab:function(i){var a=i.itemUrl,u=r.open(a,"_blank","noopener");u==null||u.focus()},navigateNewWindow:function(i){var a=i.itemUrl;r.open(a,"_blank","noopener")}},t.navigator)})}function Ne(t){return Ne=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ne(t)}function Fn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function tt(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var Wn,xt,rt,Se=null,Kn=(Wn=-1,xt=-1,rt=void 0,function(t){var e=++Wn;return Promise.resolve(t).then(function(n){return rt&&e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function Le(t){return Le=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Le(t)}var _i=["props","refresh","store"],Oi=["inputElement","formElement","panelElement"],Si=["inputElement"],wi=["inputElement","maxLength"],ji=["sourceIndex"],Ei=["sourceIndex"],Pi=["item","source","sourceIndex"];function $n(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function R(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function Di(t){var e=t.props,n=t.refresh,r=t.store,o=ne(t,_i),i=function(a,u){return u!==void 0?"".concat(a,"-").concat(u):a};return{getEnvironmentProps:function(a){var u=a.inputElement,c=a.formElement,s=a.panelElement;function l(m){!r.getState().isOpen&&r.pendingRequests.isEmpty()||m.target===u||[c,s].some(function(p){return v=p,d=m.target,v===d||v.contains(d);var v,d})===!1&&(r.dispatch("blur",null),e.debug||r.pendingRequests.cancelAll())}return R({onTouchStart:l,onMouseDown:l,onTouchMove:function(m){r.getState().isOpen!==!1&&u===e.environment.document.activeElement&&m.target!==u&&u.blur()}},ne(a,Oi))},getRootProps:function(a){return R({role:"combobox","aria-expanded":r.getState().isOpen,"aria-haspopup":"listbox","aria-owns":r.getState().isOpen?"".concat(e.id,"-list"):void 0,"aria-labelledby":"".concat(e.id,"-label")},a)},getFormProps:function(a){return a.inputElement,R({action:"",noValidate:!0,role:"search",onSubmit:function(u){var c;u.preventDefault(),e.onSubmit(R({event:u,refresh:n,state:r.getState()},o)),r.dispatch("submit",null),(c=a.inputElement)===null||c===void 0||c.blur()},onReset:function(u){var c;u.preventDefault(),e.onReset(R({event:u,refresh:n,state:r.getState()},o)),r.dispatch("reset",null),(c=a.inputElement)===null||c===void 0||c.focus()}},ne(a,Si))},getLabelProps:function(a){var u=a||{},c=u.sourceIndex,s=ne(u,ji);return R({htmlFor:"".concat(i(e.id,c),"-input"),id:"".concat(i(e.id,c),"-label")},s)},getInputProps:function(a){var u;function c(y){(e.openOnFocus||r.getState().query)&&se(R({event:y,props:e,query:r.getState().completion||r.getState().query,refresh:n,store:r},o)),r.dispatch("focus",null)}var s=a||{},l=(s.inputElement,s.maxLength),m=l===void 0?512:l,p=ne(s,wi),v=fe(r.getState()),d=function(y){return!!(y&&y.match(ri))}(((u=e.environment.navigator)===null||u===void 0?void 0:u.userAgent)||""),h=v!=null&&v.itemUrl&&!d?"go":"search";return R({"aria-autocomplete":"both","aria-activedescendant":r.getState().isOpen&&r.getState().activeItemId!==null?"".concat(e.id,"-item-").concat(r.getState().activeItemId):void 0,"aria-controls":r.getState().isOpen?"".concat(e.id,"-list"):void 0,"aria-labelledby":"".concat(e.id,"-label"),value:r.getState().completion||r.getState().query,id:"".concat(e.id,"-input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:h,spellCheck:"false",autoFocus:e.autoFocus,placeholder:e.placeholder,maxLength:m,type:"search",onChange:function(y){se(R({event:y,props:e,query:y.currentTarget.value.slice(0,m),refresh:n,store:r},o))},onKeyDown:function(y){(function(b){var _=b.event,S=b.props,O=b.refresh,g=b.store,P=bi(b,yi);if(_.key==="ArrowUp"||_.key==="ArrowDown"){var C=function(){var M=S.environment.document.getElementById("".concat(S.id,"-item-").concat(g.getState().activeItemId));M&&(M.scrollIntoViewIfNeeded?M.scrollIntoViewIfNeeded(!1):M.scrollIntoView(!1))},L=function(){var M=fe(g.getState());if(g.getState().activeItemId!==null&&M){var Ot=M.item,St=M.itemInputValue,$e=M.itemUrl,B=M.source;B.onActive(te({event:_,item:Ot,itemInputValue:St,itemUrl:$e,refresh:O,source:B,state:g.getState()},P))}};_.preventDefault(),g.getState().isOpen===!1&&(S.openOnFocus||g.getState().query)?se(te({event:_,props:S,query:g.getState().query,refresh:O,store:g},P)).then(function(){g.dispatch(_.key,{nextActiveItemId:S.defaultActiveItemId}),L(),setTimeout(C,0)}):(g.dispatch(_.key,{}),L(),C())}else if(_.key==="Escape")_.preventDefault(),g.dispatch(_.key,null),g.pendingRequests.cancelAll();else if(_.key==="Tab")g.dispatch("blur",null),g.pendingRequests.cancelAll();else if(_.key==="Enter"){if(g.getState().activeItemId===null||g.getState().collections.every(function(M){return M.items.length===0}))return void(S.debug||g.pendingRequests.cancelAll());_.preventDefault();var x=fe(g.getState()),k=x.item,N=x.itemInputValue,U=x.itemUrl,F=x.source;if(_.metaKey||_.ctrlKey)U!==void 0&&(F.onSelect(te({event:_,item:k,itemInputValue:N,itemUrl:U,refresh:O,source:F,state:g.getState()},P)),S.navigator.navigateNewTab({itemUrl:U,item:k,state:g.getState()}));else if(_.shiftKey)U!==void 0&&(F.onSelect(te({event:_,item:k,itemInputValue:N,itemUrl:U,refresh:O,source:F,state:g.getState()},P)),S.navigator.navigateNewWindow({itemUrl:U,item:k,state:g.getState()}));else if(!_.altKey){if(U!==void 0)return F.onSelect(te({event:_,item:k,itemInputValue:N,itemUrl:U,refresh:O,source:F,state:g.getState()},P)),void S.navigator.navigate({itemUrl:U,item:k,state:g.getState()});se(te({event:_,nextState:{isOpen:!1},props:S,query:N,refresh:O,store:g},P)).then(function(){F.onSelect(te({event:_,item:k,itemInputValue:N,itemUrl:U,refresh:O,source:F,state:g.getState()},P))})}}})(R({event:y,props:e,refresh:n,store:r},o))},onFocus:c,onBlur:vt,onClick:function(y){a.inputElement!==e.environment.document.activeElement||r.getState().isOpen||c(y)}},p)},getPanelProps:function(a){return R({onMouseDown:function(u){u.preventDefault()},onMouseLeave:function(){r.dispatch("mouseleave",null)}},a)},getListProps:function(a){var u=a||{},c=u.sourceIndex,s=ne(u,Ei);return R({role:"listbox","aria-labelledby":"".concat(i(e.id,c),"-label"),id:"".concat(i(e.id,c),"-list")},s)},getItemProps:function(a){var u=a.item,c=a.source,s=a.sourceIndex,l=ne(a,Pi);return R({id:"".concat(i(e.id,s),"-item-").concat(u.__autocomplete_id),role:"option","aria-selected":r.getState().activeItemId===u.__autocomplete_id,onMouseMove:function(m){if(u.__autocomplete_id!==r.getState().activeItemId){r.dispatch("mousemove",u.__autocomplete_id);var p=fe(r.getState());if(r.getState().activeItemId!==null&&p){var v=p.item,d=p.itemInputValue,h=p.itemUrl,y=p.source;y.onActive(R({event:m,item:v,itemInputValue:d,itemUrl:h,refresh:n,source:y,state:r.getState()},o))}}},onMouseDown:function(m){m.preventDefault()},onClick:function(m){var p=c.getItemInputValue({item:u,state:r.getState()}),v=c.getItemUrl({item:u,state:r.getState()});(v?Promise.resolve():se(R({event:m,nextState:{isOpen:!1},props:e,query:p,refresh:n,store:r},o))).then(function(){c.onSelect(R({event:m,item:u,itemInputValue:p,itemUrl:v,refresh:n,source:c,state:r.getState()},o))})}},l)}}}function Me(t){return Me=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Me(t)}function Jn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function ki(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function Yi(t){var e=t.translations,n=e===void 0?{}:e,r=Zi(t,Ji),o=n.noResultsText,i=o===void 0?"No results for":o,a=n.suggestedQueryText,u=a===void 0?"Try searching for":a,c=n.reportMissingResultsText,s=c===void 0?"Believe this query should return results?":c,l=n.reportMissingResultsLinkText,m=l===void 0?"Let us know.":l,p=r.state.context.searchSuggestions;return f.createElement("div",{className:"DocSearch-NoResults"},f.createElement("div",{className:"DocSearch-Screen-Icon"},f.createElement(zi,null)),f.createElement("p",{className:"DocSearch-Title"},i,' "',f.createElement("strong",null,r.state.query),'"'),p&&p.length>0&&f.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},f.createElement("p",{className:"DocSearch-Help"},u,":"),f.createElement("ul",null,p.slice(0,3).reduce(function(v,d){return[].concat(Qi(v),[f.createElement("li",{key:d},f.createElement("button",{className:"DocSearch-Prefill",key:d,type:"button",onClick:function(){r.setQuery(d.toLowerCase()+" "),r.refresh(),r.inputRef.current.focus()}},d))])},[]))),r.getMissingResultsUrl&&f.createElement("p",{className:"DocSearch-Help"},"".concat(s," "),f.createElement("a",{href:r.getMissingResultsUrl({query:r.state.query}),target:"_blank",rel:"noopener noreferrer"},m)))}var Gi=["hit","attribute","tagName"];function Xn(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(o){return Object.getOwnPropertyDescriptor(t,o).enumerable})),n.push.apply(n,r)}return n}function er(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function tr(t,e){return e.split(".").reduce(function(n,r){return n!=null&&n[r]?n[r]:null},t)}function le(t){var e=t.hit,n=t.attribute,r=t.tagName;return V(r===void 0?"span":r,er(er({},ea(t,Gi)),{},{dangerouslySetInnerHTML:{__html:tr(e,"_snippetResult.".concat(n,".value"))||tr(e,n)}}))}function nr(t,e){return function(n){if(Array.isArray(n))return n}(t)||function(n,r){var o=n==null?null:typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(o!=null){var i,a,u=[],c=!0,s=!1;try{for(o=o.call(n);!(c=(i=o.next()).done)&&(u.push(i.value),!r||u.length!==r);c=!0);}catch(l){s=!0,a=l}finally{try{c||o.return==null||o.return()}finally{if(s)throw a}}return u}}(t,e)||function(n,r){if(n){if(typeof n=="string")return rr(n,r);var o=Object.prototype.toString.call(n).slice(8,-1);if(o==="Object"&&n.constructor&&(o=n.constructor.name),o==="Map"||o==="Set")return Array.from(n);if(o==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return rr(n,r)}}(t,e)||function(){throw new TypeError(`Invalid attempt to destructure non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}()}function rr(t,e){(e==null||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n|<\/mark>)/g,ra=RegExp(zr.source);function $r(t){var e,n,r,o,i,a=t;if(!a.__docsearch_parent&&!t._highlightResult)return t.hierarchy.lvl0;var u=((a.__docsearch_parent?(e=a.__docsearch_parent)===null||e===void 0||(n=e._highlightResult)===null||n===void 0||(r=n.hierarchy)===null||r===void 0?void 0:r.lvl0:(o=t._highlightResult)===null||o===void 0||(i=o.hierarchy)===null||i===void 0?void 0:i.lvl0)||{}).value;return u&&ra.test(u)?u.replace(zr,""):u}function $t(){return $t=Object.assign||function(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function ca(t){var e=t.translations,n=e===void 0?{}:e,r=aa(t,ia),o=n.recentSearchesTitle,i=o===void 0?"Recent":o,a=n.noRecentSearchesText,u=a===void 0?"No recent searches":a,c=n.saveRecentSearchButtonTitle,s=c===void 0?"Save this search":c,l=n.removeRecentSearchButtonTitle,m=l===void 0?"Remove this search from history":l,p=n.favoriteSearchesTitle,v=p===void 0?"Favorite":p,d=n.removeFavoriteSearchButtonTitle,h=d===void 0?"Remove this search from favorites":d;return r.state.status==="idle"&&r.hasCollections===!1?r.disableUserPersonalization?null:f.createElement("div",{className:"DocSearch-StartScreen"},f.createElement("p",{className:"DocSearch-Help"},u)):r.hasCollections===!1?null:f.createElement("div",{className:"DocSearch-Dropdown-Container"},f.createElement(zt,ht({},r,{title:i,collection:r.state.collections[0],renderIcon:function(){return f.createElement("div",{className:"DocSearch-Hit-icon"},f.createElement(Hi,null))},renderAction:function(y){var b=y.item,_=y.runFavoriteTransition,S=y.runDeleteTransition;return f.createElement(f.Fragment,null,f.createElement("div",{className:"DocSearch-Hit-action"},f.createElement("button",{className:"DocSearch-Hit-action-button",title:s,type:"submit",onClick:function(O){O.preventDefault(),O.stopPropagation(),_(function(){r.favoriteSearches.add(b),r.recentSearches.remove(b),r.refresh()})}},f.createElement(Gn,null))),f.createElement("div",{className:"DocSearch-Hit-action"},f.createElement("button",{className:"DocSearch-Hit-action-button",title:m,type:"submit",onClick:function(O){O.preventDefault(),O.stopPropagation(),S(function(){r.recentSearches.remove(b),r.refresh()})}},f.createElement(Kt,null))))}})),f.createElement(zt,ht({},r,{title:v,collection:r.state.collections[1],renderIcon:function(){return f.createElement("div",{className:"DocSearch-Hit-icon"},f.createElement(Gn,null))},renderAction:function(y){var b=y.item,_=y.runDeleteTransition;return f.createElement("div",{className:"DocSearch-Hit-action"},f.createElement("button",{className:"DocSearch-Hit-action-button",title:h,type:"submit",onClick:function(S){S.preventDefault(),S.stopPropagation(),_(function(){r.favoriteSearches.remove(b),r.refresh()})}},f.createElement(Kt,null)))}})))}var ua=["translations"];function yt(){return yt=Object.assign||function(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}var sa=f.memo(function(t){var e=t.translations,n=e===void 0?{}:e,r=la(t,ua);if(r.state.status==="error")return f.createElement($i,{translations:n==null?void 0:n.errorScreen});var o=r.state.collections.some(function(i){return i.items.length>0});return r.state.query?o===!1?f.createElement(Yi,yt({},r,{translations:n==null?void 0:n.noResultsScreen})):f.createElement(oa,r):f.createElement(ca,yt({},r,{hasCollections:o,translations:n==null?void 0:n.startScreen}))},function(t,e){return e.state.status==="loading"||e.state.status==="stalled"}),fa=["translations"];function gt(){return gt=Object.assign||function(t){for(var e=1;e=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function pa(t){var e=t.translations,n=e===void 0?{}:e,r=ma(t,fa),o=n.resetButtonTitle,i=o===void 0?"Clear the query":o,a=n.resetButtonAriaLabel,u=a===void 0?"Clear the query":a,c=n.cancelButtonText,s=c===void 0?"Cancel":c,l=n.cancelButtonAriaLabel,m=l===void 0?"Cancel":l,p=r.getFormProps({inputElement:r.inputRef.current}).onReset;return f.useEffect(function(){r.autoFocus&&r.inputRef.current&&r.inputRef.current.focus()},[r.autoFocus,r.inputRef]),f.useEffect(function(){r.isFromSelection&&r.inputRef.current&&r.inputRef.current.select()},[r.isFromSelection,r.inputRef]),f.createElement(f.Fragment,null,f.createElement("form",{className:"DocSearch-Form",onSubmit:function(v){v.preventDefault()},onReset:p},f.createElement("label",gt({className:"DocSearch-MagnifierLabel"},r.getLabelProps()),f.createElement(Hr,null)),f.createElement("div",{className:"DocSearch-LoadingIndicator"},f.createElement(Mi,null)),f.createElement("input",gt({className:"DocSearch-Input",ref:r.inputRef},r.getInputProps({inputElement:r.inputRef.current,autoFocus:r.autoFocus,maxLength:64}))),f.createElement("button",{type:"reset",title:i,className:"DocSearch-Reset","aria-label":u,hidden:!r.state.query},f.createElement(Kt,null))),f.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":m,onClick:r.onClose},s))}var va=["_highlightResult","_snippetResult"];function da(t,e){if(t==null)return{};var n,r,o=function(a,u){if(a==null)return{};var c,s,l={},m=Object.keys(a);for(s=0;s=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function ha(t){return function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch{return!1}}()===!1?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(e){return window.localStorage.setItem(t,JSON.stringify(e))},getItem:function(){var e=window.localStorage.getItem(t);return e?JSON.parse(e):[]}}}function ar(t){var e=t.key,n=t.limit,r=n===void 0?5:n,o=ha(e),i=o.getItem().slice(0,r);return{add:function(a){var u=a,c=(u._highlightResult,u._snippetResult,da(u,va)),s=i.findIndex(function(l){return l.objectID===c.objectID});s>-1&&i.splice(s,1),i.unshift(c),i=i.slice(0,r),o.setItem(i)},remove:function(a){i=i.filter(function(u){return u.objectID!==a.objectID}),o.setItem(i)},getAll:function(){return i}}}var ya=["facetName","facetQuery"];function ga(t){var e,n="algoliasearch-client-js-".concat(t.key),r=function(){return e===void 0&&(e=t.localStorage||window.localStorage),e},o=function(){return JSON.parse(r().getItem(n)||"{}")};return{get:function(i,a){var u=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then(function(){var c=JSON.stringify(i),s=o()[c];return Promise.all([s||a(),s!==void 0])}).then(function(c){var s=st(c,2),l=s[0],m=s[1];return Promise.all([l,m||u.miss(l)])}).then(function(c){return st(c,1)[0]})},set:function(i,a){return Promise.resolve().then(function(){var u=o();return u[JSON.stringify(i)]=a,r().setItem(n,JSON.stringify(u)),a})},delete:function(i){return Promise.resolve().then(function(){var a=o();delete a[JSON.stringify(i)],r().setItem(n,JSON.stringify(a))})},clear:function(){return Promise.resolve().then(function(){r().removeItem(n)})}}}function je(t){var e=ft(t.caches),n=e.shift();return n===void 0?{get:function(r,o){var i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return o().then(function(a){return Promise.all([a,i.miss(a)])}).then(function(a){return st(a,1)[0]})},set:function(r,o){return Promise.resolve(o)},delete:function(r){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(r,o){var i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}};return n.get(r,o,i).catch(function(){return je({caches:e}).get(r,o,i)})},set:function(r,o){return n.set(r,o).catch(function(){return je({caches:e}).set(r,o)})},delete:function(r){return n.delete(r).catch(function(){return je({caches:e}).delete(r)})},clear:function(){return n.clear().catch(function(){return je({caches:e}).clear()})}}}function Tt(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{serializable:!0},e={};return{get:function(n,r){var o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{miss:function(){return Promise.resolve()}},i=JSON.stringify(n);if(i in e)return Promise.resolve(t.serializable?JSON.parse(e[i]):e[i]);var a=r(),u=o&&o.miss||function(){return Promise.resolve()};return a.then(function(c){return u(c)}).then(function(){return a})},set:function(n,r){return e[JSON.stringify(n)]=t.serializable?JSON.stringify(r):r,Promise.resolve(r)},delete:function(n){return delete e[JSON.stringify(n)],Promise.resolve()},clear:function(){return e={},Promise.resolve()}}}function ba(t){for(var e=t.length-1;e>0;e--){var n=Math.floor(Math.random()*(e+1)),r=t[e];t[e]=t[n],t[n]=r}return t}function Jr(t,e){return e&&Object.keys(e).forEach(function(n){t[n]=e[n](t)}),t}function bt(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r0?r:void 0,timeout:n.timeout||e,headers:n.headers||{},queryParameters:n.queryParameters||{},cacheable:n.cacheable}}var me={Read:1,Write:2,Any:3},Qr=1,_a=2,Zr=3;function Yr(t){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Qr;return I(I({},t),{},{status:e,lastUpdate:Date.now()})}function Gr(t){return typeof t=="string"?{protocol:"https",url:t,accept:me.Any}:{protocol:t.protocol||"https",url:t.url,accept:t.accept||me.Any}}var ur="GET",_t="POST";function Oa(t,e){return Promise.all(e.map(function(n){return t.get(n,function(){return Promise.resolve(Yr(n))})})).then(function(n){var r=n.filter(function(a){return function(u){return u.status===Qr||Date.now()-u.lastUpdate>12e4}(a)}),o=n.filter(function(a){return function(u){return u.status===Zr&&Date.now()-u.lastUpdate<=12e4}(a)}),i=[].concat(ft(r),ft(o));return{getTimeout:function(a,u){return(o.length===0&&a===0?1:o.length+3+a)*u},statelessHosts:i.length>0?i.map(function(a){return Gr(a)}):e}})}function lr(t,e,n,r){var o=[],i=function(p,v){if(!(p.method===ur||p.data===void 0&&v.data===void 0)){var d=Array.isArray(p.data)?p.data:I(I({},p.data),v.data);return JSON.stringify(d)}}(n,r),a=function(p,v){var d=I(I({},p.headers),v.headers),h={};return Object.keys(d).forEach(function(y){var b=d[y];h[y.toLowerCase()]=b}),h}(t,r),u=n.method,c=n.method!==ur?{}:I(I({},n.data),r.data),s=I(I(I({"x-algolia-agent":t.userAgent.value},t.queryParameters),c),r.queryParameters),l=0,m=function p(v,d){var h=v.pop();if(h===void 0)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:sr(o)};var y={data:i,headers:a,method:u,url:wa(h,n.path,s),connectTimeout:d(l,t.timeouts.connect),responseTimeout:d(l,r.timeout)},b=function(S){var O={request:y,response:S,host:h,triesLeft:v.length};return o.push(O),O},_={onSucess:function(S){return function(O){try{return JSON.parse(O.content)}catch(g){throw function(P,C){return{name:"DeserializationError",message:P,response:C}}(g.message,O)}}(S)},onRetry:function(S){var O=b(S);return S.isTimedOut&&l++,Promise.all([t.logger.info("Retryable failure",eo(O)),t.hostsCache.set(h,Yr(h,S.isTimedOut?Zr:_a))]).then(function(){return p(v,d)})},onFail:function(S){throw b(S),function(O,g){var P=O.content,C=O.status,L=P;try{L=JSON.parse(P).message}catch{}return function(x,k,N){return{name:"ApiError",message:x,status:k,transporterStackTrace:N}}(L,C,g)}(S,sr(o))}};return t.requester.send(y).then(function(S){return function(O,g){return function(P){var C=P.status;return P.isTimedOut||function(L){var x=L.isTimedOut,k=L.status;return!x&&~~k==0}(P)||~~(C/100)!=2&&~~(C/100)!=4}(O)?g.onRetry(O):~~(O.status/100)==2?g.onSucess(O):g.onFail(O)}(S,_)})};return Oa(t.hostsCache,e).then(function(p){return m(ft(p.statelessHosts).reverse(),p.getTimeout)})}function Sa(t){var e={value:"Algolia for JavaScript (".concat(t,")"),add:function(n){var r="; ".concat(n.segment).concat(n.version!==void 0?" (".concat(n.version,")"):"");return e.value.indexOf(r)===-1&&(e.value="".concat(e.value).concat(r)),e}};return e}function wa(t,e,n){var r=Xr(n),o="".concat(t.protocol,"://").concat(t.url,"/").concat(e.charAt(0)==="/"?e.substr(1):e);return r.length&&(o+="?".concat(r)),o}function Xr(t){return Object.keys(t).map(function(e){return bt("%s=%s",e,(n=t[e],Object.prototype.toString.call(n)==="[object Object]"||Object.prototype.toString.call(n)==="[object Array]"?JSON.stringify(t[e]):t[e]));var n}).join("&")}function sr(t){return t.map(function(e){return eo(e)})}function eo(t){var e=t.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return I(I({},t),{},{request:I(I({},t.request),{},{headers:I(I({},t.request.headers),e)})})}var ja=function(t){var e=t.appId,n=function(i,a,u){var c={"x-algolia-api-key":u,"x-algolia-application-id":a};return{headers:function(){return i===lt.WithinHeaders?c:{}},queryParameters:function(){return i===lt.WithinQueryParameters?c:{}}}}(t.authMode!==void 0?t.authMode:lt.WithinHeaders,e,t.apiKey),r=function(i){var a=i.hostsCache,u=i.logger,c=i.requester,s=i.requestsCache,l=i.responsesCache,m=i.timeouts,p=i.userAgent,v=i.hosts,d=i.queryParameters,h={hostsCache:a,logger:u,requester:c,requestsCache:s,responsesCache:l,timeouts:m,userAgent:p,headers:i.headers,queryParameters:d,hosts:v.map(function(y){return Gr(y)}),read:function(y,b){var _=cr(b,h.timeouts.read),S=function(){return lr(h,h.hosts.filter(function(g){return(g.accept&me.Read)!=0}),y,_)};if((_.cacheable!==void 0?_.cacheable:y.cacheable)!==!0)return S();var O={request:y,mappedRequestOptions:_,transporter:{queryParameters:h.queryParameters,headers:h.headers}};return h.responsesCache.get(O,function(){return h.requestsCache.get(O,function(){return h.requestsCache.set(O,S()).then(function(g){return Promise.all([h.requestsCache.delete(O),g])},function(g){return Promise.all([h.requestsCache.delete(O),Promise.reject(g)])}).then(function(g){var P=st(g,2);return P[0],P[1]})})},{miss:function(g){return h.responsesCache.set(O,g)}})},write:function(y,b){return lr(h,h.hosts.filter(function(_){return(_.accept&me.Write)!=0}),y,cr(b,h.timeouts.write))}};return h}(I(I({hosts:[{url:"".concat(e,"-dsn.algolia.net"),accept:me.Read},{url:"".concat(e,".algolia.net"),accept:me.Write}].concat(ba([{url:"".concat(e,"-1.algolianet.com")},{url:"".concat(e,"-2.algolianet.com")},{url:"".concat(e,"-3.algolianet.com")}]))},t),{},{headers:I(I(I({},n.headers()),{"content-type":"application/x-www-form-urlencoded"}),t.headers),queryParameters:I(I({},n.queryParameters()),t.queryParameters)})),o={transporter:r,appId:e,addAlgoliaAgent:function(i,a){r.userAgent.add({segment:i,version:a})},clearCache:function(){return Promise.all([r.requestsCache.clear(),r.responsesCache.clear()]).then(function(){})}};return Jr(o,t.methods)},to=function(t){return function(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r={transporter:t.transporter,appId:t.appId,indexName:e};return Jr(r,n.methods)}},fr=function(t){return function(e,n){var r=e.map(function(o){return I(I({},o),{},{params:Xr(o.params||{})})});return t.transporter.read({method:_t,path:"1/indexes/*/queries",data:{requests:r},cacheable:!0},n)}},mr=function(t){return function(e,n){return Promise.all(e.map(function(r){var o=r.params,i=o.facetName,a=o.facetQuery,u=Oo(o,ya);return to(t)(r.indexName,{methods:{searchForFacetValues:no}}).searchForFacetValues(i,a,I(I({},n),u))}))}},Ea=function(t){return function(e,n,r){return t.transporter.read({method:_t,path:bt("1/answers/%s/prediction",t.indexName),data:{query:e,queryLanguages:n},cacheable:!0},r)}},Pa=function(t){return function(e,n){return t.transporter.read({method:_t,path:bt("1/indexes/%s/query",t.indexName),data:{query:e},cacheable:!0},n)}},no=function(t){return function(e,n,r){return t.transporter.read({method:_t,path:bt("1/indexes/%s/facets/%s/query",t.indexName,e),data:{facetQuery:n},cacheable:!0},r)}},Ia=1,Da=2,ka=3;function ro(t,e,n){var r,o={appId:t,apiKey:e,timeouts:{connect:1,read:2,write:30},requester:{send:function(i){return new Promise(function(a){var u=new XMLHttpRequest;u.open(i.method,i.url,!0),Object.keys(i.headers).forEach(function(m){return u.setRequestHeader(m,i.headers[m])});var c,s=function(m,p){return setTimeout(function(){u.abort(),a({status:0,content:p,isTimedOut:!0})},1e3*m)},l=s(i.connectTimeout,"Connection timeout");u.onreadystatechange=function(){u.readyState>u.OPENED&&c===void 0&&(clearTimeout(l),c=s(i.responseTimeout,"Socket timeout"))},u.onerror=function(){u.status===0&&(clearTimeout(l),clearTimeout(c),a({content:u.responseText||"Network request failed",status:u.status,isTimedOut:!1}))},u.onload=function(){clearTimeout(l),clearTimeout(c),a({content:u.responseText,status:u.status,isTimedOut:!1})},u.send(i.data)})}},logger:(r=ka,{debug:function(i,a){return Ia>=r&&console.debug(i,a),Promise.resolve()},info:function(i,a){return Da>=r&&console.info(i,a),Promise.resolve()},error:function(i,a){return console.error(i,a),Promise.resolve()}}),responsesCache:Tt(),requestsCache:Tt({serializable:!1}),hostsCache:je({caches:[ga({key:"".concat("4.8.5","-").concat(t)}),Tt()]}),userAgent:Sa("4.8.5").add({segment:"Browser",version:"lite"}),authMode:lt.WithinQueryParameters};return ja(I(I(I({},o),n),{},{methods:{search:fr,searchForFacetValues:mr,multipleQueries:fr,multipleSearchForFacetValues:mr,initIndex:function(i){return function(a){return to(i)(a,{methods:{search:Pa,searchForFacetValues:no,findAnswers:Ea}})}}}}))}ro.version="4.8.5";var Aa=["footer","searchBox"];function Fe(){return Fe=Object.assign||function(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n=0||(l[c]=a[c]);return l}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(t,n)&&(o[n]=t[n])}return o}function Ta(t){var e=t.appId,n=t.apiKey,r=t.indexName,o=t.placeholder,i=o===void 0?"Search docs":o,a=t.searchParameters,u=t.maxResultsPerGroup,c=t.onClose,s=c===void 0?na:c,l=t.transformItems,m=l===void 0?ir:l,p=t.hitComponent,v=p===void 0?Li:p,d=t.resultsFooterComponent,h=d===void 0?function(){return null}:d,y=t.navigator,b=t.initialScrollY,_=b===void 0?0:b,S=t.transformSearchClient,O=S===void 0?ir:S,g=t.disableUserPersonalization,P=g!==void 0&&g,C=t.initialQuery,L=C===void 0?"":C,x=t.translations,k=x===void 0?{}:x,N=t.getMissingResultsUrl,U=t.insights,F=U!==void 0&&U,M=k.footer,Ot=k.searchBox,St=Na(k,Aa),$e=xa(f.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),B=$e[0],oo=$e[1],Gt=f.useRef(null),wt=f.useRef(null),Xt=f.useRef(null),Je=f.useRef(null),he=f.useRef(null),Q=f.useRef(10),en=f.useRef(typeof window<"u"?window.getSelection().toString().slice(0,64):"").current,ee=f.useRef(L||en).current,tn=function(j,D,T){return f.useMemo(function(){var H=ro(j,D);return H.addAlgoliaAgent("docsearch","3.5.1"),/docsearch.js \(.*\)/.test(H.transporter.userAgent.value)===!1&&H.addAlgoliaAgent("docsearch-react","3.5.1"),T(H)},[j,D,T])}(e,n,O),oe=f.useRef(ar({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(r),limit:10})).current,ye=f.useRef(ar({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(r),limit:oe.getAll().length===0?7:4})).current,ge=f.useCallback(function(j){if(!P){var D=j.type==="content"?j.__docsearch_parent:j;D&&oe.getAll().findIndex(function(T){return T.objectID===D.objectID})===-1&&ye.add(D)}},[oe,ye,P]),io=f.useCallback(function(j){if(B.context.algoliaInsightsPlugin&&j.__autocomplete_id){var D=j,T={eventName:"Item Selected",index:D.__autocomplete_indexName,items:[D],positions:[j.__autocomplete_id],queryID:D.__autocomplete_queryID};B.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(T)}},[B.context.algoliaInsightsPlugin]),be=f.useMemo(function(){return Ti({id:"docsearch",defaultActiveItemId:0,placeholder:i,openOnFocus:!0,initialState:{query:ee,context:{searchSuggestions:[]}},insights:F,navigator:y,onStateChange:function(j){oo(j.state)},getSources:function(j){var D=j.query,T=j.state,H=j.setContext,Z=j.setStatus;if(!D)return P?[]:[{sourceId:"recentSearches",onSelect:function(A){var K=A.item,ie=A.event;ge(K),it(ie)||s()},getItemUrl:function(A){return A.item.url},getItems:function(){return ye.getAll()}},{sourceId:"favoriteSearches",onSelect:function(A){var K=A.item,ie=A.event;ge(K),it(ie)||s()},getItemUrl:function(A){return A.item.url},getItems:function(){return oe.getAll()}}];var Y=!!F;return tn.search([{query:D,indexName:r,params:Rt({attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(Q.current),"hierarchy.lvl2:".concat(Q.current),"hierarchy.lvl3:".concat(Q.current),"hierarchy.lvl4:".concat(Q.current),"hierarchy.lvl5:".concat(Q.current),"hierarchy.lvl6:".concat(Q.current),"content:".concat(Q.current)],snippetEllipsisText:"…",highlightPreTag:"",highlightPostTag:"",hitsPerPage:20,clickAnalytics:Y},a)}]).catch(function(A){throw A.name==="RetryError"&&Z("error"),A}).then(function(A){var K=A.results,ie=K[0],uo=ie.hits,lo=ie.nbHits,jt=or(uo,function(Et){return $r(Et)},u);T.context.searchSuggestions.length0&&(nn(),he.current&&he.current.focus())},[ee,nn]),f.useEffect(function(){function j(){if(wt.current){var D=.01*window.innerHeight;wt.current.style.setProperty("--docsearch-vh","".concat(D,"px"))}}return j(),window.addEventListener("resize",j),function(){window.removeEventListener("resize",j)}},[]),f.createElement("div",Fe({ref:Gt},co({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container",B.status==="stalled"&&"DocSearch-Container--Stalled",B.status==="error"&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(j){j.target===j.currentTarget&&s()}}),f.createElement("div",{className:"DocSearch-Modal",ref:wt},f.createElement("header",{className:"DocSearch-SearchBar",ref:Xt},f.createElement(pa,Fe({},be,{state:B,autoFocus:ee.length===0,inputRef:he,isFromSelection:!!ee&&ee===en,translations:Ot,onClose:s}))),f.createElement("div",{className:"DocSearch-Dropdown",ref:Je},f.createElement(sa,Fe({},be,{indexName:r,state:B,hitComponent:v,resultsFooterComponent:h,disableUserPersonalization:P,recentSearches:ye,favoriteSearches:oe,inputRef:he,translations:St,getMissingResultsUrl:N,onItemClick:function(j,D){io(j),ge(j),it(D)||s()}}))),f.createElement("footer",{className:"DocSearch-Footer"},f.createElement(qi,{translations:M}))))}function Jt(){return Jt=Object.assign||function(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=new Array(e);n1&&arguments[1]!==void 0?arguments[1]:window;return typeof e=="string"?n.document.querySelector(e):e}(t.container,t.environment))}const La={id:"docsearch"},Ua=fo({__name:"VPAlgoliaSearchBox",props:{algolia:{}},setup(t){const e=t,n=mo(),r=po(),{site:o,localeIndex:i,lang:a}=bo();vo(u),ho(i,u);function u(){var v,d;const l={...e.algolia,...(v=e.algolia.locales)==null?void 0:v[i.value]},m=((d=l.searchParameters)==null?void 0:d.facetFilters)??[],p=[...(Array.isArray(m)?m:[m]).filter(h=>!h.startsWith("lang:")),`lang:${a.value}`];c({...l,searchParameters:{...l.searchParameters,facetFilters:p}})}function c(l){const m=Object.assign({},l,{container:"#docsearch",navigator:{navigate({itemUrl:p}){const{pathname:v}=new URL(window.location.origin+p);r.path===v?window.location.assign(window.location.origin+p):n.go(p)}},transformItems(p){return p.map(v=>Object.assign({},v,{url:s(v.url)}))},hitComponent({hit:p,children:v}){return{__v:null,type:"a",ref:void 0,constructor:void 0,key:void 0,props:{href:p.url,children:v}}}});qa(m)}function s(l){const{pathname:m,hash:p}=new URL(l);return m.replace(/\.html$/,o.value.cleanUrls?"":".html")+p}return(l,m)=>(yo(),go("div",La))}});export{Ua as default}; diff --git a/assets/chunks/framework.70afa331.js b/assets/chunks/framework.70afa331.js deleted file mode 100644 index 190930c47a..0000000000 --- a/assets/chunks/framework.70afa331.js +++ /dev/null @@ -1,2 +0,0 @@ -function mn(t,e){const n=Object.create(null),o=t.split(",");for(let r=0;r!!n[r.toLowerCase()]:r=>!!n[r]}const Z={},ae=[],Xt=()=>{},$s=()=>!1,Ms=/^on[^a-z]/,Ue=t=>Ms.test(t),Qn=t=>t.startsWith("onUpdate:"),et=Object.assign,Zn=(t,e)=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)},Is=Object.prototype.hasOwnProperty,G=(t,e)=>Is.call(t,e),U=Array.isArray,ue=t=>gn(t)==="[object Map]",_r=t=>gn(t)==="[object Set]",D=t=>typeof t=="function",st=t=>typeof t=="string",to=t=>typeof t=="symbol",Q=t=>t!==null&&typeof t=="object",br=t=>Q(t)&&D(t.then)&&D(t.catch),Cr=Object.prototype.toString,gn=t=>Cr.call(t),wr=t=>gn(t)==="[object Object]",eo=t=>st(t)&&t!=="NaN"&&t[0]!=="-"&&""+parseInt(t,10)===t,Se=mn(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),vn=t=>{const e=Object.create(null);return n=>e[n]||(e[n]=t(n))},Ns=/-(\w)/g,Mt=vn(t=>t.replace(Ns,(e,n)=>n?n.toUpperCase():"")),Us=/\B([A-Z])/g,ie=vn(t=>t.replace(Us,"-$1").toLowerCase()),yn=vn(t=>t.charAt(0).toUpperCase()+t.slice(1)),Ze=vn(t=>t?`on${yn(t)}`:""),Fe=(t,e)=>!Object.is(t,e),Fn=(t,e)=>{for(let n=0;n{Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:n})},js=t=>{const e=parseFloat(t);return isNaN(e)?t:e},Vs=t=>{const e=st(t)?Number(t):NaN;return isNaN(e)?t:e};let Eo;const Bs=mn("Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console");function no(t){if(U(t)){const e={};for(let n=0;n{if(n){const o=n.split(Ds);o.length>1&&(e[o[0].trim()]=o[1].trim())}}),e}function oo(t){let e="";if(st(t))e=t;else if(U(t))for(let n=0;nst(t)?t:t==null?"":U(t)||Q(t)&&(t.toString===Cr||!D(t.toString))?JSON.stringify(t,xr,2):String(t),xr=(t,e)=>e&&e.__v_isRef?xr(t,e.value):ue(e)?{[`Map(${e.size})`]:[...e.entries()].reduce((n,[o,r])=>(n[`${o} =>`]=r,n),{})}:_r(e)?{[`Set(${e.size})`]:[...e.values()]}:!Q(e)||U(e)||wr(e)?e:String(e);let yt;class Ks{constructor(e=!1){this.detached=e,this._active=!0,this.effects=[],this.cleanups=[],this.parent=yt,!e&&yt&&(this.index=(yt.scopes||(yt.scopes=[])).push(this)-1)}get active(){return this._active}run(e){if(this._active){const n=yt;try{return yt=this,e()}finally{yt=n}}}on(){yt=this}off(){yt=this.parent}stop(e){if(this._active){let n,o;for(n=0,o=this.effects.length;n{const e=new Set(t);return e.w=0,e.n=0,e},Sr=t=>(t.w&Gt)>0,Er=t=>(t.n&Gt)>0,Bn=new WeakMap;let xe=0,Gt=1,Rt;const se=Symbol(""),Hn=Symbol("");class so{constructor(e,n=null,o){this.fn=e,this.scheduler=n,this.active=!0,this.deps=[],this.parent=void 0,Gs(this,o)}run(){if(!this.active)return this.fn();let e=Rt,n=Jt;for(;e;){if(e===this)return;e=e.parent}try{return this.parent=Rt,Rt=this,Jt=!0,Gt=1<<++xe,xe<=30?(({deps:o})=>{if(o.length)for(let r=0;r{const{deps:r}=o;if(r.length){let s=0;for(let l=0;l{(f==="length"||f>=c)&&i.push(a)})}else switch(n!==void 0&&i.push(l.get(n)),e){case"add":U(t)?eo(n)&&i.push(l.get("length")):(i.push(l.get(se)),ue(t)&&i.push(l.get(Hn)));break;case"delete":U(t)||(i.push(l.get(se)),ue(t)&&i.push(l.get(Hn)));break;case"set":ue(t)&&i.push(l.get(se))}if(i.length===1)i[0]&&Dn(i[0]);else{const c=[];for(const a of i)a&&c.push(...a);Dn(ro(c))}}function Dn(t,e){const n=U(t)?t:[...t];for(const o of n)o.computed&&To(o);for(const o of n)o.computed||To(o)}function To(t,e){(t!==Rt||t.allowRecurse)&&(t.scheduler?t.scheduler():t.run())}const Js=mn("__proto__,__v_isRef,__isVue"),Tr=new Set(Object.getOwnPropertyNames(Symbol).filter(t=>t!=="arguments"&&t!=="caller").map(t=>Symbol[t]).filter(to)),Ys=_n(),Qs=_n(!1,!0),Zs=_n(!0),tl=_n(!0,!0),Ro=el();function el(){const t={};return["includes","indexOf","lastIndexOf"].forEach(e=>{t[e]=function(...n){const o=X(this);for(let s=0,l=this.length;s{t[e]=function(...n){he();const o=X(this)[e].apply(this,n);return me(),o}}),t}function nl(t){const e=X(this);return gt(e,0,t),e.hasOwnProperty(t)}function _n(t=!1,e=!1){return function(n,o,r){if(o==="__v_isReactive")return!t;if(o==="__v_isReadonly")return t;if(o==="__v_isShallow")return e;if(o==="__v_raw"&&r===(t?e?dl:$r:e?Pr:Or).get(n))return n;const s=U(n);if(!t){if(s&&G(Ro,o))return Reflect.get(Ro,o,r);if(o==="hasOwnProperty")return nl}const l=Reflect.get(n,o,r);return(to(o)?Tr.has(o):Js(o))?l:(t||gt(n,0,o),e?l:at(l)?s&&eo(o)?l:l.value:Q(l)?t?Mr(l):Cn(l):l)}}function Rr(t=!1){return function(e,n,o,r){let s=e[n];if(ge(s)&&at(s)&&!at(o))return!1;if(!t&&(rn(o)||ge(o)||(s=X(s),o=X(o)),!U(e)&&at(s)&&!at(o)))return s.value=o,!0;const l=U(e)&&eo(n)?Number(n)!0,deleteProperty:(t,e)=>!0},ol=et({},Lr,{get:Qs,set:Rr(!0)});et({},Fr,{get:tl});const lo=t=>t,bn=t=>Reflect.getPrototypeOf(t);function We(t,e,n=!1,o=!1){const r=X(t=t.__v_raw),s=X(e);n||(e!==s&>(r,0,e),gt(r,0,s));const{has:l}=bn(r),i=o?lo:n?ao:Oe;return l.call(r,e)?i(t.get(e)):l.call(r,s)?i(t.get(s)):void(t!==r&&t.get(e))}function qe(t,e=!1){const n=this.__v_raw,o=X(n),r=X(t);return e||(t!==r&>(o,0,t),gt(o,0,r)),t===r?n.has(t):n.has(t)||n.has(r)}function ze(t,e=!1){return t=t.__v_raw,!e&>(X(t),0,se),Reflect.get(t,"size",t)}function Lo(t){t=X(t);const e=X(this);return bn(e).has.call(e,t)||(e.add(t),jt(e,"add",t,t)),this}function Fo(t,e){e=X(e);const n=X(this),{has:o,get:r}=bn(n);let s=o.call(n,t);s||(t=X(t),s=o.call(n,t));const l=r.call(n,t);return n.set(t,e),s?Fe(e,l)&&jt(n,"set",t,e):jt(n,"add",t,e),this}function Oo(t){const e=X(this),{has:n,get:o}=bn(e);let r=n.call(e,t);r||(t=X(t),r=n.call(e,t)),o&&o.call(e,t);const s=e.delete(t);return r&&jt(e,"delete",t,void 0),s}function Po(){const t=X(this),e=t.size!==0,n=t.clear();return e&&jt(t,"clear",void 0,void 0),n}function Ke(t,e){return function(n,o){const r=this,s=r.__v_raw,l=X(s),i=e?lo:t?ao:Oe;return!t&>(l,0,se),s.forEach((c,a)=>n.call(o,i(c),i(a),r))}}function Ge(t,e,n){return function(...o){const r=this.__v_raw,s=X(r),l=ue(s),i=t==="entries"||t===Symbol.iterator&&l,c=t==="keys"&&l,a=r[t](...o),f=n?lo:e?ao:Oe;return!e&>(s,0,c?Hn:se),{next(){const{value:p,done:g}=a.next();return g?{value:p,done:g}:{value:i?[f(p[0]),f(p[1])]:f(p),done:g}},[Symbol.iterator](){return this}}}}function Dt(t){return function(...e){return t!=="delete"&&this}}function rl(){const t={get(r){return We(this,r)},get size(){return ze(this)},has:qe,add:Lo,set:Fo,delete:Oo,clear:Po,forEach:Ke(!1,!1)},e={get(r){return We(this,r,!1,!0)},get size(){return ze(this)},has:qe,add:Lo,set:Fo,delete:Oo,clear:Po,forEach:Ke(!1,!0)},n={get(r){return We(this,r,!0)},get size(){return ze(this,!0)},has(r){return qe.call(this,r,!0)},add:Dt("add"),set:Dt("set"),delete:Dt("delete"),clear:Dt("clear"),forEach:Ke(!0,!1)},o={get(r){return We(this,r,!0,!0)},get size(){return ze(this,!0)},has(r){return qe.call(this,r,!0)},add:Dt("add"),set:Dt("set"),delete:Dt("delete"),clear:Dt("clear"),forEach:Ke(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(r=>{t[r]=Ge(r,!1,!1),n[r]=Ge(r,!0,!1),e[r]=Ge(r,!1,!0),o[r]=Ge(r,!0,!0)}),[t,n,e,o]}const[sl,ll,il,cl]=rl();function io(t,e){const n=e?t?cl:il:t?ll:sl;return(o,r,s)=>r==="__v_isReactive"?!t:r==="__v_isReadonly"?t:r==="__v_raw"?o:Reflect.get(G(n,r)&&r in o?n:o,r,s)}const al={get:io(!1,!1)},ul={get:io(!1,!0)},fl={get:io(!0,!1)},Or=new WeakMap,Pr=new WeakMap,$r=new WeakMap,dl=new WeakMap;function pl(t){return t.__v_skip||!Object.isExtensible(t)?0:function(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}((e=>gn(e).slice(8,-1))(t))}function Cn(t){return ge(t)?t:co(t,!1,Lr,al,Or)}function hl(t){return co(t,!1,ol,ul,Pr)}function Mr(t){return co(t,!0,Fr,fl,$r)}function co(t,e,n,o,r){if(!Q(t)||t.__v_raw&&(!e||!t.__v_isReactive))return t;const s=r.get(t);if(s)return s;const l=pl(t);if(l===0)return t;const i=new Proxy(t,l===2?o:n);return r.set(t,i),i}function fe(t){return ge(t)?fe(t.__v_raw):!(!t||!t.__v_isReactive)}function ge(t){return!(!t||!t.__v_isReadonly)}function rn(t){return!(!t||!t.__v_isShallow)}function Ir(t){return fe(t)||ge(t)}function X(t){const e=t&&t.__v_raw;return e?X(e):t}function Ee(t){return tn(t,"__v_skip",!0),t}const Oe=t=>Q(t)?Cn(t):t,ao=t=>Q(t)?Mr(t):t;function Nr(t){Jt&&Rt&&Ar((t=X(t)).dep||(t.dep=ro()))}function Ur(t,e){const n=(t=X(t)).dep;n&&Dn(n)}function at(t){return!(!t||t.__v_isRef!==!0)}function ke(t){return jr(t,!1)}function ml(t){return jr(t,!0)}function jr(t,e){return at(t)?t:new gl(t,e)}class gl{constructor(e,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?e:X(e),this._value=n?e:Oe(e)}get value(){return Nr(this),this._value}set value(e){const n=this.__v_isShallow||rn(e)||ge(e);e=n?e:X(e),Fe(e,this._rawValue)&&(this._rawValue=e,this._value=n?e:Oe(e),Ur(this))}}function vl(t){return at(t)?t.value:t}const yl={get:(t,e,n)=>vl(Reflect.get(t,e,n)),set:(t,e,n,o)=>{const r=t[e];return at(r)&&!at(n)?(r.value=n,!0):Reflect.set(t,e,n,o)}};function Vr(t){return fe(t)?t:new Proxy(t,yl)}class _l{constructor(e,n,o,r){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new so(e,()=>{this._dirty||(this._dirty=!0,Ur(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!r,this.__v_isReadonly=o}get value(){const e=X(this);return Nr(e),!e._dirty&&e._cacheable||(e._dirty=!1,e._value=e.effect.run()),e._value}set value(e){this._setter(e)}}function Yt(t,e,n,o){let r;try{r=o?t(...o):t()}catch(s){je(s,e,n)}return r}function Ft(t,e,n,o){if(D(t)){const s=Yt(t,e,n,o);return s&&br(s)&&s.catch(l=>{je(l,e,n)}),s}const r=[];for(let s=0;s>>1;$e(ct[r])$e(n)-$e(o)),ee=0;eet.id==null?1/0:t.id,Cl=(t,e)=>{const n=$e(t)-$e(e);if(n===0){if(t.pre&&!e.pre)return-1;if(e.pre&&!t.pre)return 1}return n};function Wr(t){Wn=!1,Pe=!0,ct.sort(Cl);try{for($t=0;$tst(E)?E.trim():E)),p&&(r=n.map(js))}let i,c=o[i=Ze(e)]||o[i=Ze(Mt(e))];!c&&s&&(c=o[i=Ze(ie(e))]),c&&Ft(c,t,6,r);const a=o[i+"Once"];if(a){if(t.emitted){if(t.emitted[i])return}else t.emitted={};t.emitted[i]=!0,Ft(a,t,6,r)}}function qr(t,e,n=!1){const o=e.emitsCache,r=o.get(t);if(r!==void 0)return r;const s=t.emits;let l={},i=!1;if(!D(t)){const c=a=>{const f=qr(a,e,!0);f&&(i=!0,et(l,f))};!n&&e.mixins.length&&e.mixins.forEach(c),t.extends&&c(t.extends),t.mixins&&t.mixins.forEach(c)}return s||i?(U(s)?s.forEach(c=>l[c]=null):et(l,s),Q(t)&&o.set(t,l),l):(Q(t)&&o.set(t,null),null)}function ln(t,e){return!(!t||!Ue(e))&&(e=e.slice(2).replace(/Once$/,""),G(t,e[0].toLowerCase()+e.slice(1))||G(t,ie(e))||G(t,e))}let ut=null,xn=null;function cn(t){const e=ut;return ut=t,xn=t&&t.type.__scopeId||null,e}function Di(t){xn=t}function Wi(){xn=null}function xl(t,e=ut,n){if(!e||t._n)return t;const o=(...r)=>{o._d&&Xo(-1);const s=cn(e);let l;try{l=t(...r)}finally{cn(s),o._d&&Xo(1)}return l};return o._n=!0,o._c=!0,o._d=!0,o}function On(t){const{type:e,vnode:n,proxy:o,withProxy:r,props:s,propsOptions:[l],slots:i,attrs:c,emit:a,render:f,renderCache:p,data:g,setupState:E,ctx:L,inheritAttrs:$}=t;let m,C;const N=cn(t);try{if(4&n.shapeFlag){const B=r||o;m=Tt(f.call(B,B,p,s,E,g,L)),C=c}else{const B=e;m=Tt(B(s,B.length>1?{attrs:c,slots:i,emit:a}:null)),C=e.props?c:Sl(c)}}catch(B){Le.length=0,je(B,t,1),m=ot(_t)}let q=m;if(C&&$!==!1){const B=Object.keys(C),{shapeFlag:K}=q;B.length&&7&K&&(l&&B.some(Qn)&&(C=El(C,l)),q=Qt(q,C))}return n.dirs&&(q=Qt(q),q.dirs=q.dirs?q.dirs.concat(n.dirs):n.dirs),n.transition&&(q.transition=n.transition),m=q,cn(N),m}const Sl=t=>{let e;for(const n in t)(n==="class"||n==="style"||Ue(n))&&((e||(e={}))[n]=t[n]);return e},El=(t,e)=>{const n={};for(const o in t)Qn(o)&&o.slice(9)in e||(n[o]=t[o]);return n};function Mo(t,e,n){const o=Object.keys(e);if(o.length!==Object.keys(t).length)return!0;for(let r=0;rt.__isSuspense;function zr(t,e){e&&e.pendingBranch?U(t)?e.effects.push(...t):e.effects.push(t):bl(t)}function Tl(t,e){return Sn(t,null,e)}function qi(t,e){return Sn(t,null,{flush:"post"})}const Xe={};function en(t,e,n){return Sn(t,e,n)}function Sn(t,e,{immediate:n,deep:o,flush:r}=Z){var s;const l=Xs()===((s=it)==null?void 0:s.scope)?it:null;let i,c,a=!1,f=!1;if(at(t)?(i=()=>t.value,a=rn(t)):fe(t)?(i=()=>t,o=!0):U(t)?(f=!0,a=t.some(m=>fe(m)||rn(m)),i=()=>t.map(m=>at(m)?m.value:fe(m)?ce(m):D(m)?Yt(m,l,2):void 0)):i=D(t)?e?()=>Yt(t,l,2):()=>{if(!l||!l.isUnmounted)return c&&c(),Ft(t,l,3,[p])}:Xt,e&&o){const m=i;i=()=>ce(m())}let p=m=>{c=$.onStop=()=>{Yt(m,l,4)}},g=f?new Array(t.length).fill(Xe):Xe;const E=()=>{if($.active)if(e){const m=$.run();(o||a||(f?m.some((C,N)=>Fe(C,g[N])):Fe(m,g)))&&(c&&c(),Ft(e,l,3,[m,g===Xe?void 0:f&&g[0]===Xe?[]:g,p]),g=m)}else $.run()};let L;E.allowRecurse=!!e,r==="sync"?L=E:r==="post"?L=()=>mt(E,l&&l.suspense):(E.pre=!0,l&&(E.id=l.uid),L=()=>wn(E));const $=new so(i,L);return e?n?E():g=$.run():r==="post"?mt($.run.bind($),l&&l.suspense):$.run(),()=>{$.stop(),l&&l.scope&&Zn(l.scope.effects,$)}}function Rl(t,e,n){const o=this.proxy,r=st(t)?t.includes(".")?Kr(o,t):()=>o[t]:t.bind(o,o);let s;D(e)?s=e:(s=e.handler,n=e);const l=it;ye(this);const i=Sn(r,s.bind(o),n);return l?ye(l):le(),i}function Kr(t,e){const n=e.split(".");return()=>{let o=t;for(let r=0;r{ce(n,e)});else if(wr(t))for(const n in t)ce(t[n],e);return t}function Pt(t,e,n,o){const r=t.dirs,s=e&&e.dirs;for(let l=0;l{t.isMounted=!0}),Zr(()=>{t.isUnmounting=!0}),t}const St=[Function,Array],Xr={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:St,onEnter:St,onAfterEnter:St,onEnterCancelled:St,onBeforeLeave:St,onLeave:St,onAfterLeave:St,onLeaveCancelled:St,onBeforeAppear:St,onAppear:St,onAfterAppear:St,onAppearCancelled:St},Ll={name:"BaseTransition",props:Xr,setup(t,{slots:e}){const n=yo(),o=Gr();let r;return()=>{const s=e.default&&fo(e.default(),!0);if(!s||!s.length)return;let l=s[0];if(s.length>1){for(const $ of s)if($.type!==_t){l=$;break}}const i=X(t),{mode:c}=i;if(o.isLeaving)return Pn(l);const a=Io(l);if(!a)return Pn(l);const f=Me(a,i,o,n);Ie(a,f);const p=n.subTree,g=p&&Io(p);let E=!1;const{getTransitionKey:L}=a.type;if(L){const $=L();r===void 0?r=$:$!==r&&(r=$,E=!0)}if(g&&g.type!==_t&&(!ne(a,g)||E)){const $=Me(g,i,o,n);if(Ie(g,$),c==="out-in")return o.isLeaving=!0,$.afterLeave=()=>{o.isLeaving=!1,n.update.active!==!1&&n.update()},Pn(l);c==="in-out"&&a.type!==_t&&($.delayLeave=(m,C,N)=>{Jr(o,g)[String(g.key)]=g,m._leaveCb=()=>{C(),m._leaveCb=void 0,delete f.delayedLeave},f.delayedLeave=N})}return l}}};function Jr(t,e){const{leavingVNodes:n}=t;let o=n.get(e.type);return o||(o=Object.create(null),n.set(e.type,o)),o}function Me(t,e,n,o){const{appear:r,mode:s,persisted:l=!1,onBeforeEnter:i,onEnter:c,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:p,onLeave:g,onAfterLeave:E,onLeaveCancelled:L,onBeforeAppear:$,onAppear:m,onAfterAppear:C,onAppearCancelled:N}=e,q=String(t.key),B=Jr(n,t),K=(M,W)=>{M&&Ft(M,o,9,W)},J=(M,W)=>{const z=W[1];K(M,W),U(M)?M.every(nt=>nt.length<=1)&&z():M.length<=1&&z()},H={mode:s,persisted:l,beforeEnter(M){let W=i;if(!n.isMounted){if(!r)return;W=$||i}M._leaveCb&&M._leaveCb(!0);const z=B[q];z&&ne(t,z)&&z.el._leaveCb&&z.el._leaveCb(),K(W,[M])},enter(M){let W=c,z=a,nt=f;if(!n.isMounted){if(!r)return;W=m||c,z=C||a,nt=N||f}let T=!1;const k=M._enterCb=V=>{T||(T=!0,K(V?nt:z,[M]),H.delayedLeave&&H.delayedLeave(),M._enterCb=void 0)};W?J(W,[M,k]):k()},leave(M,W){const z=String(t.key);if(M._enterCb&&M._enterCb(!0),n.isUnmounting)return W();K(p,[M]);let nt=!1;const T=M._leaveCb=k=>{nt||(nt=!0,W(),K(k?L:E,[M]),M._leaveCb=void 0,B[z]===t&&delete B[z])};B[z]=t,g?J(g,[M,T]):T()},clone:M=>Me(M,e,n,o)};return H}function Pn(t){if(Ve(t))return(t=Qt(t)).children=null,t}function Io(t){return Ve(t)?t.children?t.children[0]:void 0:t}function Ie(t,e){6&t.shapeFlag&&t.component?Ie(t.component.subTree,e):128&t.shapeFlag?(t.ssContent.transition=e.clone(t.ssContent),t.ssFallback.transition=e.clone(t.ssFallback)):t.transition=e}function fo(t,e=!1,n){let o=[],r=0;for(let s=0;s1)for(let s=0;set({name:t.name},e,{setup:t}))():t}const pe=t=>!!t.type.__asyncLoader;function zi(t){D(t)&&(t={loader:t});const{loader:e,loadingComponent:n,errorComponent:o,delay:r=200,timeout:s,suspensible:l=!0,onError:i}=t;let c,a=null,f=0;const p=()=>{let g;return a||(g=a=e().catch(E=>{if(E=E instanceof Error?E:new Error(String(E)),i)return new Promise((L,$)=>{i(E,()=>L((f++,a=null,p())),()=>$(E),f+1)});throw E}).then(E=>g!==a&&a?a:(E&&(E.__esModule||E[Symbol.toStringTag]==="Module")&&(E=E.default),c=E,E)))};return po({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return c},setup(){const g=it;if(c)return()=>$n(c,g);const E=C=>{a=null,je(C,g,13,!o)};if(l&&g.suspense)return p().then(C=>()=>$n(C,g)).catch(C=>(E(C),()=>o?ot(o,{error:C}):null));const L=ke(!1),$=ke(),m=ke(!!r);return r&&setTimeout(()=>{m.value=!1},r),s!=null&&setTimeout(()=>{if(!L.value&&!$.value){const C=new Error(`Async component timed out after ${s}ms.`);E(C),$.value=C}},s),p().then(()=>{L.value=!0,g.parent&&Ve(g.parent.vnode)&&wn(g.parent.update)}).catch(C=>{E(C),$.value=C}),()=>L.value&&c?$n(c,g):$.value&&o?ot(o,{error:$.value}):n&&!m.value?ot(n):void 0}})}function $n(t,e){const{ref:n,props:o,children:r,ce:s}=e.vnode,l=ot(t,o,r);return l.ref=n,l.ce=s,delete e.vnode.ce,l}const Ve=t=>t.type.__isKeepAlive;function Fl(t,e){Yr(t,"a",e)}function Ol(t,e){Yr(t,"da",e)}function Yr(t,e,n=it){const o=t.__wdc||(t.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return t()});if(En(e,o,n),n){let r=n.parent;for(;r&&r.parent;)Ve(r.parent.vnode)&&Pl(o,e,n,r),r=r.parent}}function Pl(t,e,n,o){const r=En(e,t,o,!0);An(()=>{Zn(o[e],r)},n)}function En(t,e,n=it,o=!1){if(n){const r=n[t]||(n[t]=[]),s=e.__weh||(e.__weh=(...l)=>{if(n.isUnmounted)return;he(),ye(n);const i=Ft(e,n,t,l);return le(),me(),i});return o?r.unshift(s):r.push(s),s}}const Vt=t=>(e,n=it)=>(!hn||t==="sp")&&En(t,(...o)=>e(...o),n),$l=Vt("bm"),kn=Vt("m"),Ml=Vt("bu"),Qr=Vt("u"),Zr=Vt("bum"),An=Vt("um"),Il=Vt("sp"),Nl=Vt("rtg"),Ul=Vt("rtc");function jl(t,e=it){En("ec",t,e)}const ho="components";function Ki(t,e){return es(ho,t,!0,e)||t}const ts=Symbol.for("v-ndc");function Gi(t){return st(t)?es(ho,t,!1)||t:t||ts}function es(t,e,n=!0,o=!1){const r=ut||it;if(r){const s=r.type;if(t===ho){const i=ei(s,!1);if(i&&(i===e||i===Mt(e)||i===yn(Mt(e))))return s}const l=No(r[t]||s[t],e)||No(r.appContext[t],e);return!l&&o?s:l}}function No(t,e){return t&&(t[e]||t[Mt(e)]||t[yn(Mt(e))])}function Xi(t,e,n,o){let r;const s=n&&n[o];if(U(t)||st(t)){r=new Array(t.length);for(let l=0,i=t.length;le(l,i,void 0,s&&s[i]));else{const l=Object.keys(t);r=new Array(l.length);for(let i=0,c=l.length;i!dn(e)||e.type!==_t&&!(e.type===pt&&!ns(e.children)))?t:null}function Yi(t,e){const n={};for(const o in t)n[e&&/[A-Z]/.test(o)?`on:${o}`:Ze(o)]=t[o];return n}const qn=t=>t?hs(t)?bo(t)||t.proxy:qn(t.parent):null,Ae=et(Object.create(null),{$:t=>t,$el:t=>t.vnode.el,$data:t=>t.data,$props:t=>t.props,$attrs:t=>t.attrs,$slots:t=>t.slots,$refs:t=>t.refs,$parent:t=>qn(t.parent),$root:t=>qn(t.root),$emit:t=>t.emit,$options:t=>mo(t),$forceUpdate:t=>t.f||(t.f=()=>wn(t.update)),$nextTick:t=>t.n||(t.n=Hr.bind(t.proxy)),$watch:t=>Rl.bind(t)}),Mn=(t,e)=>t!==Z&&!t.__isScriptSetup&&G(t,e),zn={get({_:t},e){const{ctx:n,setupState:o,data:r,props:s,accessCache:l,type:i,appContext:c}=t;let a;if(e[0]!=="$"){const E=l[e];if(E!==void 0)switch(E){case 1:return o[e];case 2:return r[e];case 4:return n[e];case 3:return s[e]}else{if(Mn(o,e))return l[e]=1,o[e];if(r!==Z&&G(r,e))return l[e]=2,r[e];if((a=t.propsOptions[0])&&G(a,e))return l[e]=3,s[e];if(n!==Z&&G(n,e))return l[e]=4,n[e];Kn&&(l[e]=0)}}const f=Ae[e];let p,g;return f?(e==="$attrs"&>(t,0,e),f(t)):(p=i.__cssModules)&&(p=p[e])?p:n!==Z&&G(n,e)?(l[e]=4,n[e]):(g=c.config.globalProperties,G(g,e)?g[e]:void 0)},set({_:t},e,n){const{data:o,setupState:r,ctx:s}=t;return Mn(r,e)?(r[e]=n,!0):o!==Z&&G(o,e)?(o[e]=n,!0):!G(t.props,e)&&(e[0]!=="$"||!(e.slice(1)in t))&&(s[e]=n,!0)},has({_:{data:t,setupState:e,accessCache:n,ctx:o,appContext:r,propsOptions:s}},l){let i;return!!n[l]||t!==Z&&G(t,l)||Mn(e,l)||(i=s[0])&&G(i,l)||G(o,l)||G(Ae,l)||G(r.config.globalProperties,l)},defineProperty(t,e,n){return n.get!=null?t._.accessCache[e]=0:G(n,"value")&&this.set(t,e,n.value,null),Reflect.defineProperty(t,e,n)}};et({},zn,{get(t,e){if(e!==Symbol.unscopables)return zn.get(t,e,t)},has:(t,e)=>e[0]!=="_"&&!Bs(e)});function Qi(){return Vl().slots}function Vl(){const t=yo();return t.setupContext||(t.setupContext=gs(t))}function Uo(t){return U(t)?t.reduce((e,n)=>(e[n]=null,e),{}):t}let Kn=!0;function Bl(t){const e=mo(t),n=t.proxy,o=t.ctx;Kn=!1,e.beforeCreate&&jo(e.beforeCreate,t,"bc");const{data:r,computed:s,methods:l,watch:i,provide:c,inject:a,created:f,beforeMount:p,mounted:g,beforeUpdate:E,updated:L,activated:$,deactivated:m,beforeUnmount:C,unmounted:N,render:q,renderTracked:B,renderTriggered:K,errorCaptured:J,serverPrefetch:H,expose:M,inheritAttrs:W,components:z,directives:nt}=e;if(a&&function(k,V,tt=Xt){U(k)&&(k=Gn(k));for(const bt in k){const Ct=k[bt];let wt;wt=Q(Ct)?"default"in Ct?Te(Ct.from||bt,Ct.default,!0):Te(Ct.from||bt):Te(Ct),at(wt)?Object.defineProperty(V,bt,{enumerable:!0,configurable:!0,get:()=>wt.value,set:Ot=>wt.value=Ot}):V[bt]=wt}}(a,o,null),l)for(const k in l){const V=l[k];D(V)&&(o[k]=V.bind(n))}if(r){const k=r.call(n,n);Q(k)&&(t.data=Cn(k))}if(Kn=!0,s)for(const k in s){const V=s[k],tt=D(V)?V.bind(n,n):D(V.get)?V.get.bind(n,n):Xt,bt=!D(V)&&D(V.set)?V.set.bind(n):Xt,Ct=At({get:tt,set:bt});Object.defineProperty(o,k,{enumerable:!0,configurable:!0,get:()=>Ct.value,set:wt=>Ct.value=wt})}if(i)for(const k in i)os(i[k],o,n,k);if(c){const k=D(c)?c.call(n):c;Reflect.ownKeys(k).forEach(V=>{ql(V,k[V])})}function T(k,V){U(V)?V.forEach(tt=>k(tt.bind(n))):V&&k(V.bind(n))}if(f&&jo(f,t,"c"),T($l,p),T(kn,g),T(Ml,E),T(Qr,L),T(Fl,$),T(Ol,m),T(jl,J),T(Ul,B),T(Nl,K),T(Zr,C),T(An,N),T(Il,H),U(M))if(M.length){const k=t.exposed||(t.exposed={});M.forEach(V=>{Object.defineProperty(k,V,{get:()=>n[V],set:tt=>n[V]=tt})})}else t.exposed||(t.exposed={});q&&t.render===Xt&&(t.render=q),W!=null&&(t.inheritAttrs=W),z&&(t.components=z),nt&&(t.directives=nt)}function jo(t,e,n){Ft(U(t)?t.map(o=>o.bind(e.proxy)):t.bind(e.proxy),e,n)}function os(t,e,n,o){const r=o.includes(".")?Kr(n,o):()=>n[o];if(st(t)){const s=e[t];D(s)&&en(r,s)}else if(D(t))en(r,t.bind(n));else if(Q(t))if(U(t))t.forEach(s=>os(s,e,n,o));else{const s=D(t.handler)?t.handler.bind(n):e[t.handler];D(s)&&en(r,s,t)}}function mo(t){const e=t.type,{mixins:n,extends:o}=e,{mixins:r,optionsCache:s,config:{optionMergeStrategies:l}}=t.appContext,i=s.get(e);let c;return i?c=i:r.length||n||o?(c={},r.length&&r.forEach(a=>an(c,a,l,!0)),an(c,e,l)):c=e,Q(e)&&s.set(e,c),c}function an(t,e,n,o=!1){const{mixins:r,extends:s}=e;s&&an(t,s,n,!0),r&&r.forEach(l=>an(t,l,n,!0));for(const l in e)if(!(o&&l==="expose")){const i=Hl[l]||n&&n[l];t[l]=i?i(t[l],e[l]):e[l]}return t}const Hl={data:Vo,props:Bo,emits:Bo,methods:Ce,computed:Ce,beforeCreate:dt,created:dt,beforeMount:dt,mounted:dt,beforeUpdate:dt,updated:dt,beforeDestroy:dt,beforeUnmount:dt,destroyed:dt,unmounted:dt,activated:dt,deactivated:dt,errorCaptured:dt,serverPrefetch:dt,components:Ce,directives:Ce,watch:function(t,e){if(!t)return e;if(!e)return t;const n=et(Object.create(null),t);for(const o in e)n[o]=dt(t[o],e[o]);return n},provide:Vo,inject:function(t,e){return Ce(Gn(t),Gn(e))}};function Vo(t,e){return e?t?function(){return et(D(t)?t.call(this,this):t,D(e)?e.call(this,this):e)}:e:t}function Gn(t){if(U(t)){const e={};for(let n=0;n(s.has(c)||(c&&D(c.install)?(s.add(c),c.install(i,...a)):D(c)&&(s.add(c),c(i,...a))),i),mixin:c=>(r.mixins.includes(c)||r.mixins.push(c),i),component:(c,a)=>a?(r.components[c]=a,i):r.components[c],directive:(c,a)=>a?(r.directives[c]=a,i):r.directives[c],mount(c,a,f){if(!l){const p=ot(n,o);return p.appContext=r,a&&e?e(p,c):t(p,c,f),l=!0,i._container=c,c.__vue_app__=i,bo(p.component)||p.component.proxy}},unmount(){l&&(t(null,i._container),delete i._container.__vue_app__)},provide:(c,a)=>(r.provides[c]=a,i),runWithContext(c){un=i;try{return c()}finally{un=null}}};return i}}let un=null;function ql(t,e){if(it){let n=it.provides;const o=it.parent&&it.parent.provides;o===n&&(n=it.provides=Object.create(o)),n[t]=e}}function Te(t,e,n=!1){const o=it||ut;if(o||un){const r=o?o.parent==null?o.vnode.appContext&&o.vnode.appContext.provides:o.parent.provides:un._context.provides;if(r&&t in r)return r[t];if(arguments.length>1)return n&&D(e)?e.call(o&&o.proxy):e}}function Ho(t,e,n,o){const[r,s]=t.propsOptions;let l,i=!1;if(e)for(let c in e){if(Se(c))continue;const a=e[c];let f;r&&G(r,f=Mt(c))?s&&s.includes(f)?(l||(l={}))[f]=a:n[f]=a:ln(t.emitsOptions,c)||c in o&&a===o[c]||(o[c]=a,i=!0)}if(s){const c=X(n),a=l||Z;for(let f=0;f{c=!0;const[g,E]=ss(p,e,!0);et(l,g),E&&i.push(...E)};!n&&e.mixins.length&&e.mixins.forEach(f),t.extends&&f(t.extends),t.mixins&&t.mixins.forEach(f)}if(!s&&!c)return Q(t)&&o.set(t,ae),ae;if(U(s))for(let f=0;f-1,E[1]=$<0||L<$,(L>-1||G(E,"default"))&&i.push(p)}}}const a=[l,i];return Q(t)&&o.set(t,a),a}function Do(t){return t[0]!=="$"}function Wo(t){const e=t&&t.toString().match(/^\s*(function|class) (\w+)/);return e?e[2]:t===null?"null":""}function qo(t,e){return Wo(t)===Wo(e)}function zo(t,e){return U(e)?e.findIndex(n=>qo(n,t)):D(e)&&qo(e,t)?0:-1}const ls=t=>t[0]==="_"||t==="$stable",go=t=>U(t)?t.map(Tt):[Tt(t)],zl=(t,e,n)=>{if(e._n)return e;const o=xl((...r)=>go(e(...r)),n);return o._c=!1,o},Ko=(t,e,n)=>{const o=t._ctx;for(const r in t){if(ls(r))continue;const s=t[r];if(D(s))e[r]=zl(0,s,o);else if(s!=null){const l=go(s);e[r]=()=>l}}},Go=(t,e)=>{const n=go(e);t.slots.default=()=>n};function fn(t,e,n,o,r=!1){if(U(t))return void t.forEach((g,E)=>fn(g,e&&(U(e)?e[E]:e),n,o,r));if(pe(o)&&!r)return;const s=4&o.shapeFlag?bo(o.component)||o.component.proxy:o.el,l=r?null:s,{i,r:c}=t,a=e&&e.r,f=i.refs===Z?i.refs={}:i.refs,p=i.setupState;if(a!=null&&a!==c&&(st(a)?(f[a]=null,G(p,a)&&(p[a]=null)):at(a)&&(a.value=null)),D(c))Yt(c,i,12,[l,f]);else{const g=st(c),E=at(c);if(g||E){const L=()=>{if(t.f){const $=g?G(p,c)?p[c]:f[c]:c.value;r?U($)&&Zn($,s):U($)?$.includes(s)||$.push(s):g?(f[c]=[s],G(p,c)&&(p[c]=f[c])):(c.value=[s],t.k&&(f[t.k]=c.value))}else g?(f[c]=l,G(p,c)&&(p[c]=l)):E&&(c.value=l,t.k&&(f[t.k]=l))};l?(L.id=-1,mt(L,n)):L()}}}let Wt=!1;const Je=t=>/svg/.test(t.namespaceURI)&&t.tagName!=="foreignObject",Ye=t=>t.nodeType===8;function Kl(t){const{mt:e,p:n,o:{patchProp:o,createText:r,nextSibling:s,parentNode:l,remove:i,insert:c,createComment:a}}=t,f=(m,C,N,q,B,K=!1)=>{const J=Ye(m)&&m.data==="[",H=()=>L(m,C,N,q,B,J),{type:M,ref:W,shapeFlag:z,patchFlag:nt}=C;let T=m.nodeType;C.el=m,nt===-2&&(K=!1,C.dynamicChildren=null);let k=null;switch(M){case ve:T!==3?C.children===""?(c(C.el=r(""),l(m),m),k=m):k=H():(m.data!==C.children&&(Wt=!0,m.data=C.children),k=s(m));break;case _t:k=T!==8||J?H():s(m);break;case Re:if(J&&(T=(m=s(m)).nodeType),T===1||T===3){k=m;const V=!C.children.length;for(let tt=0;tt{K=K||!!C.dynamicChildren;const{type:J,props:H,patchFlag:M,shapeFlag:W,dirs:z}=C,nt=J==="input"&&z||J==="option";if(nt||M!==-1){if(z&&Pt(C,null,N,"created"),H)if(nt||!K||48&M)for(const k in H)(nt&&k.endsWith("value")||Ue(k)&&!Se(k))&&o(m,k,null,H[k],!1,void 0,N);else H.onClick&&o(m,"onClick",null,H.onClick,!1,void 0,N);let T;if((T=H&&H.onVnodeBeforeMount)&&Et(T,N,C),z&&Pt(C,null,N,"beforeMount"),((T=H&&H.onVnodeMounted)||z)&&zr(()=>{T&&Et(T,N,C),z&&Pt(C,null,N,"mounted")},q),16&W&&(!H||!H.innerHTML&&!H.textContent)){let k=g(m.firstChild,C,m,N,q,B,K);for(;k;){Wt=!0;const V=k;k=k.nextSibling,i(V)}}else 8&W&&m.textContent!==C.children&&(Wt=!0,m.textContent=C.children)}return m.nextSibling},g=(m,C,N,q,B,K,J)=>{J=J||!!C.dynamicChildren;const H=C.children,M=H.length;for(let W=0;W{const{slotScopeIds:J}=C;J&&(B=B?B.concat(J):J);const H=l(m),M=g(s(m),C,H,N,q,B,K);return M&&Ye(M)&&M.data==="]"?s(C.anchor=M):(Wt=!0,c(C.anchor=a("]"),H,M),M)},L=(m,C,N,q,B,K)=>{if(Wt=!0,C.el=null,K){const M=$(m);for(;;){const W=s(m);if(!W||W===M)break;i(W)}}const J=s(m),H=l(m);return i(m),n(null,C,H,J,N,q,Je(H),B),J},$=m=>{let C=0;for(;m;)if((m=s(m))&&Ye(m)&&(m.data==="["&&C++,m.data==="]")){if(C===0)return s(m);C--}return m};return[(m,C)=>{if(!C.hasChildNodes())return n(null,m,C),sn(),void(C._vnode=m);Wt=!1,f(C.firstChild,m,null,null,null),sn(),C._vnode=m,Wt&&console.error("Hydration completed but contains mismatches.")},f]}const mt=zr;function Gl(t){return Xl(t,Kl)}function Xl(t,e){(Eo||(Eo=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{})).__VUE__=!0;const{insert:n,remove:o,patchProp:r,createElement:s,createText:l,createComment:i,setText:c,setElementText:a,parentNode:f,nextSibling:p,setScopeId:g=Xt,insertStaticContent:E}=t,L=(u,d,v,x=null,y=null,_=null,F=!1,w=null,b=!!d.dynamicChildren)=>{if(u===d)return;u&&!ne(u,d)&&(x=Be(u),Ot(u,y,_,!0),u=null),d.patchFlag===-2&&(b=!1,d.dynamicChildren=null);const{type:h,ref:R,shapeFlag:A}=d;switch(h){case ve:$(u,d,v,x);break;case _t:m(u,d,v,x);break;case Re:u==null&&C(d,v,x,F);break;case pt:W(u,d,v,x,y,_,F,w,b);break;default:1&A?N(u,d,v,x,y,_,F,w,b):6&A?z(u,d,v,x,y,_,F,w,b):(64&A||128&A)&&h.process(u,d,v,x,y,_,F,w,b,_e)}R!=null&&y&&fn(R,u&&u.ref,_,d||u,!d)},$=(u,d,v,x)=>{if(u==null)n(d.el=l(d.children),v,x);else{const y=d.el=u.el;d.children!==u.children&&c(y,d.children)}},m=(u,d,v,x)=>{u==null?n(d.el=i(d.children||""),v,x):d.el=u.el},C=(u,d,v,x)=>{[u.el,u.anchor]=E(u.children,d,v,x,u.el,u.anchor)},N=(u,d,v,x,y,_,F,w,b)=>{F=F||d.type==="svg",u==null?q(d,v,x,y,_,F,w,b):J(u,d,y,_,F,w,b)},q=(u,d,v,x,y,_,F,w)=>{let b,h;const{type:R,props:A,shapeFlag:O,transition:S,dirs:P}=u;if(b=u.el=s(u.type,_,A&&A.is,A),8&O?a(b,u.children):16&O&&K(u.children,b,null,x,y,_&&R!=="foreignObject",F,w),P&&Pt(u,null,x,"created"),B(b,u,u.scopeId,F,x),A){for(const I in A)I==="value"||Se(I)||r(b,I,null,A[I],_,u.children,x,y,It);"value"in A&&r(b,"value",null,A.value),(h=A.onVnodeBeforeMount)&&Et(h,x,u)}P&&Pt(u,null,x,"beforeMount");const j=(!y||y&&!y.pendingBranch)&&S&&!S.persisted;j&&S.beforeEnter(b),n(b,d,v),((h=A&&A.onVnodeMounted)||j||P)&&mt(()=>{h&&Et(h,x,u),j&&S.enter(b),P&&Pt(u,null,x,"mounted")},y)},B=(u,d,v,x,y)=>{if(v&&g(u,v),x)for(let _=0;_{for(let h=b;h{const w=d.el=u.el;let{patchFlag:b,dynamicChildren:h,dirs:R}=d;b|=16&u.patchFlag;const A=u.props||Z,O=d.props||Z;let S;v&&Zt(v,!1),(S=O.onVnodeBeforeUpdate)&&Et(S,v,d,u),R&&Pt(d,u,v,"beforeUpdate"),v&&Zt(v,!0);const P=y&&d.type!=="foreignObject";if(h?H(u.dynamicChildren,h,w,v,x,P,_):F||tt(u,d,w,null,v,x,P,_,!1),b>0){if(16&b)M(w,d,A,O,v,x,y);else if(2&b&&A.class!==O.class&&r(w,"class",null,O.class,y),4&b&&r(w,"style",A.style,O.style,y),8&b){const j=d.dynamicProps;for(let I=0;I{S&&Et(S,v,d,u),R&&Pt(d,u,v,"updated")},x)},H=(u,d,v,x,y,_,F)=>{for(let w=0;w{if(v!==x){if(v!==Z)for(const w in v)Se(w)||w in x||r(u,w,v[w],null,F,d.children,y,_,It);for(const w in x){if(Se(w))continue;const b=x[w],h=v[w];b!==h&&w!=="value"&&r(u,w,h,b,F,d.children,y,_,It)}"value"in x&&r(u,"value",v.value,x.value)}},W=(u,d,v,x,y,_,F,w,b)=>{const h=d.el=u?u.el:l(""),R=d.anchor=u?u.anchor:l("");let{patchFlag:A,dynamicChildren:O,slotScopeIds:S}=d;S&&(w=w?w.concat(S):S),u==null?(n(h,v,x),n(R,v,x),K(d.children,v,R,y,_,F,w,b)):A>0&&64&A&&O&&u.dynamicChildren?(H(u.dynamicChildren,O,v,y,_,F,w),(d.key!=null||y&&d===y.subTree)&&is(u,d,!0)):tt(u,d,v,R,y,_,F,w,b)},z=(u,d,v,x,y,_,F,w,b)=>{d.slotScopeIds=w,u==null?512&d.shapeFlag?y.ctx.activate(d,v,x,F,b):nt(d,v,x,y,_,F,b):T(u,d,b)},nt=(u,d,v,x,y,_,F)=>{const w=u.component=function(b,h,R){const A=b.type,O=(h?h.appContext:b.appContext)||Zl,S={uid:ti++,vnode:b,type:A,parent:h,appContext:O,root:null,next:null,subTree:null,effect:null,update:null,scope:new Ks(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:h?h.provides:Object.create(O.provides),accessCache:null,renderCache:[],components:null,directives:null,propsOptions:ss(A,O),emitsOptions:qr(A,O),emit:null,emitted:null,propsDefaults:Z,inheritAttrs:A.inheritAttrs,ctx:Z,data:Z,props:Z,attrs:Z,slots:Z,refs:Z,setupState:Z,setupContext:null,attrsProxy:null,slotsProxy:null,suspense:R,suspenseId:R?R.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return S.ctx={_:S},S.root=h?h.root:S,S.emit=wl.bind(null,S),b.ce&&b.ce(S),S}(u,x,y);if(Ve(u)&&(w.ctx.renderer=_e),function(b,h=!1){hn=h;const{props:R,children:A}=b.vnode,O=hs(b);(function(S,P,j,I=!1){const Y={},rt={};tn(rt,pn,1),S.propsDefaults=Object.create(null),Ho(S,P,Y,rt);for(const vt in S.propsOptions[0])vt in Y||(Y[vt]=void 0);S.props=j?I?Y:hl(Y):S.type.props?Y:rt,S.attrs=rt})(b,R,O,h),((S,P)=>{if(32&S.vnode.shapeFlag){const j=P._;j?(S.slots=X(P),tn(P,"_",j)):Ko(P,S.slots={})}else S.slots={},P&&Go(S,P);tn(S.slots,pn,1)})(b,A),O&&function(S,P){const j=S.type;S.accessCache=Object.create(null),S.proxy=Ee(new Proxy(S.ctx,zn));const{setup:I}=j;if(I){const Y=S.setupContext=I.length>1?gs(S):null;ye(S),he();const rt=Yt(I,S,0,[S.props,Y]);if(me(),le(),br(rt)){if(rt.then(le,le),P)return rt.then(vt=>{Yo(S,vt,P)}).catch(vt=>{je(vt,S,0)});S.asyncDep=rt}else Yo(S,rt,P)}else ms(S,P)}(b,h),hn=!1}(w),w.asyncDep){if(y&&y.registerDep(w,k),!u.el){const b=w.subTree=ot(_t);m(null,b,d,v)}}else k(w,u,d,v,y,_,F)},T=(u,d,v)=>{const x=d.component=u.component;if(function(y,_,F){const{props:w,children:b,component:h}=y,{props:R,children:A,patchFlag:O}=_,S=h.emitsOptions;if(_.dirs||_.transition)return!0;if(!(F&&O>=0))return!(!b&&!A||A&&A.$stable)||w!==R&&(w?!R||Mo(w,R,S):!!R);if(1024&O)return!0;if(16&O)return w?Mo(w,R,S):!!R;if(8&O){const P=_.dynamicProps;for(let j=0;j$t&&ct.splice(_,1)}(x.update),x.update()}else d.el=u.el,x.vnode=d},k=(u,d,v,x,y,_,F)=>{const w=u.effect=new so(()=>{if(u.isMounted){let h,{next:R,bu:A,u:O,parent:S,vnode:P}=u,j=R;Zt(u,!1),R?(R.el=P.el,V(u,R,F)):R=P,A&&Fn(A),(h=R.props&&R.props.onVnodeBeforeUpdate)&&Et(h,S,R,P),Zt(u,!0);const I=On(u),Y=u.subTree;u.subTree=I,L(Y,I,f(Y.el),Be(Y),u,y,_),R.el=I.el,j===null&&kl(u,I.el),O&&mt(O,y),(h=R.props&&R.props.onVnodeUpdated)&&mt(()=>Et(h,S,R,P),y)}else{let h;const{el:R,props:A}=d,{bm:O,m:S,parent:P}=u,j=pe(d);if(Zt(u,!1),O&&Fn(O),!j&&(h=A&&A.onVnodeBeforeMount)&&Et(h,P,d),Zt(u,!0),R&&Rn){const I=()=>{u.subTree=On(u),Rn(R,u.subTree,u,y,null)};j?d.type.__asyncLoader().then(()=>!u.isUnmounted&&I()):I()}else{const I=u.subTree=On(u);L(null,I,v,x,u,y,_),d.el=I.el}if(S&&mt(S,y),!j&&(h=A&&A.onVnodeMounted)){const I=d;mt(()=>Et(h,P,I),y)}(256&d.shapeFlag||P&&pe(P.vnode)&&256&P.vnode.shapeFlag)&&u.a&&mt(u.a,y),u.isMounted=!0,d=v=x=null}},()=>wn(b),u.scope),b=u.update=()=>w.run();b.id=u.uid,Zt(u,!0),b()},V=(u,d,v)=>{d.component=u;const x=u.vnode.props;u.vnode=d,u.next=null,function(y,_,F,w){const{props:b,attrs:h,vnode:{patchFlag:R}}=y,A=X(b),[O]=y.propsOptions;let S=!1;if(!(w||R>0)||16&R){let P;Ho(y,_,b,h)&&(S=!0);for(const j in A)_&&(G(_,j)||(P=ie(j))!==j&&G(_,P))||(O?!F||F[j]===void 0&&F[P]===void 0||(b[j]=Xn(O,A,j,void 0,y,!0)):delete b[j]);if(h!==A)for(const j in h)_&&G(_,j)||(delete h[j],S=!0)}else if(8&R){const P=y.vnode.dynamicProps;for(let j=0;j{const{vnode:w,slots:b}=y;let h=!0,R=Z;if(32&w.shapeFlag){const A=_._;A?F&&A===1?h=!1:(et(b,_),F||A!==1||delete b._):(h=!_.$stable,Ko(_,b)),R=_}else _&&(Go(y,_),R={default:1});if(h)for(const A in b)ls(A)||A in R||delete b[A]})(u,d.children,v),he(),$o(),me()},tt=(u,d,v,x,y,_,F,w,b=!1)=>{const h=u&&u.children,R=u?u.shapeFlag:0,A=d.children,{patchFlag:O,shapeFlag:S}=d;if(O>0){if(128&O)return void Ct(h,A,v,x,y,_,F,w,b);if(256&O)return void bt(h,A,v,x,y,_,F,w,b)}8&S?(16&R&&It(h,y,_),A!==h&&a(v,A)):16&R?16&S?Ct(h,A,v,x,y,_,F,w,b):It(h,y,_,!0):(8&R&&a(v,""),16&S&&K(A,v,x,y,_,F,w,b))},bt=(u,d,v,x,y,_,F,w,b)=>{const h=(u=u||ae).length,R=(d=d||ae).length,A=Math.min(h,R);let O;for(O=0;OR?It(u,y,_,!0,!1,A):K(d,v,x,y,_,F,w,b,A)},Ct=(u,d,v,x,y,_,F,w,b)=>{let h=0;const R=d.length;let A=u.length-1,O=R-1;for(;h<=A&&h<=O;){const S=u[h],P=d[h]=b?Kt(d[h]):Tt(d[h]);if(!ne(S,P))break;L(S,P,v,null,y,_,F,w,b),h++}for(;h<=A&&h<=O;){const S=u[A],P=d[O]=b?Kt(d[O]):Tt(d[O]);if(!ne(S,P))break;L(S,P,v,null,y,_,F,w,b),A--,O--}if(h>A){if(h<=O){const S=O+1,P=SO)for(;h<=A;)Ot(u[h],y,_,!0),h++;else{const S=h,P=h,j=new Map;for(h=P;h<=O;h++){const lt=d[h]=b?Kt(d[h]):Tt(d[h]);lt.key!=null&&j.set(lt.key,h)}let I,Y=0;const rt=O-P+1;let vt=!1,xo=0;const be=new Array(rt);for(h=0;h=rt){Ot(lt,y,_,!0);continue}let ht;if(lt.key!=null)ht=j.get(lt.key);else for(I=P;I<=O;I++)if(be[I-P]===0&&ne(lt,d[I])){ht=I;break}ht===void 0?Ot(lt,y,_,!0):(be[ht-P]=h+1,ht>=xo?xo=ht:vt=!0,L(lt,d[ht],v,null,y,_,F,w,b),Y++)}const So=vt?function(lt){const ht=lt.slice(),ft=[0];let Bt,Ln,xt,Ht,He;const Ps=lt.length;for(Bt=0;Bt>1,lt[ft[He]]0&&(ht[Bt]=ft[xt-1]),ft[xt]=Bt)}}for(xt=ft.length,Ht=ft[xt-1];xt-- >0;)ft[xt]=Ht,Ht=ht[Ht];return ft}(be):ae;for(I=So.length-1,h=rt-1;h>=0;h--){const lt=P+h,ht=d[lt],ft=lt+1{const{el:_,type:F,transition:w,children:b,shapeFlag:h}=u;if(6&h)return void wt(u.component.subTree,d,v,x);if(128&h)return void u.suspense.move(d,v,x);if(64&h)return void F.move(u,d,v,_e);if(F===pt){n(_,d,v);for(let R=0;R{let P;for(;R&&R!==A;)P=p(R),n(R,O,S),R=P;n(A,O,S)})(u,d,v);if(x!==2&&1&h&&w)if(x===0)w.beforeEnter(_),n(_,d,v),mt(()=>w.enter(_),y);else{const{leave:R,delayLeave:A,afterLeave:O}=w,S=()=>n(_,d,v),P=()=>{R(_,()=>{S(),O&&O()})};A?A(_,S,P):P()}else n(_,d,v)},Ot=(u,d,v,x=!1,y=!1)=>{const{type:_,props:F,ref:w,children:b,dynamicChildren:h,shapeFlag:R,patchFlag:A,dirs:O}=u;if(w!=null&&fn(w,null,v,u,!0),256&R)return void d.ctx.deactivate(u);const S=1&R&&O,P=!pe(u);let j;if(P&&(j=F&&F.onVnodeBeforeUnmount)&&Et(j,d,u),6&R)Os(u.component,v,x);else{if(128&R)return void u.suspense.unmount(v,x);S&&Pt(u,null,d,"beforeUnmount"),64&R?u.type.remove(u,d,v,y,_e,x):h&&(_!==pt||A>0&&64&A)?It(h,d,v,!1,!0):(_===pt&&384&A||!y&&16&R)&&It(b,d,v),x&&Co(u)}(P&&(j=F&&F.onVnodeUnmounted)||S)&&mt(()=>{j&&Et(j,d,u),S&&Pt(u,null,d,"unmounted")},v)},Co=u=>{const{type:d,el:v,anchor:x,transition:y}=u;if(d===pt)return void Fs(v,x);if(d===Re)return void(({el:F,anchor:w})=>{let b;for(;F&&F!==w;)b=p(F),o(F),F=b;o(w)})(u);const _=()=>{o(v),y&&!y.persisted&&y.afterLeave&&y.afterLeave()};if(1&u.shapeFlag&&y&&!y.persisted){const{leave:F,delayLeave:w}=y,b=()=>F(v,_);w?w(u.el,_,b):b()}else _()},Fs=(u,d)=>{let v;for(;u!==d;)v=p(u),o(u),u=v;o(d)},Os=(u,d,v)=>{const{bum:x,scope:y,update:_,subTree:F,um:w}=u;x&&Fn(x),y.stop(),_&&(_.active=!1,Ot(F,u,d,v)),w&&mt(w,d),mt(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},It=(u,d,v,x=!1,y=!1,_=0)=>{for(let F=_;F6&u.shapeFlag?Be(u.component.subTree):128&u.shapeFlag?u.suspense.next():p(u.anchor||u.el),wo=(u,d,v)=>{u==null?d._vnode&&Ot(d._vnode,null,null,!0):L(d._vnode||null,u,d,null,null,null,v),$o(),sn(),d._vnode=u},_e={p:L,um:Ot,m:wt,r:Co,mt:nt,mc:K,pc:tt,pbc:H,n:Be,o:t};let Tn,Rn;return e&&([Tn,Rn]=e(_e)),{render:wo,hydrate:Tn,createApp:Wl(wo,Tn)}}function Zt({effect:t,update:e},n){t.allowRecurse=e.allowRecurse=n}function is(t,e,n=!1){const o=t.children,r=e.children;if(U(o)&&U(r))for(let s=0;s0?Lt||ae:null,Jl(),Ne>0&&Lt&&Lt.push(t),t}function Zi(t,e,n,o,r,s){return as(ds(t,e,n,o,r,s,!0))}function us(t,e,n,o,r){return as(ot(t,e,n,o,r,!0))}function dn(t){return!!t&&t.__v_isVNode===!0}function ne(t,e){return t.type===e.type&&t.key===e.key}const pn="__vInternal",fs=({key:t})=>t??null,nn=({ref:t,ref_key:e,ref_for:n})=>(typeof t=="number"&&(t=""+t),t!=null?st(t)||at(t)||D(t)?{i:ut,r:t,k:e,f:!!n}:t:null);function ds(t,e=null,n=null,o=0,r=null,s=t===pt?0:1,l=!1,i=!1){const c={__v_isVNode:!0,__v_skip:!0,type:t,props:e,key:e&&fs(e),ref:e&&nn(e),scopeId:xn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:o,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ut};return i?(vo(c,n),128&s&&t.normalize(c)):n&&(c.shapeFlag|=st(n)?8:16),Ne>0&&!l&&Lt&&(c.patchFlag>0||6&s)&&c.patchFlag!==32&&Lt.push(c),c}const ot=function(t,e=null,n=null,o=0,r=null,s=!1){if(t&&t!==ts||(t=_t),dn(t)){const c=Qt(t,e,!0);return n&&vo(c,n),Ne>0&&!s&&Lt&&(6&c.shapeFlag?Lt[Lt.indexOf(t)]=c:Lt.push(c)),c.patchFlag|=-2,c}l=t,D(l)&&"__vccOpts"in l&&(t=t.__vccOpts);var l;if(e){e=Yl(e);let{class:c,style:a}=e;c&&!st(c)&&(e.class=oo(c)),Q(a)&&(Ir(a)&&!U(a)&&(a=et({},a)),e.style=no(a))}const i=st(t)?1:Al(t)?128:(c=>c.__isTeleport)(t)?64:Q(t)?4:D(t)?2:0;return ds(t,e,n,o,r,i,s,!0)};function Yl(t){return t?Ir(t)||pn in t?et({},t):t:null}function Qt(t,e,n=!1){const{props:o,ref:r,patchFlag:s,children:l}=t,i=e?Ql(o||{},e):o;return{__v_isVNode:!0,__v_skip:!0,type:t.type,props:i,key:i&&fs(i),ref:e&&e.ref?n&&r?U(r)?r.concat(nn(e)):[r,nn(e)]:nn(e):r,scopeId:t.scopeId,slotScopeIds:t.slotScopeIds,children:l,target:t.target,targetAnchor:t.targetAnchor,staticCount:t.staticCount,shapeFlag:t.shapeFlag,patchFlag:e&&t.type!==pt?s===-1?16:16|s:s,dynamicProps:t.dynamicProps,dynamicChildren:t.dynamicChildren,appContext:t.appContext,dirs:t.dirs,transition:t.transition,component:t.component,suspense:t.suspense,ssContent:t.ssContent&&Qt(t.ssContent),ssFallback:t.ssFallback&&Qt(t.ssFallback),el:t.el,anchor:t.anchor,ctx:t.ctx,ce:t.ce}}function ps(t=" ",e=0){return ot(ve,null,t,e)}function tc(t,e){const n=ot(Re,null,t);return n.staticCount=e,n}function ec(t="",e=!1){return e?(cs(),us(_t,null,t)):ot(_t,null,t)}function Tt(t){return t==null||typeof t=="boolean"?ot(_t):U(t)?ot(pt,null,t.slice()):typeof t=="object"?Kt(t):ot(ve,null,String(t))}function Kt(t){return t.el===null&&t.patchFlag!==-1||t.memo?t:Qt(t)}function vo(t,e){let n=0;const{shapeFlag:o}=t;if(e==null)e=null;else if(U(e))n=16;else if(typeof e=="object"){if(65&o){const r=e.default;return void(r&&(r._c&&(r._d=!1),vo(t,r()),r._c&&(r._d=!0)))}{n=32;const r=e._;r||pn in e?r===3&&ut&&(ut.slots._===1?e._=1:(e._=2,t.patchFlag|=1024)):e._ctx=ut}}else D(e)?(e={default:e,_ctx:ut},n=32):(e=String(e),64&o?(n=16,e=[ps(e)]):n=8);t.children=e,t.shapeFlag|=n}function Ql(...t){const e={};for(let n=0;nit||ut;let _o;_o=t=>{it=t};const ye=t=>{_o(t),t.scope.on()},le=()=>{it&&it.scope.off(),_o(null)};function hs(t){return 4&t.vnode.shapeFlag}let Jo,hn=!1;function Yo(t,e,n){D(e)?t.render=e:Q(e)&&(t.setupState=Vr(e)),ms(t,n)}function ms(t,e,n){const o=t.type;if(!t.render){if(!e&&Jo&&!o.render){const r=o.template||mo(t).template;if(r){const{isCustomElement:s,compilerOptions:l}=t.appContext.config,{delimiters:i,compilerOptions:c}=o,a=et(et({isCustomElement:s,delimiters:i},l),c);o.render=Jo(r,a)}}t.render=o.render||Xt}ye(t),he(),Bl(t),me(),le()}function gs(t){const e=n=>{t.exposed=n||{}};return{get attrs(){return function(n){return n.attrsProxy||(n.attrsProxy=new Proxy(n.attrs,{get:(o,r)=>(gt(n,0,"$attrs"),o[r])}))}(t)},slots:t.slots,emit:t.emit,expose:e}}function bo(t){if(t.exposed)return t.exposeProxy||(t.exposeProxy=new Proxy(Vr(Ee(t.exposed)),{get:(e,n)=>n in e?e[n]:n in Ae?Ae[n](t):void 0,has:(e,n)=>n in e||n in Ae}))}function ei(t,e=!0){return D(t)?t.displayName||t.name:t.name||e&&t.__name}const At=(t,e)=>function(n,o,r=!1){let s,l;const i=D(n);return i?(s=n,l=Xt):(s=n.get,l=n.set),new _l(s,l,i||!l,r)}(t,0,hn);function Jn(t,e,n){const o=arguments.length;return o===2?Q(e)&&!U(e)?dn(e)?ot(t,null,[e]):ot(t,e):ot(t,null,e):(o>3?n=Array.prototype.slice.call(arguments,2):o===3&&dn(n)&&(n=[n]),ot(t,e,n))}const ni="3.3.4",oe=typeof document<"u"?document:null,Qo=oe&&oe.createElement("template"),oi={insert:(t,e,n)=>{e.insertBefore(t,n||null)},remove:t=>{const e=t.parentNode;e&&e.removeChild(t)},createElement:(t,e,n,o)=>{const r=e?oe.createElementNS("http://www.w3.org/2000/svg",t):oe.createElement(t,n?{is:n}:void 0);return t==="select"&&o&&o.multiple!=null&&r.setAttribute("multiple",o.multiple),r},createText:t=>oe.createTextNode(t),createComment:t=>oe.createComment(t),setText:(t,e)=>{t.nodeValue=e},setElementText:(t,e)=>{t.textContent=e},parentNode:t=>t.parentNode,nextSibling:t=>t.nextSibling,querySelector:t=>oe.querySelector(t),setScopeId(t,e){t.setAttribute(e,"")},insertStaticContent(t,e,n,o,r,s){const l=n?n.previousSibling:e.lastChild;if(r&&(r===s||r.nextSibling))for(;e.insertBefore(r.cloneNode(!0),n),r!==s&&(r=r.nextSibling););else{Qo.innerHTML=o?`${t}`:t;const i=Qo.content;if(o){const c=i.firstChild;for(;c.firstChild;)i.appendChild(c.firstChild);i.removeChild(c)}e.insertBefore(i,n)}return[l?l.nextSibling:e.firstChild,n?n.previousSibling:e.lastChild]}},Zo=/\s*!important$/;function Yn(t,e,n){if(U(n))n.forEach(o=>Yn(t,e,o));else if(n==null&&(n=""),e.startsWith("--"))t.setProperty(e,n);else{const o=function(r,s){const l=In[s];if(l)return l;let i=Mt(s);if(i!=="filter"&&i in r)return In[s]=i;i=yn(i);for(let c=0;c{if(E._vts){if(E._vts<=g.attached)return}else E._vts=Date.now();Ft(function(L,$){if(U($)){const m=L.stopImmediatePropagation;return L.stopImmediatePropagation=()=>{m.call(L),L._stopped=!0},$.map(C=>N=>!N._stopped&&C&&C(N))}return $}(E,g.value),p,5,[E])};return g.value=f,g.attached=(()=>Nn||(li.then(()=>Nn=0),Nn=Date.now()))(),g}(o,r);ri(t,i,a,c)}else l&&(function(a,f,p,g){a.removeEventListener(f,p,g)}(t,i,l,c),s[e]=void 0)}}const nr=/(?:Once|Passive|Capture)$/;let Nn=0;const li=Promise.resolve(),or=/^on[a-z]/,qt="transition",we="animation",vs=(t,{slots:e})=>Jn(Ll,_s(t),e);vs.displayName="Transition";const ys={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},ii=vs.props=et({},Xr,ys),te=(t,e=[])=>{U(t)?t.forEach(n=>n(...e)):t&&t(...e)},rr=t=>!!t&&(U(t)?t.some(e=>e.length>1):t.length>1);function _s(t){const e={};for(const T in t)T in ys||(e[T]=t[T]);if(t.css===!1)return e;const{name:n="v",type:o,duration:r,enterFromClass:s=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:i=`${n}-enter-to`,appearFromClass:c=s,appearActiveClass:a=l,appearToClass:f=i,leaveFromClass:p=`${n}-leave-from`,leaveActiveClass:g=`${n}-leave-active`,leaveToClass:E=`${n}-leave-to`}=t,L=function(T){if(T==null)return null;if(Q(T))return[Un(T.enter),Un(T.leave)];{const k=Un(T);return[k,k]}}(r),$=L&&L[0],m=L&&L[1],{onBeforeEnter:C,onEnter:N,onEnterCancelled:q,onLeave:B,onLeaveCancelled:K,onBeforeAppear:J=C,onAppear:H=N,onAppearCancelled:M=q}=e,W=(T,k,V)=>{zt(T,k?f:i),zt(T,k?a:l),V&&V()},z=(T,k)=>{T._isLeaving=!1,zt(T,p),zt(T,E),zt(T,g),k&&k()},nt=T=>(k,V)=>{const tt=T?H:N,bt=()=>W(k,T,V);te(tt,[k,bt]),sr(()=>{zt(k,T?c:s),Nt(k,T?f:i),rr(tt)||lr(k,o,$,bt)})};return et(e,{onBeforeEnter(T){te(C,[T]),Nt(T,s),Nt(T,l)},onBeforeAppear(T){te(J,[T]),Nt(T,c),Nt(T,a)},onEnter:nt(!1),onAppear:nt(!0),onLeave(T,k){T._isLeaving=!0;const V=()=>z(T,k);Nt(T,p),Cs(),Nt(T,g),sr(()=>{T._isLeaving&&(zt(T,p),Nt(T,E),rr(B)||lr(T,o,m,V))}),te(B,[T,V])},onEnterCancelled(T){W(T,!1),te(q,[T])},onAppearCancelled(T){W(T,!0),te(M,[T])},onLeaveCancelled(T){z(T),te(K,[T])}})}function Un(t){return Vs(t)}function Nt(t,e){e.split(/\s+/).forEach(n=>n&&t.classList.add(n)),(t._vtc||(t._vtc=new Set)).add(e)}function zt(t,e){e.split(/\s+/).forEach(o=>o&&t.classList.remove(o));const{_vtc:n}=t;n&&(n.delete(e),n.size||(t._vtc=void 0))}function sr(t){requestAnimationFrame(()=>{requestAnimationFrame(t)})}let ci=0;function lr(t,e,n,o){const r=t._endId=++ci,s=()=>{r===t._endId&&o()};if(n)return setTimeout(s,n);const{type:l,timeout:i,propCount:c}=bs(t,e);if(!l)return o();const a=l+"end";let f=0;const p=()=>{t.removeEventListener(a,g),s()},g=E=>{E.target===t&&++f>=c&&p()};setTimeout(()=>{f(n[E]||"").split(", "),r=o(`${qt}Delay`),s=o(`${qt}Duration`),l=ir(r,s),i=o(`${we}Delay`),c=o(`${we}Duration`),a=ir(i,c);let f=null,p=0,g=0;return e===qt?l>0&&(f=qt,p=l,g=s.length):e===we?a>0&&(f=we,p=a,g=c.length):(p=Math.max(l,a),f=p>0?l>a?qt:we:null,g=f?f===qt?s.length:c.length:0),{type:f,timeout:p,propCount:g,hasTransform:f===qt&&/\b(transform|all)(,|$)/.test(o(`${qt}Property`).toString())}}function ir(t,e){for(;t.lengthcr(n)+cr(t[o])))}function cr(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}function Cs(){return document.body.offsetHeight}const ws=new WeakMap,xs=new WeakMap;et({},ii,{tag:String,moveClass:String});function ai(t){const e=t.el;e._moveCb&&e._moveCb(),e._enterCb&&e._enterCb()}function ui(t){xs.set(t,t.el.getBoundingClientRect())}function fi(t){const e=ws.get(t),n=xs.get(t),o=e.left-n.left,r=e.top-n.top;if(o||r){const s=t.el.style;return s.transform=s.webkitTransform=`translate(${o}px,${r}px)`,s.transitionDuration="0s",t}}const di=["ctrl","shift","alt","meta"],pi={stop:t=>t.stopPropagation(),prevent:t=>t.preventDefault(),self:t=>t.target!==t.currentTarget,ctrl:t=>!t.ctrlKey,shift:t=>!t.shiftKey,alt:t=>!t.altKey,meta:t=>!t.metaKey,left:t=>"button"in t&&t.button!==0,middle:t=>"button"in t&&t.button!==1,right:t=>"button"in t&&t.button!==2,exact:(t,e)=>di.some(n=>t[`${n}Key`]&&!e.includes(n))},nc=(t,e)=>(n,...o)=>{for(let r=0;rn=>{if(!("key"in n))return;const o=ie(n.key);return e.some(r=>r===o||hi[r]===o)?t(n):void 0},mi=et({patchProp:(t,e,n,o,r=!1,s,l,i,c)=>{e==="class"?function(a,f,p){const g=a._vtc;g&&(f=(f?[f,...g]:[...g]).join(" ")),f==null?a.removeAttribute("class"):p?a.setAttribute("class",f):a.className=f}(t,o,r):e==="style"?function(a,f,p){const g=a.style,E=st(p);if(p&&!E){if(f&&!st(f))for(const L in f)p[L]==null&&Yn(g,L,"");for(const L in p)Yn(g,L,p[L])}else{const L=g.display;E?f!==p&&(g.cssText=p):f&&a.removeAttribute("style"),"_vod"in a&&(g.display=L)}}(t,n,o):Ue(e)?Qn(e)||si(t,e,0,o,l):(e[0]==="."?(e=e.slice(1),1):e[0]==="^"?(e=e.slice(1),0):function(a,f,p,g){return g?f==="innerHTML"||f==="textContent"||!!(f in a&&or.test(f)&&D(p)):f==="spellcheck"||f==="draggable"||f==="translate"||f==="form"||f==="list"&&a.tagName==="INPUT"||f==="type"&&a.tagName==="TEXTAREA"||or.test(f)&&st(p)?!1:f in a}(t,e,o,r))?function(a,f,p,g,E,L,$){if(f==="innerHTML"||f==="textContent")return g&&$(g,E,L),void(a[f]=p??"");const m=a.tagName;if(f==="value"&&m!=="PROGRESS"&&!m.includes("-")){a._value=p;const N=p??"";return(m==="OPTION"?a.getAttribute("value"):a.value)!==N&&(a.value=N),void(p==null&&a.removeAttribute(f))}let C=!1;if(p===""||p==null){const N=typeof a[f];N==="boolean"?p=ko(p):p==null&&N==="string"?(p="",C=!0):N==="number"&&(p=0,C=!0)}try{a[f]=p}catch{}C&&a.removeAttribute(f)}(t,e,o,s,l,i,c):(e==="true-value"?t._trueValue=o:e==="false-value"&&(t._falseValue=o),function(a,f,p,g,E){if(g&&f.startsWith("xlink:"))p==null?a.removeAttributeNS(er,f.slice(6,f.length)):a.setAttributeNS(er,f,p);else{const L=zs(f);p==null||L&&!ko(p)?a.removeAttribute(f):a.setAttribute(f,L?"":p)}}(t,e,o,r))}},oi);let jn,ar=!1;function gi(){return jn=ar?jn:Gl(mi),ar=!0,jn}const rc=(...t)=>{const e=gi().createApp(...t),{mount:n}=e;return e.mount=o=>{const r=vi(o);if(r)return n(r,!0,r instanceof SVGElement)},e};function vi(t){return st(t)?document.querySelector(t):t}const sc=(t,e)=>{const n=t.__vccOpts||t;for(const[o,r]of e)n[o]=r;return n},yi="modulepreload",_i=function(t){return"/"+t},ur={},lc=function(e,n,o){if(!n||n.length===0)return e();const r=document.getElementsByTagName("link");return Promise.all(n.map(s=>{if(s=_i(s),s in ur)return;ur[s]=!0;const l=s.endsWith(".css"),i=l?'[rel="stylesheet"]':"";if(!!o)for(let f=r.length-1;f>=0;f--){const p=r[f];if(p.href===s&&(!l||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${s}"]${i}`))return;const a=document.createElement("link");if(a.rel=l?"stylesheet":yi,l||(a.as="script",a.crossOrigin=""),a.href=s,document.head.appendChild(a),l)return new Promise((f,p)=>{a.addEventListener("load",f),a.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${s}`)))})})).then(()=>e()).catch(s=>{const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=s,window.dispatchEvent(l),!l.defaultPrevented)throw s})},bi=window.__VP_SITE_DATA__,Ss=/^[a-z]+:/i,ic=/^pathname:\/\//,cc="vitepress-theme-appearance",Es=/#.*$/,Ci=/(index)?\.(md|html)$/,kt=typeof document<"u",ks={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function wi(t,e,n=!1){if(e===void 0)return!1;if(t=fr(`/${t}`),n)return new RegExp(e).test(t);if(fr(e)!==t)return!1;const o=e.match(Es);return o?(kt?location.hash:"")===o[0]:!0}function fr(t){return decodeURI(t).replace(Es,"").replace(Ci,"")}function xi(t){return Ss.test(t)}function Si(t,e){var o,r,s,l,i,c,a;const n=Object.keys(t.locales).find(f=>f!=="root"&&!xi(f)&&wi(e,`/${f}/`,!0))||"root";return Object.assign({},t,{localeIndex:n,lang:((o=t.locales[n])==null?void 0:o.lang)??t.lang,dir:((r=t.locales[n])==null?void 0:r.dir)??t.dir,title:((s=t.locales[n])==null?void 0:s.title)??t.title,titleTemplate:((l=t.locales[n])==null?void 0:l.titleTemplate)??t.titleTemplate,description:((i=t.locales[n])==null?void 0:i.description)??t.description,head:Ts(t.head,((c=t.locales[n])==null?void 0:c.head)??[]),themeConfig:{...t.themeConfig,...(a=t.locales[n])==null?void 0:a.themeConfig}})}function As(t,e){const n=e.title||t.title,o=e.titleTemplate??t.titleTemplate;if(typeof o=="string"&&o.includes(":title"))return o.replace(/:title/g,n);const r=Ei(t.title,o);return`${n}${r}`}function Ei(t,e){return e===!1?"":e===!0||e===void 0?` | ${t}`:t===e?"":` | ${e}`}function ki(t,e){const[n,o]=e;if(n!=="meta")return!1;const r=Object.entries(o)[0];return r==null?!1:t.some(([s,l])=>s===n&&l[r[0]]===r[1])}function Ts(t,e){return[...t.filter(n=>!ki(e,n)),...e]}const Ai=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,Ti=/^[a-z]:/i;function dr(t){const e=Ti.exec(t),n=e?e[0]:"";return n+t.slice(n.length).replace(Ai,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const Ri=Symbol(),re=ml(bi);function ac(t){const e=At(()=>Si(re.value,t.data.relativePath));return{site:e,theme:At(()=>e.value.themeConfig),page:At(()=>t.data),frontmatter:At(()=>t.data.frontmatter),params:At(()=>t.data.params),lang:At(()=>e.value.lang),dir:At(()=>e.value.dir),localeIndex:At(()=>e.value.localeIndex||"root"),title:At(()=>As(e.value,t.data)),description:At(()=>t.data.description||e.value.description),isDark:ke(!1)}}function uc(){const t=Te(Ri);if(!t)throw new Error("vitepress data not properly injected in app");return t}function Li(t,e){return`${t}${e}`.replace(/\/+/g,"/")}function pr(t){return Ss.test(t)||t.startsWith(".")?t:Li(re.value.base,t)}function Fi(t){let e=t.replace(/\.html$/,"");if(e=decodeURIComponent(e),e=e.replace(/\/$/,"/index"),kt){const n="/";e=dr(e.slice(n.length).replace(/\//g,"_")||"index")+".md";let o=__VP_HASH_MAP__[e.toLowerCase()];if(o||(e=e.endsWith("_index.md")?e.slice(0,-9)+".md":e.slice(0,-3)+"_index.md",o=__VP_HASH_MAP__[e.toLowerCase()]),!o)return null;e=`${n}assets/${e}.${o}.js`}else e=`./${dr(e.slice(1).replace(/\//g,"_"))}.md.js`;return e}let on=[];function fc(t){on.push(t),An(()=>{on=on.filter(e=>e!==t)})}const Oi=Symbol(),hr="http://a.com",Pi=()=>({path:"/",component:null,data:ks});function dc(t,e){const n=Cn(Pi()),o={route:n,go:r};async function r(i=kt?location.href:"/"){var a,f;if(await((a=o.onBeforeRouteChange)==null?void 0:a.call(o,i))===!1)return;const c=new URL(i,hr);re.value.cleanUrls||!c.pathname.endsWith("/")&&!c.pathname.endsWith(".html")&&(c.pathname+=".html",i=c.pathname+c.search+c.hash),kt&&i!==location.href&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",i)),await l(i),await((f=o.onAfterRouteChanged)==null?void 0:f.call(o,i))}let s=null;async function l(i,c=0,a=!1){var g;if(await((g=o.onBeforePageLoad)==null?void 0:g.call(o,i))===!1)return;const f=new URL(i,hr),p=s=f.pathname;try{let E=await t(p);if(!E)throw new Error(`Page not found: ${p}`);if(s===p){s=null;const{default:L,__pageData:$}=E;if(!L)throw new Error(`Invalid route component: ${L}`);n.path=kt?p:pr(p),n.component=Ee(L),n.data=Ee($),kt&&Hr(()=>{let m=re.value.base+$.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!re.value.cleanUrls&&!m.endsWith("/")&&(m+=".html"),m!==f.pathname&&(f.pathname=m,i=m+f.search+f.hash,history.replaceState(null,"",i)),f.hash&&!c){let C=null;try{C=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(N){console.warn(N)}if(C){mr(C,f.hash);return}}window.scrollTo(0,c)})}}catch(E){if(!/fetch|Page not found/.test(E.message)&&!/^\/404(\.html|\/)?$/.test(i)&&console.error(E),!a)try{const L=await fetch(re.value.base+"hashmap.json");window.__VP_HASH_MAP__=await L.json(),await l(i,c,!0);return}catch{}s===p&&(s=null,n.path=kt?p:pr(p),n.component=e?Ee(e):null,n.data=ks)}}return kt&&(window.addEventListener("click",i=>{if(i.target.closest("button"))return;const a=i.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:f}=a,{href:p,origin:g,pathname:E,hash:L,search:$}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),m=window.location,C=E.match(/\.\w+$/);!i.ctrlKey&&!i.shiftKey&&!i.altKey&&!i.metaKey&&!f&&g===m.origin&&!(C&&C[0]!==".html")&&(i.preventDefault(),E===m.pathname&&$===m.search?L&&(L!==m.hash&&(history.pushState(null,"",L),window.dispatchEvent(new Event("hashchange"))),mr(a,L,a.classList.contains("header-anchor"))):r(p))}},{capture:!0}),window.addEventListener("popstate",i=>{l(location.href,i.state&&i.state.scrollPosition||0)}),window.addEventListener("hashchange",i=>{i.preventDefault()})),o}function $i(){const t=Te(Oi);if(!t)throw new Error("useRouter() is called without provider.");return t}function Rs(){return $i().route}function mr(t,e,n=!1){let o=null;try{o=t.classList.contains("header-anchor")?t:document.getElementById(decodeURIComponent(e).slice(1))}catch(r){console.warn(r)}if(o){let c=function(){!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})};const r=re.value.scrollOffset;let s=0;if(typeof r=="number")s=r;else if(typeof r=="string")s=gr(r);else if(Array.isArray(r))for(const a of r){const f=gr(a);if(f){s=f;break}}const l=parseInt(window.getComputedStyle(o).paddingTop,10),i=window.scrollY+o.getBoundingClientRect().top-s+l;requestAnimationFrame(c)}}function gr(t){const e=document.querySelector(t);if(!e)return 0;const n=e.getBoundingClientRect().bottom;return n<0?0:n+24}const vr=()=>on.forEach(t=>t()),pc=po({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(t){const e=Rs();return()=>Jn(t.as,{style:{position:"relative"}},[e.component?Jn(e.component,{onVnodeMounted:vr,onVnodeUpdated:vr}):"404 Page Not Found"])}}),hc=po({setup(t,{slots:e}){const n=ke(!1);return kn(()=>{n.value=!0}),()=>n.value&&e.default?e.default():null}});function mc(){kt&&window.addEventListener("click",t=>{var n,o;const e=t.target;if(e.matches(".vp-code-group input")){const r=(n=e.parentElement)==null?void 0:n.parentElement,s=Array.from((r==null?void 0:r.querySelectorAll("input"))||[]).indexOf(e),l=r==null?void 0:r.querySelector('div[class*="language-"].active'),i=(o=r==null?void 0:r.querySelectorAll('div[class*="language-"]:not(.language-id)'))==null?void 0:o[s];l&&i&&l!==i&&(l.classList.remove("active"),i.classList.add("active"))}})}function gc(){if(kt){const t=new WeakMap;window.addEventListener("click",e=>{var o;const n=e.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,s=(o=n.nextElementSibling)==null?void 0:o.nextElementSibling;if(!r||!s)return;const l=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className);let i="";s.querySelectorAll("span.line:not(.diff.remove)").forEach(c=>i+=(c.textContent||"")+` -`),i=i.slice(0,-1),l&&(i=i.replace(/^ *(\$|>) /gm,"").trim()),Mi(i).then(()=>{n.classList.add("copied"),clearTimeout(t.get(n));const c=setTimeout(()=>{n.classList.remove("copied"),n.blur(),t.delete(n)},2e3);t.set(n,c)})}})}}async function Mi(t){try{return navigator.clipboard.writeText(t)}catch{const e=document.createElement("textarea"),n=document.activeElement;e.value=t,e.setAttribute("readonly",""),e.style.contain="strict",e.style.position="absolute",e.style.left="-9999px",e.style.fontSize="12pt";const o=document.getSelection(),r=o?o.rangeCount>0&&o.getRangeAt(0):null;document.body.appendChild(e),e.select(),e.selectionStart=0,e.selectionEnd=t.length,document.execCommand("copy"),document.body.removeChild(e),r&&(o.removeAllRanges(),o.addRange(r)),n&&n.focus()}}function vc(t,e){let n=[],o=!0;const r=s=>{if(o){o=!1;return}n.forEach(l=>document.head.removeChild(l)),n=[],s.forEach(l=>{const i=yr(l);document.head.appendChild(i),n.push(i)})};Tl(()=>{const s=t.data,l=e.value,i=s&&s.description,c=s&&s.frontmatter.head||[];document.title=As(l,s);const a=i||l.description;let f=document.querySelector("meta[name=description]");f?f.setAttribute("content",a):yr(["meta",{name:"description",content:a}]),r(Ts(l.head,Ni(c)))})}function yr([t,e,n]){const o=document.createElement(t);for(const r in e)o.setAttribute(r,e[r]);return n&&(o.innerHTML=n),o}function Ii(t){return t[0]==="meta"&&t[1]&&t[1].name==="description"}function Ni(t){return t.filter(e=>!Ii(e))}const Vn=new Set,Ls=()=>document.createElement("link"),Ui=t=>{const e=Ls();e.rel="prefetch",e.href=t,document.head.appendChild(e)},ji=t=>{const e=new XMLHttpRequest;e.open("GET",t,e.withCredentials=!0),e.send()};let Qe;const Vi=kt&&(Qe=Ls())&&Qe.relList&&Qe.relList.supports&&Qe.relList.supports("prefetch")?Ui:ji;function yc(){if(!kt||!window.IntersectionObserver)return;let t;if((t=navigator.connection)&&(t.saveData||/2g/.test(t.effectiveType)))return;const e=window.requestIdleCallback||setTimeout;let n=null;const o=()=>{n&&n.disconnect(),n=new IntersectionObserver(s=>{s.forEach(l=>{if(l.isIntersecting){const i=l.target;n.unobserve(i);const{pathname:c}=i;if(!Vn.has(c)){Vn.add(c);const a=Fi(c);a&&Vi(a)}}})}),e(()=>{document.querySelectorAll("#app a").forEach(s=>{const{hostname:l,pathname:i}=new URL(s.href instanceof SVGAnimatedString?s.href.animVal:s.href,s.baseURI),c=i.match(/\.\w+$/);c&&c[0]!==".html"||s.target!=="_blank"&&l===location.hostname&&(i!==location.pathname?n.observe(s):Vn.add(i))})})};kn(o);const r=Rs();en(()=>r.path,o),An(()=>{n&&n.disconnect()})}export{vs as $,kn as A,ec as B,us as C,no as D,Ss as E,ds as F,Hr as G,Tl as H,kt as I,cc as J,Mr as K,ps as L,Ki as M,vl as N,xl as O,ic as P,zi as Q,tc as R,lc as S,Qr as T,ql as U,Ql as V,oc as W,Bi as X,Yi as Y,qi as Z,sc as _,oo as a,nc as a0,Qi as a1,vc as a2,yc as a3,gc as a4,mc as a5,Jn as a6,Oi as a7,ac as a8,Ri as a9,pc as aa,hc as ab,re as ac,rc as ad,dc as ae,Fi as af,$i as ag,Zi as b,uc as c,ke as d,Di as e,Wi as f,Hi as g,yo as h,xi as i,wi as j,Rs as k,An as l,pt as m,Xi as n,Xs as o,ml as p,en as q,At as r,fc as s,ot as t,po as u,cs as v,pr as w,Gi as x,Te as y,Ji as z}; diff --git a/assets/chunks/framework.CSeR4K32.js b/assets/chunks/framework.CSeR4K32.js new file mode 100644 index 0000000000..0f65fac1fa --- /dev/null +++ b/assets/chunks/framework.CSeR4K32.js @@ -0,0 +1,18 @@ +/** +* @vue/shared v3.5.14 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function Ms(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const ne={},Rt=[],Ue=()=>{},Oo=()=>!1,Zt=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ps=e=>e.startsWith("onUpdate:"),de=Object.assign,Is=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Mo=Object.prototype.hasOwnProperty,Q=(e,t)=>Mo.call(e,t),K=Array.isArray,Ot=e=>Pn(e)==="[object Map]",Yr=e=>Pn(e)==="[object Set]",G=e=>typeof e=="function",oe=e=>typeof e=="string",Qe=e=>typeof e=="symbol",se=e=>e!==null&&typeof e=="object",zr=e=>(se(e)||G(e))&&G(e.then)&&G(e.catch),Jr=Object.prototype.toString,Pn=e=>Jr.call(e),Po=e=>Pn(e).slice(8,-1),Qr=e=>Pn(e)==="[object Object]",Ls=e=>oe(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Mt=Ms(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),In=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Io=/-(\w)/g,Ne=In(e=>e.replace(Io,(t,n)=>n?n.toUpperCase():"")),Lo=/\B([A-Z])/g,ct=In(e=>e.replace(Lo,"-$1").toLowerCase()),Ln=In(e=>e.charAt(0).toUpperCase()+e.slice(1)),yn=In(e=>e?`on${Ln(e)}`:""),it=(e,t)=>!Object.is(e,t),Gn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},No=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Fo=e=>{const t=oe(e)?Number(e):NaN;return isNaN(t)?e:t};let sr;const Nn=()=>sr||(sr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Ns(e){if(K(e)){const t={};for(let n=0;n{if(n){const s=n.split(Do);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function Fs(e){let t="";if(oe(e))t=e;else if(K(e))for(let n=0;n!!(e&&e.__v_isRef===!0),Uo=e=>oe(e)?e:e==null?"":K(e)||se(e)&&(e.toString===Jr||!G(e.toString))?ti(e)?Uo(e.value):JSON.stringify(e,ni,2):String(e),ni=(e,t)=>ti(t)?ni(e,t.value):Ot(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[Xn(s,i)+" =>"]=r,n),{})}:Yr(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Xn(n))}:Qe(t)?Xn(t):se(t)&&!K(t)&&!Qr(t)?String(t):t,Xn=(e,t="")=>{var n;return Qe(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.5.14 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class Wo{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0&&--this._on===0&&(ve=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(kt){let t=kt;for(kt=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Vt;){let t=Vt;for(Vt=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function li(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function ci(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),$s(s),Ko(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function vs(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(ai(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function ai(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Kt)||(e.globalVersion=Kt,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!vs(e))))return;e.flags|=2;const t=e.dep,n=te,s=He;te=e,He=!0;try{li(e);const r=e.fn(e._value);(t.version===0||it(r,e._value))&&(e.flags|=128,e._value=r,t.version++)}catch(r){throw t.version++,r}finally{te=n,He=s,ci(e),e.flags&=-3}}function $s(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)$s(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function Ko(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let He=!0;const fi=[];function Xe(){fi.push(He),He=!1}function Ye(){const e=fi.pop();He=e===void 0?!0:e}function rr(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=te;te=void 0;try{t()}finally{te=n}}}let Kt=0;class qo{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Fn{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0}track(t){if(!te||!He||te===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==te)n=this.activeLink=new qo(te,this),te.deps?(n.prevDep=te.depsTail,te.depsTail.nextDep=n,te.depsTail=n):te.deps=te.depsTail=n,ui(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=te.depsTail,n.nextDep=void 0,te.depsTail.nextDep=n,te.depsTail=n,te.deps===n&&(te.deps=s)}return n}trigger(t){this.version++,Kt++,this.notify(t)}notify(t){Hs();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Ds()}}}function ui(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)ui(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const xn=new WeakMap,gt=Symbol(""),ys=Symbol(""),qt=Symbol("");function be(e,t,n){if(He&&te){let s=xn.get(e);s||xn.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new Fn),r.map=s,r.key=n),r.track()}}function Ge(e,t,n,s,r,i){const o=xn.get(e);if(!o){Kt++;return}const l=c=>{c&&c.trigger()};if(Hs(),t==="clear")o.forEach(l);else{const c=K(e),f=c&&Ls(n);if(c&&n==="length"){const a=Number(s);o.forEach((h,v)=>{(v==="length"||v===qt||!Qe(v)&&v>=a)&&l(h)})}else switch((n!==void 0||o.has(void 0))&&l(o.get(n)),f&&l(o.get(qt)),t){case"add":c?f&&l(o.get("length")):(l(o.get(gt)),Ot(e)&&l(o.get(ys)));break;case"delete":c||(l(o.get(gt)),Ot(e)&&l(o.get(ys)));break;case"set":Ot(e)&&l(o.get(gt));break}}Ds()}function Go(e,t){const n=xn.get(e);return n&&n.get(t)}function Et(e){const t=J(e);return t===e?t:(be(t,"iterate",qt),Pe(e)?t:t.map(he))}function Hn(e){return be(e=J(e),"iterate",qt),e}const Xo={__proto__:null,[Symbol.iterator](){return zn(this,Symbol.iterator,he)},concat(...e){return Et(this).concat(...e.map(t=>K(t)?Et(t):t))},entries(){return zn(this,"entries",e=>(e[1]=he(e[1]),e))},every(e,t){return Be(this,"every",e,t,void 0,arguments)},filter(e,t){return Be(this,"filter",e,t,n=>n.map(he),arguments)},find(e,t){return Be(this,"find",e,t,he,arguments)},findIndex(e,t){return Be(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Be(this,"findLast",e,t,he,arguments)},findLastIndex(e,t){return Be(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Be(this,"forEach",e,t,void 0,arguments)},includes(...e){return Jn(this,"includes",e)},indexOf(...e){return Jn(this,"indexOf",e)},join(e){return Et(this).join(e)},lastIndexOf(...e){return Jn(this,"lastIndexOf",e)},map(e,t){return Be(this,"map",e,t,void 0,arguments)},pop(){return Dt(this,"pop")},push(...e){return Dt(this,"push",e)},reduce(e,...t){return ir(this,"reduce",e,t)},reduceRight(e,...t){return ir(this,"reduceRight",e,t)},shift(){return Dt(this,"shift")},some(e,t){return Be(this,"some",e,t,void 0,arguments)},splice(...e){return Dt(this,"splice",e)},toReversed(){return Et(this).toReversed()},toSorted(e){return Et(this).toSorted(e)},toSpliced(...e){return Et(this).toSpliced(...e)},unshift(...e){return Dt(this,"unshift",e)},values(){return zn(this,"values",he)}};function zn(e,t,n){const s=Hn(e),r=s[t]();return s!==e&&!Pe(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.value&&(i.value=n(i.value)),i}),r}const Yo=Array.prototype;function Be(e,t,n,s,r,i){const o=Hn(e),l=o!==e&&!Pe(e),c=o[t];if(c!==Yo[t]){const h=c.apply(e,i);return l?he(h):h}let f=n;o!==e&&(l?f=function(h,v){return n.call(this,he(h),v,e)}:n.length>2&&(f=function(h,v){return n.call(this,h,v,e)}));const a=c.call(o,f,s);return l&&r?r(a):a}function ir(e,t,n,s){const r=Hn(e);let i=n;return r!==e&&(Pe(e)?n.length>3&&(i=function(o,l,c){return n.call(this,o,l,c,e)}):i=function(o,l,c){return n.call(this,o,he(l),c,e)}),r[t](i,...s)}function Jn(e,t,n){const s=J(e);be(s,"iterate",qt);const r=s[t](...n);return(r===-1||r===!1)&&ks(n[0])?(n[0]=J(n[0]),s[t](...n)):r}function Dt(e,t,n=[]){Xe(),Hs();const s=J(e)[t].apply(e,n);return Ds(),Ye(),s}const zo=Ms("__proto__,__v_isRef,__isVue"),di=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Qe));function Jo(e){Qe(e)||(e=String(e));const t=J(this);return be(t,"has",e),t.hasOwnProperty(e)}class hi{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?ll:vi:i?mi:gi).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=K(t);if(!r){let c;if(o&&(c=Xo[n]))return c;if(n==="hasOwnProperty")return Jo}const l=Reflect.get(t,n,ue(t)?t:s);return(Qe(n)?di.has(n):zo(n))||(r||be(t,"get",n),i)?l:ue(l)?o&&Ls(n)?l:l.value:se(l)?r?Dn(l):It(l):l}}class pi extends hi{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];if(!this._isShallow){const c=ot(i);if(!Pe(s)&&!ot(s)&&(i=J(i),s=J(s)),!K(t)&&ue(i)&&!ue(s))return c?!1:(i.value=s,!0)}const o=K(t)&&Ls(n)?Number(n)e,cn=e=>Reflect.getPrototypeOf(e);function nl(e,t,n){return function(...s){const r=this.__v_raw,i=J(r),o=Ot(i),l=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,f=r[e](...s),a=n?bs:t?En:he;return!t&&be(i,"iterate",c?ys:gt),{next(){const{value:h,done:v}=f.next();return v?{value:h,done:v}:{value:l?[a(h[0]),a(h[1])]:a(h),done:v}},[Symbol.iterator](){return this}}}}function an(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function sl(e,t){const n={get(r){const i=this.__v_raw,o=J(i),l=J(r);e||(it(r,l)&&be(o,"get",r),be(o,"get",l));const{has:c}=cn(o),f=t?bs:e?En:he;if(c.call(o,r))return f(i.get(r));if(c.call(o,l))return f(i.get(l));i!==o&&i.get(r)},get size(){const r=this.__v_raw;return!e&&be(J(r),"iterate",gt),Reflect.get(r,"size",r)},has(r){const i=this.__v_raw,o=J(i),l=J(r);return e||(it(r,l)&&be(o,"has",r),be(o,"has",l)),r===l?i.has(r):i.has(r)||i.has(l)},forEach(r,i){const o=this,l=o.__v_raw,c=J(l),f=t?bs:e?En:he;return!e&&be(c,"iterate",gt),l.forEach((a,h)=>r.call(i,f(a),f(h),o))}};return de(n,e?{add:an("add"),set:an("set"),delete:an("delete"),clear:an("clear")}:{add(r){!t&&!Pe(r)&&!ot(r)&&(r=J(r));const i=J(this);return cn(i).has.call(i,r)||(i.add(r),Ge(i,"add",r,r)),this},set(r,i){!t&&!Pe(i)&&!ot(i)&&(i=J(i));const o=J(this),{has:l,get:c}=cn(o);let f=l.call(o,r);f||(r=J(r),f=l.call(o,r));const a=c.call(o,r);return o.set(r,i),f?it(i,a)&&Ge(o,"set",r,i):Ge(o,"add",r,i),this},delete(r){const i=J(this),{has:o,get:l}=cn(i);let c=o.call(i,r);c||(r=J(r),c=o.call(i,r)),l&&l.call(i,r);const f=i.delete(r);return c&&Ge(i,"delete",r,void 0),f},clear(){const r=J(this),i=r.size!==0,o=r.clear();return i&&Ge(r,"clear",void 0,void 0),o}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=nl(r,e,t)}),n}function js(e,t){const n=sl(e,t);return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(Q(n,r)&&r in s?n:s,r,i)}const rl={get:js(!1,!1)},il={get:js(!1,!0)},ol={get:js(!0,!1)};const gi=new WeakMap,mi=new WeakMap,vi=new WeakMap,ll=new WeakMap;function cl(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function al(e){return e.__v_skip||!Object.isExtensible(e)?0:cl(Po(e))}function It(e){return ot(e)?e:Vs(e,!1,Zo,rl,gi)}function fl(e){return Vs(e,!1,tl,il,mi)}function Dn(e){return Vs(e,!0,el,ol,vi)}function Vs(e,t,n,s,r){if(!se(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=al(e);if(i===0)return e;const o=r.get(e);if(o)return o;const l=new Proxy(e,i===2?s:n);return r.set(e,l),l}function mt(e){return ot(e)?mt(e.__v_raw):!!(e&&e.__v_isReactive)}function ot(e){return!!(e&&e.__v_isReadonly)}function Pe(e){return!!(e&&e.__v_isShallow)}function ks(e){return e?!!e.__v_raw:!1}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function bn(e){return!Q(e,"__v_skip")&&Object.isExtensible(e)&&Zr(e,"__v_skip",!0),e}const he=e=>se(e)?It(e):e,En=e=>se(e)?Dn(e):e;function ue(e){return e?e.__v_isRef===!0:!1}function We(e){return yi(e,!1)}function Ie(e){return yi(e,!0)}function yi(e,t){return ue(e)?e:new ul(e,t)}class ul{constructor(t,n){this.dep=new Fn,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:J(t),this._value=n?t:he(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Pe(t)||ot(t);t=s?t:J(t),it(t,n)&&(this._rawValue=t,this._value=s?t:he(t),this.dep.trigger())}}function Us(e){return ue(e)?e.value:e}function le(e){return G(e)?e():Us(e)}const dl={get:(e,t,n)=>t==="__v_raw"?e:Us(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ue(r)&&!ue(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function bi(e){return mt(e)?e:new Proxy(e,dl)}class hl{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new Fn,{get:s,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function pl(e){return new hl(e)}class gl{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0}get value(){const t=this._object[this._key];return this._value=t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Go(J(this._object),this._key)}}class ml{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function vl(e,t,n){return ue(e)?e:G(e)?new ml(e):se(e)&&arguments.length>1?yl(e,t,n):We(e)}function yl(e,t,n){const s=e[t];return ue(s)?s:new gl(e,t,n)}class bl{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Fn(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Kt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&te!==this)return oi(this,!0),!0}get value(){const t=this.dep.track();return ai(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function _l(e,t,n=!1){let s,r;return G(e)?s=e:(s=e.get,r=e.set),new bl(s,r,n)}const fn={},Tn=new WeakMap;let ht;function wl(e,t=!1,n=ht){if(n){let s=Tn.get(n);s||Tn.set(n,s=[]),s.push(e)}}function Sl(e,t,n=ne){const{immediate:s,deep:r,once:i,scheduler:o,augmentJob:l,call:c}=n,f=g=>r?g:Pe(g)||r===!1||r===0?rt(g,1):rt(g);let a,h,v,y,x=!1,_=!1;if(ue(e)?(h=()=>e.value,x=Pe(e)):mt(e)?(h=()=>f(e),x=!0):K(e)?(_=!0,x=e.some(g=>mt(g)||Pe(g)),h=()=>e.map(g=>{if(ue(g))return g.value;if(mt(g))return f(g);if(G(g))return c?c(g,2):g()})):G(e)?t?h=c?()=>c(e,2):e:h=()=>{if(v){Xe();try{v()}finally{Ye()}}const g=ht;ht=a;try{return c?c(e,3,[y]):e(y)}finally{ht=g}}:h=Ue,t&&r){const g=h,P=r===!0?1/0:r;h=()=>rt(g(),P)}const V=si(),L=()=>{a.stop(),V&&V.active&&Is(V.effects,a)};if(i&&t){const g=t;t=(...P)=>{g(...P),L()}}let D=_?new Array(e.length).fill(fn):fn;const p=g=>{if(!(!(a.flags&1)||!a.dirty&&!g))if(t){const P=a.run();if(r||x||(_?P.some((U,O)=>it(U,D[O])):it(P,D))){v&&v();const U=ht;ht=a;try{const O=[P,D===fn?void 0:_&&D[0]===fn?[]:D,y];c?c(t,3,O):t(...O),D=P}finally{ht=U}}}else a.run()};return l&&l(p),a=new ri(h),a.scheduler=o?()=>o(p,!1):p,y=g=>wl(g,!1,a),v=a.onStop=()=>{const g=Tn.get(a);if(g){if(c)c(g,4);else for(const P of g)P();Tn.delete(a)}},t?s?p(!0):D=a.run():o?o(p.bind(null,!0),!0):a.run(),L.pause=a.pause.bind(a),L.resume=a.resume.bind(a),L.stop=L,L}function rt(e,t=1/0,n){if(t<=0||!se(e)||e.__v_skip||(n=n||new Set,n.has(e)))return e;if(n.add(e),t--,ue(e))rt(e.value,t,n);else if(K(e))for(let s=0;s{rt(s,t,n)});else if(Qr(e)){for(const s in e)rt(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&rt(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.14 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function en(e,t,n,s){try{return s?e(...s):e()}catch(r){tn(r,t,n)}}function De(e,t,n,s){if(G(e)){const r=en(e,t,n,s);return r&&zr(r)&&r.catch(i=>{tn(i,t,n)}),r}if(K(e)){const r=[];for(let i=0;i>>1,r=we[s],i=Gt(r);i=Gt(n)?we.push(e):we.splice(El(t),0,e),e.flags|=1,wi()}}function wi(){Cn||(Cn=_i.then(Si))}function Tl(e){K(e)?Pt.push(...e):tt&&e.id===-1?tt.splice(Ct+1,0,e):e.flags&1||(Pt.push(e),e.flags|=1),wi()}function or(e,t,n=Ve+1){for(;nGt(n)-Gt(s));if(Pt.length=0,tt){tt.push(...t);return}for(tt=t,Ct=0;Cte.id==null?e.flags&2?-1:1/0:e.id;function Si(e){try{for(Ve=0;Ve{s._d&&yr(-1);const i=Rn(t);let o;try{o=e(...r)}finally{Rn(i),s._d&&yr(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function ke(e,t,n,s){const r=e.dirs,i=t&&t.dirs;for(let o=0;oe.__isTeleport,nt=Symbol("_leaveCb"),un=Symbol("_enterCb");function Rl(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Nt(()=>{e.isMounted=!0}),Pi(()=>{e.isUnmounting=!0}),e}const Re=[Function,Array],Ti={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Re,onEnter:Re,onAfterEnter:Re,onEnterCancelled:Re,onBeforeLeave:Re,onLeave:Re,onAfterLeave:Re,onLeaveCancelled:Re,onBeforeAppear:Re,onAppear:Re,onAfterAppear:Re,onAppearCancelled:Re},Ci=e=>{const t=e.subTree;return t.component?Ci(t.component):t},Ol={name:"BaseTransition",props:Ti,setup(e,{slots:t}){const n=sn(),s=Rl();return()=>{const r=t.default&&Oi(t.default(),!0);if(!r||!r.length)return;const i=Ai(r),o=J(e),{mode:l}=o;if(s.isLeaving)return Qn(i);const c=lr(i);if(!c)return Qn(i);let f=_s(c,o,s,n,h=>f=h);c.type!==pe&&Xt(c,f);let a=n.subTree&&lr(n.subTree);if(a&&a.type!==pe&&!pt(c,a)&&Ci(n).type!==pe){let h=_s(a,o,s,n);if(Xt(a,h),l==="out-in"&&c.type!==pe)return s.isLeaving=!0,h.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete h.afterLeave,a=void 0},Qn(i);l==="in-out"&&c.type!==pe?h.delayLeave=(v,y,x)=>{const _=Ri(s,a);_[String(a.key)]=a,v[nt]=()=>{y(),v[nt]=void 0,delete f.delayedLeave,a=void 0},f.delayedLeave=()=>{x(),delete f.delayedLeave,a=void 0}}:a=void 0}else a&&(a=void 0);return i}}};function Ai(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==pe){t=n;break}}return t}const Ml=Ol;function Ri(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function _s(e,t,n,s,r){const{appear:i,mode:o,persisted:l=!1,onBeforeEnter:c,onEnter:f,onAfterEnter:a,onEnterCancelled:h,onBeforeLeave:v,onLeave:y,onAfterLeave:x,onLeaveCancelled:_,onBeforeAppear:V,onAppear:L,onAfterAppear:D,onAppearCancelled:p}=t,g=String(e.key),P=Ri(n,e),U=(C,I)=>{C&&De(C,s,9,I)},O=(C,I)=>{const A=I[1];U(C,I),K(C)?C.every(b=>b.length<=1)&&A():C.length<=1&&A()},B={mode:o,persisted:l,beforeEnter(C){let I=c;if(!n.isMounted)if(i)I=V||c;else return;C[nt]&&C[nt](!0);const A=P[g];A&&pt(e,A)&&A.el[nt]&&A.el[nt](),U(I,[C])},enter(C){let I=f,A=a,b=h;if(!n.isMounted)if(i)I=L||f,A=D||a,b=p||h;else return;let F=!1;const Y=C[un]=re=>{F||(F=!0,re?U(b,[C]):U(A,[C]),B.delayedLeave&&B.delayedLeave(),C[un]=void 0)};I?O(I,[C,Y]):Y()},leave(C,I){const A=String(e.key);if(C[un]&&C[un](!0),n.isUnmounting)return I();U(v,[C]);let b=!1;const F=C[nt]=Y=>{b||(b=!0,I(),Y?U(_,[C]):U(x,[C]),C[nt]=void 0,P[A]===e&&delete P[A])};P[A]=e,y?O(y,[C,F]):F()},clone(C){const I=_s(C,t,n,s,r);return r&&r(I),I}};return B}function Qn(e){if(nn(e))return e=lt(e),e.children=null,e}function lr(e){if(!nn(e))return Ei(e.type)&&e.children?Ai(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&G(n.default))return n.default()}}function Xt(e,t){e.shapeFlag&6&&e.component?(e.transition=t,Xt(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Oi(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;iYt(x,t&&(K(t)?t[_]:t),n,s,r));return}if(vt(s)&&!r){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Yt(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?Ys(s.component):s.el,o=r?null:i,{i:l,r:c}=e,f=t&&t.r,a=l.refs===ne?l.refs={}:l.refs,h=l.setupState,v=J(h),y=h===ne?()=>!1:x=>Q(v,x);if(f!=null&&f!==c&&(oe(f)?(a[f]=null,y(f)&&(h[f]=null)):ue(f)&&(f.value=null)),G(c))en(c,l,12,[o,a]);else{const x=oe(c),_=ue(c);if(x||_){const V=()=>{if(e.f){const L=x?y(c)?h[c]:a[c]:c.value;r?K(L)&&Is(L,i):K(L)?L.includes(i)||L.push(i):x?(a[c]=[i],y(c)&&(h[c]=a[c])):(c.value=[i],e.k&&(a[e.k]=c.value))}else x?(a[c]=o,y(c)&&(h[c]=o)):_&&(c.value=o,e.k&&(a[e.k]=o))};o?(V.id=-1,Ce(V,n)):V()}}}let cr=!1;const Tt=()=>{cr||(console.error("Hydration completed but contains mismatches."),cr=!0)},Pl=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",Il=e=>e.namespaceURI.includes("MathML"),dn=e=>{if(e.nodeType===1){if(Pl(e))return"svg";if(Il(e))return"mathml"}},At=e=>e.nodeType===8;function Ll(e){const{mt:t,p:n,o:{patchProp:s,createText:r,nextSibling:i,parentNode:o,remove:l,insert:c,createComment:f}}=e,a=(p,g)=>{if(!g.hasChildNodes()){n(null,p,g),An(),g._vnode=p;return}h(g.firstChild,p,null,null,null),An(),g._vnode=p},h=(p,g,P,U,O,B=!1)=>{B=B||!!g.dynamicChildren;const C=At(p)&&p.data==="[",I=()=>_(p,g,P,U,O,C),{type:A,ref:b,shapeFlag:F,patchFlag:Y}=g;let re=p.nodeType;g.el=p,Y===-2&&(B=!1,g.dynamicChildren=null);let k=null;switch(A){case _t:re!==3?g.children===""?(c(g.el=r(""),o(p),p),k=p):k=I():(p.data!==g.children&&(Tt(),p.data=g.children),k=i(p));break;case pe:D(p)?(k=i(p),L(g.el=p.content.firstChild,p,P)):re!==8||C?k=I():k=i(p);break;case Wt:if(C&&(p=i(p),re=p.nodeType),re===1||re===3){k=p;const X=!g.children.length;for(let $=0;${B=B||!!g.dynamicChildren;const{type:C,props:I,patchFlag:A,shapeFlag:b,dirs:F,transition:Y}=g,re=C==="input"||C==="option";if(re||A!==-1){F&&ke(g,null,P,"created");let k=!1;if(D(p)){k=Xi(null,Y)&&P&&P.vnode.props&&P.vnode.props.appear;const $=p.content.firstChild;k&&Y.beforeEnter($),L($,p,P),g.el=p=$}if(b&16&&!(I&&(I.innerHTML||I.textContent))){let $=y(p.firstChild,g,p,P,U,O,B);for(;$;){hn(p,1)||Tt();const ae=$;$=$.nextSibling,l(ae)}}else if(b&8){let $=g.children;$[0]===` +`&&(p.tagName==="PRE"||p.tagName==="TEXTAREA")&&($=$.slice(1)),p.textContent!==$&&(hn(p,0)||Tt(),p.textContent=g.children)}if(I){if(re||!B||A&48){const $=p.tagName.includes("-");for(const ae in I)(re&&(ae.endsWith("value")||ae==="indeterminate")||Zt(ae)&&!Mt(ae)||ae[0]==="."||$)&&s(p,ae,null,I[ae],void 0,P)}else if(I.onClick)s(p,"onClick",null,I.onClick,void 0,P);else if(A&4&&mt(I.style))for(const $ in I.style)I.style[$]}let X;(X=I&&I.onVnodeBeforeMount)&&Oe(X,P,g),F&&ke(g,null,P,"beforeMount"),((X=I&&I.onVnodeMounted)||F||k)&&no(()=>{X&&Oe(X,P,g),k&&Y.enter(p),F&&ke(g,null,P,"mounted")},U)}return p.nextSibling},y=(p,g,P,U,O,B,C)=>{C=C||!!g.dynamicChildren;const I=g.children,A=I.length;for(let b=0;b{const{slotScopeIds:C}=g;C&&(O=O?O.concat(C):C);const I=o(p),A=y(i(p),g,I,P,U,O,B);return A&&At(A)&&A.data==="]"?i(g.anchor=A):(Tt(),c(g.anchor=f("]"),I,A),A)},_=(p,g,P,U,O,B)=>{if(hn(p.parentElement,1)||Tt(),g.el=null,B){const A=V(p);for(;;){const b=i(p);if(b&&b!==A)l(b);else break}}const C=i(p),I=o(p);return l(p),n(null,g,I,C,P,U,dn(I),O),P&&(P.vnode.el=g.el,eo(P,g.el)),C},V=(p,g="[",P="]")=>{let U=0;for(;p;)if(p=i(p),p&&At(p)&&(p.data===g&&U++,p.data===P)){if(U===0)return i(p);U--}return p},L=(p,g,P)=>{const U=g.parentNode;U&&U.replaceChild(p,g);let O=P;for(;O;)O.vnode.el===g&&(O.vnode.el=O.subTree.el=p),O=O.parent},D=p=>p.nodeType===1&&p.tagName==="TEMPLATE";return[a,h]}const ar="data-allow-mismatch",Nl={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function hn(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(ar);)e=e.parentElement;const n=e&&e.getAttribute(ar);if(n==null)return!1;if(n==="")return!0;{const s=n.split(",");return t===0&&s.includes("children")?!0:n.split(",").includes(Nl[t])}}Nn().requestIdleCallback;Nn().cancelIdleCallback;function Fl(e,t){if(At(e)&&e.data==="["){let n=1,s=e.nextSibling;for(;s;){if(s.nodeType===1){if(t(s)===!1)break}else if(At(s))if(s.data==="]"){if(--n===0)break}else s.data==="["&&n++;s=s.nextSibling}}else t(e)}const vt=e=>!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function gf(e){G(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:s,delay:r=200,hydrate:i,timeout:o,suspensible:l=!0,onError:c}=e;let f=null,a,h=0;const v=()=>(h++,f=null,y()),y=()=>{let x;return f||(x=f=t().catch(_=>{if(_=_ instanceof Error?_:new Error(String(_)),c)return new Promise((V,L)=>{c(_,()=>V(v()),()=>L(_),h+1)});throw _}).then(_=>x!==f&&f?f:(_&&(_.__esModule||_[Symbol.toStringTag]==="Module")&&(_=_.default),a=_,_)))};return Bs({name:"AsyncComponentWrapper",__asyncLoader:y,__asyncHydrate(x,_,V){const L=i?()=>{const D=i(V,p=>Fl(x,p));D&&(_.bum||(_.bum=[])).push(D)}:V;a?L():y().then(()=>!_.isUnmounted&&L())},get __asyncResolved(){return a},setup(){const x=fe;if(Ks(x),a)return()=>Zn(a,x);const _=p=>{f=null,tn(p,x,13,!s)};if(l&&x.suspense||Lt)return y().then(p=>()=>Zn(p,x)).catch(p=>(_(p),()=>s?ce(s,{error:p}):null));const V=We(!1),L=We(),D=We(!!r);return r&&setTimeout(()=>{D.value=!1},r),o!=null&&setTimeout(()=>{if(!V.value&&!L.value){const p=new Error(`Async component timed out after ${o}ms.`);_(p),L.value=p}},o),y().then(()=>{V.value=!0,x.parent&&nn(x.parent.vnode)&&x.parent.update()}).catch(p=>{_(p),L.value=p}),()=>{if(V.value&&a)return Zn(a,x);if(L.value&&s)return ce(s,{error:L.value});if(n&&!D.value)return ce(n)}}})}function Zn(e,t){const{ref:n,props:s,children:r,ce:i}=t.vnode,o=ce(e,s,r);return o.ref=n,o.ce=i,delete t.vnode.ce,o}const nn=e=>e.type.__isKeepAlive;function Hl(e,t){Mi(e,"a",t)}function Dl(e,t){Mi(e,"da",t)}function Mi(e,t,n=fe){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(jn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)nn(r.parent.vnode)&&$l(s,t,n,r),r=r.parent}}function $l(e,t,n,s){const r=jn(t,e,s,!0);Vn(()=>{Is(s[t],r)},n)}function jn(e,t,n=fe,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{Xe();const l=rn(n),c=De(t,n,e,o);return l(),Ye(),c});return s?r.unshift(i):r.push(i),i}}const Ze=e=>(t,n=fe)=>{(!Lt||e==="sp")&&jn(e,(...s)=>t(...s),n)},jl=Ze("bm"),Nt=Ze("m"),Vl=Ze("bu"),kl=Ze("u"),Pi=Ze("bum"),Vn=Ze("um"),Ul=Ze("sp"),Wl=Ze("rtg"),Bl=Ze("rtc");function Kl(e,t=fe){jn("ec",e,t)}const Ii="components";function mf(e,t){return Ni(Ii,e,!0,t)||e}const Li=Symbol.for("v-ndc");function vf(e){return oe(e)?Ni(Ii,e,!1)||e:e||Li}function Ni(e,t,n=!0,s=!1){const r=ge||fe;if(r){const i=r.type;{const l=Oc(i,!1);if(l&&(l===t||l===Ne(t)||l===Ln(Ne(t))))return i}const o=fr(r[e]||i[e],t)||fr(r.appContext[e],t);return!o&&s?i:o}}function fr(e,t){return e&&(e[t]||e[Ne(t)]||e[Ln(Ne(t))])}function yf(e,t,n,s){let r;const i=n,o=K(e);if(o||oe(e)){const l=o&&mt(e);let c=!1,f=!1;l&&(c=!Pe(e),f=ot(e),e=Hn(e)),r=new Array(e.length);for(let a=0,h=e.length;at(l,c,void 0,i));else{const l=Object.keys(e);r=new Array(l.length);for(let c=0,f=l.length;cJt(t)?!(t.type===pe||t.type===Se&&!Fi(t.children)):!0)?e:null}function _f(e,t){const n={};for(const s in e)n[/[A-Z]/.test(s)?`on:${s}`:yn(s)]=e[s];return n}const ws=e=>e?lo(e)?Ys(e):ws(e.parent):null,Ut=de(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>ws(e.parent),$root:e=>ws(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Di(e),$forceUpdate:e=>e.f||(e.f=()=>{Ws(e.update)}),$nextTick:e=>e.n||(e.n=$n.bind(e.proxy)),$watch:e=>hc.bind(e)}),es=(e,t)=>e!==ne&&!e.__isScriptSetup&&Q(e,t),ql={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:c}=e;let f;if(t[0]!=="$"){const y=o[t];if(y!==void 0)switch(y){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(es(s,t))return o[t]=1,s[t];if(r!==ne&&Q(r,t))return o[t]=2,r[t];if((f=e.propsOptions[0])&&Q(f,t))return o[t]=3,i[t];if(n!==ne&&Q(n,t))return o[t]=4,n[t];Ss&&(o[t]=0)}}const a=Ut[t];let h,v;if(a)return t==="$attrs"&&be(e.attrs,"get",""),a(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==ne&&Q(n,t))return o[t]=4,n[t];if(v=c.config.globalProperties,Q(v,t))return v[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return es(r,t)?(r[t]=n,!0):s!==ne&&Q(s,t)?(s[t]=n,!0):Q(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},o){let l;return!!n[o]||e!==ne&&Q(e,o)||es(t,o)||(l=i[0])&&Q(l,o)||Q(s,o)||Q(Ut,o)||Q(r.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Q(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function wf(){return Gl().slots}function Gl(){const e=sn();return e.setupContext||(e.setupContext=ao(e))}function ur(e){return K(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Ss=!0;function Xl(e){const t=Di(e),n=e.proxy,s=e.ctx;Ss=!1,t.beforeCreate&&dr(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:c,inject:f,created:a,beforeMount:h,mounted:v,beforeUpdate:y,updated:x,activated:_,deactivated:V,beforeDestroy:L,beforeUnmount:D,destroyed:p,unmounted:g,render:P,renderTracked:U,renderTriggered:O,errorCaptured:B,serverPrefetch:C,expose:I,inheritAttrs:A,components:b,directives:F,filters:Y}=t;if(f&&Yl(f,s,null),o)for(const X in o){const $=o[X];G($)&&(s[X]=$.bind(n))}if(r){const X=r.call(n,n);se(X)&&(e.data=It(X))}if(Ss=!0,i)for(const X in i){const $=i[X],ae=G($)?$.bind(n,n):G($.get)?$.get.bind(n,n):Ue,on=!G($)&&G($.set)?$.set.bind(n):Ue,at=ie({get:ae,set:on});Object.defineProperty(s,X,{enumerable:!0,configurable:!0,get:()=>at.value,set:$e=>at.value=$e})}if(l)for(const X in l)Hi(l[X],s,n,X);if(c){const X=G(c)?c.call(n):c;Reflect.ownKeys(X).forEach($=>{tc($,X[$])})}a&&dr(a,e,"c");function k(X,$){K($)?$.forEach(ae=>X(ae.bind(n))):$&&X($.bind(n))}if(k(jl,h),k(Nt,v),k(Vl,y),k(kl,x),k(Hl,_),k(Dl,V),k(Kl,B),k(Bl,U),k(Wl,O),k(Pi,D),k(Vn,g),k(Ul,C),K(I))if(I.length){const X=e.exposed||(e.exposed={});I.forEach($=>{Object.defineProperty(X,$,{get:()=>n[$],set:ae=>n[$]=ae})})}else e.exposed||(e.exposed={});P&&e.render===Ue&&(e.render=P),A!=null&&(e.inheritAttrs=A),b&&(e.components=b),F&&(e.directives=F),C&&Ks(e)}function Yl(e,t,n=Ue){K(e)&&(e=xs(e));for(const s in e){const r=e[s];let i;se(r)?"default"in r?i=bt(r.from||s,r.default,!0):i=bt(r.from||s):i=bt(r),ue(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function dr(e,t,n){De(K(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Hi(e,t,n,s){let r=s.includes(".")?Qi(n,s):()=>n[s];if(oe(e)){const i=t[e];G(i)&&Le(r,i)}else if(G(e))Le(r,e.bind(n));else if(se(e))if(K(e))e.forEach(i=>Hi(i,t,n,s));else{const i=G(e.handler)?e.handler.bind(n):t[e.handler];G(i)&&Le(r,i,e)}}function Di(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let c;return l?c=l:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(f=>On(c,f,o,!0)),On(c,t,o)),se(t)&&i.set(t,c),c}function On(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&On(e,i,n,!0),r&&r.forEach(o=>On(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=zl[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const zl={data:hr,props:pr,emits:pr,methods:jt,computed:jt,beforeCreate:_e,created:_e,beforeMount:_e,mounted:_e,beforeUpdate:_e,updated:_e,beforeDestroy:_e,beforeUnmount:_e,destroyed:_e,unmounted:_e,activated:_e,deactivated:_e,errorCaptured:_e,serverPrefetch:_e,components:jt,directives:jt,watch:Ql,provide:hr,inject:Jl};function hr(e,t){return t?e?function(){return de(G(e)?e.call(this,this):e,G(t)?t.call(this,this):t)}:t:e}function Jl(e,t){return jt(xs(e),xs(t))}function xs(e){if(K(e)){const t={};for(let n=0;n1)return n&&G(t)?t.call(s&&s.proxy):t}}function ji(){return!!(fe||ge||yt)}const Vi={},ki=()=>Object.create(Vi),Ui=e=>Object.getPrototypeOf(e)===Vi;function nc(e,t,n,s=!1){const r={},i=ki();e.propsDefaults=Object.create(null),Wi(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:fl(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function sc(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=J(r),[c]=e.propsOptions;let f=!1;if((s||o>0)&&!(o&16)){if(o&8){const a=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[v,y]=Bi(h,t,!0);de(o,v),y&&l.push(...y)};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}if(!i&&!c)return se(e)&&s.set(e,Rt),Rt;if(K(i))for(let a=0;ae[0]==="_"||e==="$stable",Gs=e=>K(e)?e.map(Me):[Me(e)],ic=(e,t,n)=>{if(t._n)return t;const s=Cl((...r)=>Gs(t(...r)),n);return s._c=!1,s},Ki=(e,t,n)=>{const s=e._ctx;for(const r in e){if(qs(r))continue;const i=e[r];if(G(i))t[r]=ic(r,i,s);else if(i!=null){const o=Gs(i);t[r]=()=>o}}},qi=(e,t)=>{const n=Gs(t);e.slots.default=()=>n},Gi=(e,t,n)=>{for(const s in t)(n||!qs(s))&&(e[s]=t[s])},oc=(e,t,n)=>{const s=e.slots=ki();if(e.vnode.shapeFlag&32){const r=t._;r?(Gi(s,t,n),n&&Zr(s,"_",r,!0)):Ki(t,s)}else t&&qi(e,t)},lc=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=ne;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:Gi(r,t,n):(i=!t.$stable,Ki(t,r)),o=t}else t&&(qi(e,t),o={default:1});if(i)for(const l in r)!qs(l)&&o[l]==null&&delete r[l]},Ce=no;function cc(e){return ac(e,Ll)}function ac(e,t){const n=Nn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:f,setElementText:a,parentNode:h,nextSibling:v,setScopeId:y=Ue,insertStaticContent:x}=e,_=(u,d,m,E=null,w=null,S=null,N=void 0,M=null,R=!!d.dynamicChildren)=>{if(u===d)return;u&&!pt(u,d)&&(E=ln(u),$e(u,w,S,!0),u=null),d.patchFlag===-2&&(R=!1,d.dynamicChildren=null);const{type:T,ref:W,shapeFlag:H}=d;switch(T){case _t:V(u,d,m,E);break;case pe:L(u,d,m,E);break;case Wt:u==null&&D(d,m,E,N);break;case Se:b(u,d,m,E,w,S,N,M,R);break;default:H&1?P(u,d,m,E,w,S,N,M,R):H&6?F(u,d,m,E,w,S,N,M,R):(H&64||H&128)&&T.process(u,d,m,E,w,S,N,M,R,xt)}W!=null&&w&&Yt(W,u&&u.ref,S,d||u,!d)},V=(u,d,m,E)=>{if(u==null)s(d.el=l(d.children),m,E);else{const w=d.el=u.el;d.children!==u.children&&f(w,d.children)}},L=(u,d,m,E)=>{u==null?s(d.el=c(d.children||""),m,E):d.el=u.el},D=(u,d,m,E)=>{[u.el,u.anchor]=x(u.children,d,m,E,u.el,u.anchor)},p=({el:u,anchor:d},m,E)=>{let w;for(;u&&u!==d;)w=v(u),s(u,m,E),u=w;s(d,m,E)},g=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=v(u),r(u),u=m;r(d)},P=(u,d,m,E,w,S,N,M,R)=>{d.type==="svg"?N="svg":d.type==="math"&&(N="mathml"),u==null?U(d,m,E,w,S,N,M,R):C(u,d,w,S,N,M,R)},U=(u,d,m,E,w,S,N,M)=>{let R,T;const{props:W,shapeFlag:H,transition:j,dirs:q}=u;if(R=u.el=o(u.type,S,W&&W.is,W),H&8?a(R,u.children):H&16&&B(u.children,R,null,E,w,ts(u,S),N,M),q&&ke(u,null,E,"created"),O(R,u,u.scopeId,N,E),W){for(const ee in W)ee!=="value"&&!Mt(ee)&&i(R,ee,null,W[ee],S,E);"value"in W&&i(R,"value",null,W.value,S),(T=W.onVnodeBeforeMount)&&Oe(T,E,u)}q&&ke(u,null,E,"beforeMount");const z=Xi(w,j);z&&j.beforeEnter(R),s(R,d,m),((T=W&&W.onVnodeMounted)||z||q)&&Ce(()=>{T&&Oe(T,E,u),z&&j.enter(R),q&&ke(u,null,E,"mounted")},w)},O=(u,d,m,E,w)=>{if(m&&y(u,m),E)for(let S=0;S{for(let T=R;T{const M=d.el=u.el;let{patchFlag:R,dynamicChildren:T,dirs:W}=d;R|=u.patchFlag&16;const H=u.props||ne,j=d.props||ne;let q;if(m&&ft(m,!1),(q=j.onVnodeBeforeUpdate)&&Oe(q,m,d,u),W&&ke(d,u,m,"beforeUpdate"),m&&ft(m,!0),(H.innerHTML&&j.innerHTML==null||H.textContent&&j.textContent==null)&&a(M,""),T?I(u.dynamicChildren,T,M,m,E,ts(d,w),S):N||$(u,d,M,null,m,E,ts(d,w),S,!1),R>0){if(R&16)A(M,H,j,m,w);else if(R&2&&H.class!==j.class&&i(M,"class",null,j.class,w),R&4&&i(M,"style",H.style,j.style,w),R&8){const z=d.dynamicProps;for(let ee=0;ee{q&&Oe(q,m,d,u),W&&ke(d,u,m,"updated")},E)},I=(u,d,m,E,w,S,N)=>{for(let M=0;M{if(d!==m){if(d!==ne)for(const S in d)!Mt(S)&&!(S in m)&&i(u,S,d[S],null,w,E);for(const S in m){if(Mt(S))continue;const N=m[S],M=d[S];N!==M&&S!=="value"&&i(u,S,M,N,w,E)}"value"in m&&i(u,"value",d.value,m.value,w)}},b=(u,d,m,E,w,S,N,M,R)=>{const T=d.el=u?u.el:l(""),W=d.anchor=u?u.anchor:l("");let{patchFlag:H,dynamicChildren:j,slotScopeIds:q}=d;q&&(M=M?M.concat(q):q),u==null?(s(T,m,E),s(W,m,E),B(d.children||[],m,W,w,S,N,M,R)):H>0&&H&64&&j&&u.dynamicChildren?(I(u.dynamicChildren,j,m,w,S,N,M),(d.key!=null||w&&d===w.subTree)&&Yi(u,d,!0)):$(u,d,m,W,w,S,N,M,R)},F=(u,d,m,E,w,S,N,M,R)=>{d.slotScopeIds=M,u==null?d.shapeFlag&512?w.ctx.activate(d,m,E,N,R):Y(d,m,E,w,S,N,R):re(u,d,R)},Y=(u,d,m,E,w,S,N)=>{const M=u.component=Tc(u,E,w);if(nn(u)&&(M.ctx.renderer=xt),Cc(M,!1,N),M.asyncDep){if(w&&w.registerDep(M,k,N),!u.el){const R=M.subTree=ce(pe);L(null,R,d,m)}}else k(M,u,d,m,w,S,N)},re=(u,d,m)=>{const E=d.component=u.component;if(yc(u,d,m))if(E.asyncDep&&!E.asyncResolved){X(E,d,m);return}else E.next=d,E.update();else d.el=u.el,E.vnode=d},k=(u,d,m,E,w,S,N)=>{const M=()=>{if(u.isMounted){let{next:H,bu:j,u:q,parent:z,vnode:ee}=u;{const Ee=zi(u);if(Ee){H&&(H.el=ee.el,X(u,H,N)),Ee.asyncDep.then(()=>{u.isUnmounted||M()});return}}let Z=H,xe;ft(u,!1),H?(H.el=ee.el,X(u,H,N)):H=ee,j&&Gn(j),(xe=H.props&&H.props.onVnodeBeforeUpdate)&&Oe(xe,z,H,ee),ft(u,!0);const me=ns(u),Fe=u.subTree;u.subTree=me,_(Fe,me,h(Fe.el),ln(Fe),u,w,S),H.el=me.el,Z===null&&eo(u,me.el),q&&Ce(q,w),(xe=H.props&&H.props.onVnodeUpdated)&&Ce(()=>Oe(xe,z,H,ee),w)}else{let H;const{el:j,props:q}=d,{bm:z,m:ee,parent:Z,root:xe,type:me}=u,Fe=vt(d);if(ft(u,!1),z&&Gn(z),!Fe&&(H=q&&q.onVnodeBeforeMount)&&Oe(H,Z,d),ft(u,!0),j&&qn){const Ee=()=>{u.subTree=ns(u),qn(j,u.subTree,u,w,null)};Fe&&me.__asyncHydrate?me.__asyncHydrate(j,u,Ee):Ee()}else{xe.ce&&xe.ce._injectChildStyle(me);const Ee=u.subTree=ns(u);_(null,Ee,m,E,u,w,S),d.el=Ee.el}if(ee&&Ce(ee,w),!Fe&&(H=q&&q.onVnodeMounted)){const Ee=d;Ce(()=>Oe(H,Z,Ee),w)}(d.shapeFlag&256||Z&&vt(Z.vnode)&&Z.vnode.shapeFlag&256)&&u.a&&Ce(u.a,w),u.isMounted=!0,d=m=E=null}};u.scope.on();const R=u.effect=new ri(M);u.scope.off();const T=u.update=R.run.bind(R),W=u.job=R.runIfDirty.bind(R);W.i=u,W.id=u.uid,R.scheduler=()=>Ws(W),ft(u,!0),T()},X=(u,d,m)=>{d.component=u;const E=u.vnode.props;u.vnode=d,u.next=null,sc(u,d.props,E,m),lc(u,d.children,m),Xe(),or(u),Ye()},$=(u,d,m,E,w,S,N,M,R=!1)=>{const T=u&&u.children,W=u?u.shapeFlag:0,H=d.children,{patchFlag:j,shapeFlag:q}=d;if(j>0){if(j&128){on(T,H,m,E,w,S,N,M,R);return}else if(j&256){ae(T,H,m,E,w,S,N,M,R);return}}q&8?(W&16&&Ft(T,w,S),H!==T&&a(m,H)):W&16?q&16?on(T,H,m,E,w,S,N,M,R):Ft(T,w,S,!0):(W&8&&a(m,""),q&16&&B(H,m,E,w,S,N,M,R))},ae=(u,d,m,E,w,S,N,M,R)=>{u=u||Rt,d=d||Rt;const T=u.length,W=d.length,H=Math.min(T,W);let j;for(j=0;jW?Ft(u,w,S,!0,!1,H):B(d,m,E,w,S,N,M,R,H)},on=(u,d,m,E,w,S,N,M,R)=>{let T=0;const W=d.length;let H=u.length-1,j=W-1;for(;T<=H&&T<=j;){const q=u[T],z=d[T]=R?st(d[T]):Me(d[T]);if(pt(q,z))_(q,z,m,null,w,S,N,M,R);else break;T++}for(;T<=H&&T<=j;){const q=u[H],z=d[j]=R?st(d[j]):Me(d[j]);if(pt(q,z))_(q,z,m,null,w,S,N,M,R);else break;H--,j--}if(T>H){if(T<=j){const q=j+1,z=qj)for(;T<=H;)$e(u[T],w,S,!0),T++;else{const q=T,z=T,ee=new Map;for(T=z;T<=j;T++){const Te=d[T]=R?st(d[T]):Me(d[T]);Te.key!=null&&ee.set(Te.key,T)}let Z,xe=0;const me=j-z+1;let Fe=!1,Ee=0;const Ht=new Array(me);for(T=0;T=me){$e(Te,w,S,!0);continue}let je;if(Te.key!=null)je=ee.get(Te.key);else for(Z=z;Z<=j;Z++)if(Ht[Z-z]===0&&pt(Te,d[Z])){je=Z;break}je===void 0?$e(Te,w,S,!0):(Ht[je-z]=T+1,je>=Ee?Ee=je:Fe=!0,_(Te,d[je],m,null,w,S,N,M,R),xe++)}const tr=Fe?fc(Ht):Rt;for(Z=tr.length-1,T=me-1;T>=0;T--){const Te=z+T,je=d[Te],nr=Te+1{const{el:S,type:N,transition:M,children:R,shapeFlag:T}=u;if(T&6){at(u.component.subTree,d,m,E);return}if(T&128){u.suspense.move(d,m,E);return}if(T&64){N.move(u,d,m,xt);return}if(N===Se){s(S,d,m);for(let H=0;HM.enter(S),w);else{const{leave:H,delayLeave:j,afterLeave:q}=M,z=()=>{u.ctx.isUnmounted?r(S):s(S,d,m)},ee=()=>{H(S,()=>{z(),q&&q()})};j?j(S,z,ee):ee()}else s(S,d,m)},$e=(u,d,m,E=!1,w=!1)=>{const{type:S,props:N,ref:M,children:R,dynamicChildren:T,shapeFlag:W,patchFlag:H,dirs:j,cacheIndex:q}=u;if(H===-2&&(w=!1),M!=null&&(Xe(),Yt(M,null,m,u,!0),Ye()),q!=null&&(d.renderCache[q]=void 0),W&256){d.ctx.deactivate(u);return}const z=W&1&&j,ee=!vt(u);let Z;if(ee&&(Z=N&&N.onVnodeBeforeUnmount)&&Oe(Z,d,u),W&6)Ro(u.component,m,E);else{if(W&128){u.suspense.unmount(m,E);return}z&&ke(u,null,d,"beforeUnmount"),W&64?u.type.remove(u,d,m,xt,E):T&&!T.hasOnce&&(S!==Se||H>0&&H&64)?Ft(T,d,m,!1,!0):(S===Se&&H&384||!w&&W&16)&&Ft(R,d,m),E&&Zs(u)}(ee&&(Z=N&&N.onVnodeUnmounted)||z)&&Ce(()=>{Z&&Oe(Z,d,u),z&&ke(u,null,d,"unmounted")},m)},Zs=u=>{const{type:d,el:m,anchor:E,transition:w}=u;if(d===Se){Ao(m,E);return}if(d===Wt){g(u);return}const S=()=>{r(m),w&&!w.persisted&&w.afterLeave&&w.afterLeave()};if(u.shapeFlag&1&&w&&!w.persisted){const{leave:N,delayLeave:M}=w,R=()=>N(m,S);M?M(u.el,S,R):R()}else S()},Ao=(u,d)=>{let m;for(;u!==d;)m=v(u),r(u),u=m;r(d)},Ro=(u,d,m)=>{const{bum:E,scope:w,job:S,subTree:N,um:M,m:R,a:T,parent:W,slots:{__:H}}=u;mr(R),mr(T),E&&Gn(E),W&&K(H)&&H.forEach(j=>{W.renderCache[j]=void 0}),w.stop(),S&&(S.flags|=8,$e(N,u,d,m)),M&&Ce(M,d),Ce(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},Ft=(u,d,m,E=!1,w=!1,S=0)=>{for(let N=S;N{if(u.shapeFlag&6)return ln(u.component.subTree);if(u.shapeFlag&128)return u.suspense.next();const d=v(u.anchor||u.el),m=d&&d[Al];return m?v(m):d};let Bn=!1;const er=(u,d,m)=>{u==null?d._vnode&&$e(d._vnode,null,null,!0):_(d._vnode||null,u,d,null,null,null,m),d._vnode=u,Bn||(Bn=!0,or(),An(),Bn=!1)},xt={p:_,um:$e,m:at,r:Zs,mt:Y,mc:B,pc:$,pbc:I,n:ln,o:e};let Kn,qn;return t&&([Kn,qn]=t(xt)),{render:er,hydrate:Kn,createApp:ec(er,Kn)}}function ts({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function ft({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Xi(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Yi(e,t,n=!1){const s=e.children,r=t.children;if(K(s)&&K(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}function zi(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:zi(t)}function mr(e){if(e)for(let t=0;tbt(uc);function Ji(e,t){return kn(e,null,t)}function Sf(e,t){return kn(e,null,{flush:"post"})}function Le(e,t,n){return kn(e,t,n)}function kn(e,t,n=ne){const{immediate:s,deep:r,flush:i,once:o}=n,l=de({},n),c=t&&s||!t&&i!=="post";let f;if(Lt){if(i==="sync"){const y=dc();f=y.__watcherHandles||(y.__watcherHandles=[])}else if(!c){const y=()=>{};return y.stop=Ue,y.resume=Ue,y.pause=Ue,y}}const a=fe;l.call=(y,x,_)=>De(y,a,x,_);let h=!1;i==="post"?l.scheduler=y=>{Ce(y,a&&a.suspense)}:i!=="sync"&&(h=!0,l.scheduler=(y,x)=>{x?y():Ws(y)}),l.augmentJob=y=>{t&&(y.flags|=4),h&&(y.flags|=2,a&&(y.id=a.uid,y.i=a))};const v=Sl(e,t,l);return Lt&&(f?f.push(v):c&&v()),v}function hc(e,t,n){const s=this.proxy,r=oe(e)?e.includes(".")?Qi(s,e):()=>s[e]:e.bind(s,s);let i;G(t)?i=t:(i=t.handler,n=t);const o=rn(this),l=kn(r,i.bind(s),n);return o(),l}function Qi(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;rt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Ne(t)}Modifiers`]||e[`${ct(t)}Modifiers`];function gc(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||ne;let r=n;const i=t.startsWith("update:"),o=i&&pc(s,t.slice(7));o&&(o.trim&&(r=n.map(a=>oe(a)?a.trim():a)),o.number&&(r=n.map(No)));let l,c=s[l=yn(t)]||s[l=yn(Ne(t))];!c&&i&&(c=s[l=yn(ct(t))]),c&&De(c,e,6,r);const f=s[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,De(f,e,6,r)}}function Zi(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!G(e)){const c=f=>{const a=Zi(f,t,!0);a&&(l=!0,de(o,a))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!l?(se(e)&&s.set(e,null),null):(K(i)?i.forEach(c=>o[c]=null):de(o,i),se(e)&&s.set(e,o),o)}function Un(e,t){return!e||!Zt(t)?!1:(t=t.slice(2).replace(/Once$/,""),Q(e,t[0].toLowerCase()+t.slice(1))||Q(e,ct(t))||Q(e,t))}function ns(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:o,attrs:l,emit:c,render:f,renderCache:a,props:h,data:v,setupState:y,ctx:x,inheritAttrs:_}=e,V=Rn(e);let L,D;try{if(n.shapeFlag&4){const g=r||s,P=g;L=Me(f.call(P,g,a,h,y,v,x)),D=l}else{const g=t;L=Me(g.length>1?g(h,{attrs:l,slots:o,emit:c}):g(h,null)),D=t.props?l:mc(l)}}catch(g){Bt.length=0,tn(g,e,1),L=ce(pe)}let p=L;if(D&&_!==!1){const g=Object.keys(D),{shapeFlag:P}=p;g.length&&P&7&&(i&&g.some(Ps)&&(D=vc(D,i)),p=lt(p,D,!1,!0))}return n.dirs&&(p=lt(p,null,!1,!0),p.dirs=p.dirs?p.dirs.concat(n.dirs):n.dirs),n.transition&&Xt(p,n.transition),L=p,Rn(V),L}const mc=e=>{let t;for(const n in e)(n==="class"||n==="style"||Zt(n))&&((t||(t={}))[n]=e[n]);return t},vc=(e,t)=>{const n={};for(const s in e)(!Ps(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function yc(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:c}=t,f=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?vr(s,o,f):!!o;if(c&8){const a=t.dynamicProps;for(let h=0;he.__isSuspense;function no(e,t){t&&t.pendingBranch?K(e)?t.effects.push(...e):t.effects.push(e):Tl(e)}const Se=Symbol.for("v-fgt"),_t=Symbol.for("v-txt"),pe=Symbol.for("v-cmt"),Wt=Symbol.for("v-stc"),Bt=[];let Ae=null;function Ts(e=!1){Bt.push(Ae=e?null:[])}function bc(){Bt.pop(),Ae=Bt[Bt.length-1]||null}let zt=1;function yr(e,t=!1){zt+=e,e<0&&Ae&&t&&(Ae.hasOnce=!0)}function so(e){return e.dynamicChildren=zt>0?Ae||Rt:null,bc(),zt>0&&Ae&&Ae.push(e),e}function xf(e,t,n,s,r,i){return so(io(e,t,n,s,r,i,!0))}function Cs(e,t,n,s,r){return so(ce(e,t,n,s,r,!0))}function Jt(e){return e?e.__v_isVNode===!0:!1}function pt(e,t){return e.type===t.type&&e.key===t.key}const ro=({key:e})=>e??null,_n=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?oe(e)||ue(e)||G(e)?{i:ge,r:e,k:t,f:!!n}:e:null);function io(e,t=null,n=null,s=0,r=null,i=e===Se?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ro(t),ref:t&&_n(t),scopeId:xi,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ge};return l?(Xs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=oe(n)?8:16),zt>0&&!o&&Ae&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Ae.push(c),c}const ce=_c;function _c(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===Li)&&(e=pe),Jt(e)){const l=lt(e,t,!0);return n&&Xs(l,n),zt>0&&!i&&Ae&&(l.shapeFlag&6?Ae[Ae.indexOf(e)]=l:Ae.push(l)),l.patchFlag=-2,l}if(Mc(e)&&(e=e.__vccOpts),t){t=wc(t);let{class:l,style:c}=t;l&&!oe(l)&&(t.class=Fs(l)),se(c)&&(ks(c)&&!K(c)&&(c=de({},c)),t.style=Ns(c))}const o=oe(e)?1:to(e)?128:Ei(e)?64:se(e)?4:G(e)?2:0;return io(e,t,n,s,r,o,i,!0)}function wc(e){return e?ks(e)||Ui(e)?de({},e):e:null}function lt(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:o,children:l,transition:c}=e,f=t?Sc(r||{},t):r,a={__v_isVNode:!0,__v_skip:!0,type:e.type,props:f,key:f&&ro(f),ref:t&&t.ref?n&&i?K(i)?i.concat(_n(t)):[i,_n(t)]:_n(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Se?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&<(e.ssContent),ssFallback:e.ssFallback&<(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&Xt(a,c.clone(a)),a}function oo(e=" ",t=0){return ce(_t,null,e,t)}function Ef(e,t){const n=ce(Wt,null,e);return n.staticCount=t,n}function Tf(e="",t=!1){return t?(Ts(),Cs(pe,null,e)):ce(pe,null,e)}function Me(e){return e==null||typeof e=="boolean"?ce(pe):K(e)?ce(Se,null,e.slice()):Jt(e)?st(e):ce(_t,null,String(e))}function st(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:lt(e)}function Xs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(K(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Xs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Ui(t)?t._ctx=ge:r===3&&ge&&(ge.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else G(t)?(t={default:t,_ctx:ge},n=32):(t=String(t),s&64?(n=16,t=[oo(t)]):n=8);e.children=t,e.shapeFlag|=n}function Sc(...e){const t={};for(let n=0;nfe||ge;let Mn,As;{const e=Nn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(o=>o(i)):r[0](i)}};Mn=t("__VUE_INSTANCE_SETTERS__",n=>fe=n),As=t("__VUE_SSR_SETTERS__",n=>Lt=n)}const rn=e=>{const t=fe;return Mn(e),e.scope.on(),()=>{e.scope.off(),Mn(t)}},br=()=>{fe&&fe.scope.off(),Mn(null)};function lo(e){return e.vnode.shapeFlag&4}let Lt=!1;function Cc(e,t=!1,n=!1){t&&As(t);const{props:s,children:r}=e.vnode,i=lo(e);nc(e,s,i,t),oc(e,r,n||t);const o=i?Ac(e,t):void 0;return t&&As(!1),o}function Ac(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,ql);const{setup:s}=n;if(s){Xe();const r=e.setupContext=s.length>1?ao(e):null,i=rn(e),o=en(s,e,0,[e.props,r]),l=zr(o);if(Ye(),i(),(l||e.sp)&&!vt(e)&&Ks(e),l){if(o.then(br,br),t)return o.then(c=>{_r(e,c)}).catch(c=>{tn(c,e,0)});e.asyncDep=o}else _r(e,o)}else co(e)}function _r(e,t,n){G(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:se(t)&&(e.setupState=bi(t)),co(e)}function co(e,t,n){const s=e.type;e.render||(e.render=s.render||Ue);{const r=rn(e);Xe();try{Xl(e)}finally{Ye(),r()}}}const Rc={get(e,t){return be(e,"get",""),e[t]}};function ao(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,Rc),slots:e.slots,emit:e.emit,expose:t}}function Ys(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(bi(bn(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ut)return Ut[n](e)},has(t,n){return n in t||n in Ut}})):e.proxy}function Oc(e,t=!0){return G(e)?e.displayName||e.name:e.name||t&&e.__name}function Mc(e){return G(e)&&"__vccOpts"in e}const ie=(e,t)=>_l(e,t,Lt);function Rs(e,t,n){const s=arguments.length;return s===2?se(t)&&!K(t)?Jt(t)?ce(e,null,[t]):ce(e,t):ce(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Jt(n)&&(n=[n]),ce(e,t,n))}const Pc="3.5.14";/** +* @vue/runtime-dom v3.5.14 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Os;const wr=typeof window<"u"&&window.trustedTypes;if(wr)try{Os=wr.createPolicy("vue",{createHTML:e=>e})}catch{}const fo=Os?e=>Os.createHTML(e):e=>e,Ic="http://www.w3.org/2000/svg",Lc="http://www.w3.org/1998/Math/MathML",qe=typeof document<"u"?document:null,Sr=qe&&qe.createElement("template"),Nc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?qe.createElementNS(Ic,e):t==="mathml"?qe.createElementNS(Lc,e):n?qe.createElement(e,{is:n}):qe.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>qe.createTextNode(e),createComment:e=>qe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>qe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Sr.innerHTML=fo(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=Sr.content;if(s==="svg"||s==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},et="transition",$t="animation",Qt=Symbol("_vtc"),uo={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Fc=de({},Ti,uo),Hc=e=>(e.displayName="Transition",e.props=Fc,e),Cf=Hc((e,{slots:t})=>Rs(Ml,Dc(e),t)),ut=(e,t=[])=>{K(e)?e.forEach(n=>n(...t)):e&&e(...t)},xr=e=>e?K(e)?e.some(t=>t.length>1):e.length>1:!1;function Dc(e){const t={};for(const b in e)b in uo||(t[b]=e[b]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:f=o,appearToClass:a=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:v=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,x=$c(r),_=x&&x[0],V=x&&x[1],{onBeforeEnter:L,onEnter:D,onEnterCancelled:p,onLeave:g,onLeaveCancelled:P,onBeforeAppear:U=L,onAppear:O=D,onAppearCancelled:B=p}=t,C=(b,F,Y,re)=>{b._enterCancelled=re,dt(b,F?a:l),dt(b,F?f:o),Y&&Y()},I=(b,F)=>{b._isLeaving=!1,dt(b,h),dt(b,y),dt(b,v),F&&F()},A=b=>(F,Y)=>{const re=b?O:D,k=()=>C(F,b,Y);ut(re,[F,k]),Er(()=>{dt(F,b?c:i),Ke(F,b?a:l),xr(re)||Tr(F,s,_,k)})};return de(t,{onBeforeEnter(b){ut(L,[b]),Ke(b,i),Ke(b,o)},onBeforeAppear(b){ut(U,[b]),Ke(b,c),Ke(b,f)},onEnter:A(!1),onAppear:A(!0),onLeave(b,F){b._isLeaving=!0;const Y=()=>I(b,F);Ke(b,h),b._enterCancelled?(Ke(b,v),Rr()):(Rr(),Ke(b,v)),Er(()=>{b._isLeaving&&(dt(b,h),Ke(b,y),xr(g)||Tr(b,s,V,Y))}),ut(g,[b,Y])},onEnterCancelled(b){C(b,!1,void 0,!0),ut(p,[b])},onAppearCancelled(b){C(b,!0,void 0,!0),ut(B,[b])},onLeaveCancelled(b){I(b),ut(P,[b])}})}function $c(e){if(e==null)return null;if(se(e))return[ss(e.enter),ss(e.leave)];{const t=ss(e);return[t,t]}}function ss(e){return Fo(e)}function Ke(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Qt]||(e[Qt]=new Set)).add(t)}function dt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Qt];n&&(n.delete(t),n.size||(e[Qt]=void 0))}function Er(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let jc=0;function Tr(e,t,n,s){const r=e._endId=++jc,i=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=Vc(e,t);if(!o)return s();const f=o+"end";let a=0;const h=()=>{e.removeEventListener(f,v),i()},v=y=>{y.target===e&&++a>=c&&h()};setTimeout(()=>{a(n[x]||"").split(", "),r=s(`${et}Delay`),i=s(`${et}Duration`),o=Cr(r,i),l=s(`${$t}Delay`),c=s(`${$t}Duration`),f=Cr(l,c);let a=null,h=0,v=0;t===et?o>0&&(a=et,h=o,v=i.length):t===$t?f>0&&(a=$t,h=f,v=c.length):(h=Math.max(o,f),a=h>0?o>f?et:$t:null,v=a?a===et?i.length:c.length:0);const y=a===et&&/\b(transform|all)(,|$)/.test(s(`${et}Property`).toString());return{type:a,timeout:h,propCount:v,hasTransform:y}}function Cr(e,t){for(;e.lengthAr(n)+Ar(e[s])))}function Ar(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Rr(){return document.body.offsetHeight}function kc(e,t,n){const s=e[Qt];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Or=Symbol("_vod"),Uc=Symbol("_vsh"),Wc=Symbol(""),Bc=/(^|;)\s*display\s*:/;function Kc(e,t,n){const s=e.style,r=oe(n);let i=!1;if(n&&!r){if(t)if(oe(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&wn(s,l,"")}else for(const o in t)n[o]==null&&wn(s,o,"");for(const o in n)o==="display"&&(i=!0),wn(s,o,n[o])}else if(r){if(t!==n){const o=s[Wc];o&&(n+=";"+o),s.cssText=n,i=Bc.test(n)}}else t&&e.removeAttribute("style");Or in e&&(e[Or]=i?s.display:"",e[Uc]&&(s.display="none"))}const Mr=/\s*!important$/;function wn(e,t,n){if(K(n))n.forEach(s=>wn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=qc(e,t);Mr.test(n)?e.setProperty(ct(s),n.replace(Mr,""),"important"):e[s]=n}}const Pr=["Webkit","Moz","ms"],rs={};function qc(e,t){const n=rs[t];if(n)return n;let s=Ne(t);if(s!=="filter"&&s in e)return rs[t]=s;s=Ln(s);for(let r=0;ris||(Jc.then(()=>is=0),is=Date.now());function Zc(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;De(ea(s,n.value),t,5,[s])};return n.value=e,n.attached=Qc(),n}function ea(e,t){if(K(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Dr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,ta=(e,t,n,s,r,i)=>{const o=r==="svg";t==="class"?kc(e,s,o):t==="style"?Kc(e,n,s):Zt(t)?Ps(t)||Yc(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):na(e,t,s,o))?(Nr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Lr(e,t,s,o,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!oe(s))?Nr(e,Ne(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Lr(e,t,s,o))};function na(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Dr(t)&&G(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Dr(t)&&oe(n)?!1:t in e}const sa=["ctrl","shift","alt","meta"],ra={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>sa.some(n=>e[`${n}Key`]&&!t.includes(n))},Af=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...i)=>{for(let o=0;o{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const i=ct(r.key);if(t.some(o=>o===i||ia[o]===i))return e(r)})},oa=de({patchProp:ta},Nc);let os,$r=!1;function la(){return os=$r?os:cc(oa),$r=!0,os}const Of=(...e)=>{const t=la().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=aa(s);if(r)return n(r,!0,ca(r))},t};function ca(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function aa(e){return oe(e)?document.querySelector(e):e}const fa=window.__VP_SITE_DATA__;function ho(e){return si()?(Bo(e),!0):!1}const ls=new WeakMap,ua=(...e)=>{var t;const n=e[0],s=(t=sn())==null?void 0:t.proxy;if(s==null&&!ji())throw new Error("injectLocal must be called in setup");return s&&ls.has(s)&&n in ls.get(s)?ls.get(s)[n]:bt(...e)},po=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const da=Object.prototype.toString,ha=e=>da.call(e)==="[object Object]",St=()=>{},jr=pa();function pa(){var e,t;return po&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function zs(e,t){function n(...s){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(i)})}return n}const go=e=>e();function ga(e,t={}){let n,s,r=St;const i=c=>{clearTimeout(c),r(),r=St};let o;return c=>{const f=le(e),a=le(t.maxWait);return n&&i(n),f<=0||a!==void 0&&a<=0?(s&&(i(s),s=null),Promise.resolve(c())):new Promise((h,v)=>{r=t.rejectOnCancel?v:h,o=c,a&&!s&&(s=setTimeout(()=>{n&&i(n),s=null,h(o())},a)),n=setTimeout(()=>{s&&i(s),s=null,h(c())},f)})}}function ma(...e){let t=0,n,s=!0,r=St,i,o,l,c,f;!ue(e[0])&&typeof e[0]=="object"?{delay:o,trailing:l=!0,leading:c=!0,rejectOnCancel:f=!1}=e[0]:[o,l=!0,c=!0,f=!1]=e;const a=()=>{n&&(clearTimeout(n),n=void 0,r(),r=St)};return v=>{const y=le(o),x=Date.now()-t,_=()=>i=v();return a(),y<=0?(t=Date.now(),_()):(x>y&&(c||!s)?(t=Date.now(),_()):l&&(i=new Promise((V,L)=>{r=f?L:V,n=setTimeout(()=>{t=Date.now(),s=!0,V(_()),a()},Math.max(0,y-x))})),!c&&!n&&(n=setTimeout(()=>s=!0,y)),s=!1,i)}}function va(e=go,t={}){const{initialState:n="active"}=t,s=Js(n==="active");function r(){s.value=!1}function i(){s.value=!0}const o=(...l)=>{s.value&&e(...l)};return{isActive:Dn(s),pause:r,resume:i,eventFilter:o}}function Vr(e){return e.endsWith("rem")?Number.parseFloat(e)*16:Number.parseFloat(e)}function ya(e){return sn()}function cs(e){return Array.isArray(e)?e:[e]}function Js(...e){if(e.length!==1)return vl(...e);const t=e[0];return typeof t=="function"?Dn(pl(()=>({get:t,set:St}))):We(t)}function ba(e,t=200,n={}){return zs(ga(t,n),e)}function _a(e,t=200,n=!1,s=!0,r=!1){return zs(ma(t,n,s,r),e)}function wa(e,t,n={}){const{eventFilter:s=go,...r}=n;return Le(e,zs(s,t),r)}function Sa(e,t,n={}){const{eventFilter:s,initialState:r="active",...i}=n,{eventFilter:o,pause:l,resume:c,isActive:f}=va(s,{initialState:r});return{stop:wa(e,t,{...i,eventFilter:o}),pause:l,resume:c,isActive:f}}function Wn(e,t=!0,n){ya()?Nt(e,n):t?e():$n(e)}function xa(e,t,n){return Le(e,t,{...n,immediate:!0})}const ze=po?window:void 0;function Qs(e){var t;const n=le(e);return(t=n==null?void 0:n.$el)!=null?t:n}function Je(...e){const t=[],n=()=>{t.forEach(l=>l()),t.length=0},s=(l,c,f,a)=>(l.addEventListener(c,f,a),()=>l.removeEventListener(c,f,a)),r=ie(()=>{const l=cs(le(e[0])).filter(c=>c!=null);return l.every(c=>typeof c!="string")?l:void 0}),i=xa(()=>{var l,c;return[(c=(l=r.value)==null?void 0:l.map(f=>Qs(f)))!=null?c:[ze].filter(f=>f!=null),cs(le(r.value?e[1]:e[0])),cs(Us(r.value?e[2]:e[1])),le(r.value?e[3]:e[2])]},([l,c,f,a])=>{if(n(),!(l!=null&&l.length)||!(c!=null&&c.length)||!(f!=null&&f.length))return;const h=ha(a)?{...a}:a;t.push(...l.flatMap(v=>c.flatMap(y=>f.map(x=>s(v,y,x,h)))))},{flush:"post"}),o=()=>{i(),n()};return ho(n),o}function Ea(){const e=Ie(!1),t=sn();return t&&Nt(()=>{e.value=!0},t),e}function Ta(e){const t=Ea();return ie(()=>(t.value,!!e()))}function Ca(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Mf(...e){let t,n,s={};e.length===3?(t=e[0],n=e[1],s=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],s=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=ze,eventName:i="keydown",passive:o=!1,dedupe:l=!1}=s,c=Ca(t);return Je(r,i,a=>{a.repeat&&le(l)||c(a)&&n(a)},o)}const Aa=Symbol("vueuse-ssr-width");function Ra(){const e=ji()?ua(Aa,null):null;return typeof e=="number"?e:void 0}function mo(e,t={}){const{window:n=ze,ssrWidth:s=Ra()}=t,r=Ta(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function"),i=Ie(typeof s=="number"),o=Ie(),l=Ie(!1),c=f=>{l.value=f.matches};return Ji(()=>{if(i.value){i.value=!r.value;const f=le(e).split(",");l.value=f.some(a=>{const h=a.includes("not all"),v=a.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),y=a.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let x=!!(v||y);return v&&x&&(x=s>=Vr(v[1])),y&&x&&(x=s<=Vr(y[1])),h?!x:x});return}r.value&&(o.value=n.matchMedia(le(e)),l.value=o.value.matches)}),Je(o,"change",c,{passive:!0}),ie(()=>l.value)}const pn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},gn="__vueuse_ssr_handlers__",Oa=Ma();function Ma(){return gn in pn||(pn[gn]=pn[gn]||{}),pn[gn]}function vo(e,t){return Oa[e]||t}function yo(e){return mo("(prefers-color-scheme: dark)",e)}function Pa(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Ia={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},kr="vueuse-storage";function La(e,t,n,s={}){var r;const{flush:i="pre",deep:o=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:f=!1,shallow:a,window:h=ze,eventFilter:v,onError:y=A=>{console.error(A)},initOnMounted:x}=s,_=(a?Ie:We)(typeof t=="function"?t():t),V=ie(()=>le(e));if(!n)try{n=vo("getDefaultStorage",()=>{var A;return(A=ze)==null?void 0:A.localStorage})()}catch(A){y(A)}if(!n)return _;const L=le(t),D=Pa(L),p=(r=s.serializer)!=null?r:Ia[D],{pause:g,resume:P}=Sa(_,()=>O(_.value),{flush:i,deep:o,eventFilter:v});Le(V,()=>C(),{flush:i}),h&&l&&Wn(()=>{n instanceof Storage?Je(h,"storage",C,{passive:!0}):Je(h,kr,I),x&&C()}),x||C();function U(A,b){if(h){const F={key:V.value,oldValue:A,newValue:b,storageArea:n};h.dispatchEvent(n instanceof Storage?new StorageEvent("storage",F):new CustomEvent(kr,{detail:F}))}}function O(A){try{const b=n.getItem(V.value);if(A==null)U(b,null),n.removeItem(V.value);else{const F=p.write(A);b!==F&&(n.setItem(V.value,F),U(b,F))}}catch(b){y(b)}}function B(A){const b=A?A.newValue:n.getItem(V.value);if(b==null)return c&&L!=null&&n.setItem(V.value,p.write(L)),L;if(!A&&f){const F=p.read(b);return typeof f=="function"?f(F,L):D==="object"&&!Array.isArray(F)?{...L,...F}:F}else return typeof b!="string"?b:p.read(b)}function C(A){if(!(A&&A.storageArea!==n)){if(A&&A.key==null){_.value=L;return}if(!(A&&A.key!==V.value)){g();try{(A==null?void 0:A.newValue)!==p.write(_.value)&&(_.value=B(A))}catch(b){y(b)}finally{A?$n(P):P()}}}}function I(A){C(A.detail)}return _}const Na="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";function Fa(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:r=ze,storage:i,storageKey:o="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:f,disableTransition:a=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},v=yo({window:r}),y=ie(()=>v.value?"dark":"light"),x=c||(o==null?Js(s):La(o,s,i,{window:r,listenToStorageChanges:l})),_=ie(()=>x.value==="auto"?y.value:x.value),V=vo("updateHTMLAttrs",(g,P,U)=>{const O=typeof g=="string"?r==null?void 0:r.document.querySelector(g):Qs(g);if(!O)return;const B=new Set,C=new Set;let I=null;if(P==="class"){const b=U.split(/\s/g);Object.values(h).flatMap(F=>(F||"").split(/\s/g)).filter(Boolean).forEach(F=>{b.includes(F)?B.add(F):C.add(F)})}else I={key:P,value:U};if(B.size===0&&C.size===0&&I===null)return;let A;a&&(A=r.document.createElement("style"),A.appendChild(document.createTextNode(Na)),r.document.head.appendChild(A));for(const b of B)O.classList.add(b);for(const b of C)O.classList.remove(b);I&&O.setAttribute(I.key,I.value),a&&(r.getComputedStyle(A).opacity,document.head.removeChild(A))});function L(g){var P;V(t,n,(P=h[g])!=null?P:g)}function D(g){e.onChanged?e.onChanged(g,L):L(g)}Le(_,D,{flush:"post",immediate:!0}),Wn(()=>D(_.value));const p=ie({get(){return f?x.value:_.value},set(g){x.value=g}});return Object.assign(p,{store:x,system:y,state:_})}function Ha(e={}){const{valueDark:t="dark",valueLight:n=""}=e,s=Fa({...e,onChanged:(o,l)=>{var c;e.onChanged?(c=e.onChanged)==null||c.call(e,o==="dark",l,o):l(o)},modes:{dark:t,light:n}}),r=ie(()=>s.system.value);return ie({get(){return s.value==="dark"},set(o){const l=o?"dark":"light";r.value===l?s.value="auto":s.value=l}})}function as(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}const Ur=1;function Da(e,t={}){const{throttle:n=0,idle:s=200,onStop:r=St,onScroll:i=St,offset:o={left:0,right:0,top:0,bottom:0},eventListenerOptions:l={capture:!1,passive:!0},behavior:c="auto",window:f=ze,onError:a=O=>{console.error(O)}}=t,h=Ie(0),v=Ie(0),y=ie({get(){return h.value},set(O){_(O,void 0)}}),x=ie({get(){return v.value},set(O){_(void 0,O)}});function _(O,B){var C,I,A,b;if(!f)return;const F=le(e);if(!F)return;(A=F instanceof Document?f.document.body:F)==null||A.scrollTo({top:(C=le(B))!=null?C:x.value,left:(I=le(O))!=null?I:y.value,behavior:le(c)});const Y=((b=F==null?void 0:F.document)==null?void 0:b.documentElement)||(F==null?void 0:F.documentElement)||F;y!=null&&(h.value=Y.scrollLeft),x!=null&&(v.value=Y.scrollTop)}const V=Ie(!1),L=It({left:!0,right:!1,top:!0,bottom:!1}),D=It({left:!1,right:!1,top:!1,bottom:!1}),p=O=>{V.value&&(V.value=!1,D.left=!1,D.right=!1,D.top=!1,D.bottom=!1,r(O))},g=ba(p,n+s),P=O=>{var B;if(!f)return;const C=((B=O==null?void 0:O.document)==null?void 0:B.documentElement)||(O==null?void 0:O.documentElement)||Qs(O),{display:I,flexDirection:A,direction:b}=getComputedStyle(C),F=b==="rtl"?-1:1,Y=C.scrollLeft;D.left=Yh.value;const re=Math.abs(Y*F)<=(o.left||0),k=Math.abs(Y*F)+C.clientWidth>=C.scrollWidth-(o.right||0)-Ur;I==="flex"&&A==="row-reverse"?(L.left=k,L.right=re):(L.left=re,L.right=k),h.value=Y;let X=C.scrollTop;O===f.document&&!X&&(X=f.document.body.scrollTop),D.top=Xv.value;const $=Math.abs(X)<=(o.top||0),ae=Math.abs(X)+C.clientHeight>=C.scrollHeight-(o.bottom||0)-Ur;I==="flex"&&A==="column-reverse"?(L.top=ae,L.bottom=$):(L.top=$,L.bottom=ae),v.value=X},U=O=>{var B;if(!f)return;const C=(B=O.target.documentElement)!=null?B:O.target;P(C),V.value=!0,g(O),i(O)};return Je(e,"scroll",n?_a(U,n,!0,!1):U,l),Wn(()=>{try{const O=le(e);if(!O)return;P(O)}catch(O){a(O)}}),Je(e,"scrollend",p,l),{x:y,y:x,isScrolling:V,arrivedState:L,directions:D,measure(){const O=le(e);f&&O&&P(O)}}}function bo(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const fs=new WeakMap;function Pf(e,t=!1){const n=Ie(t);let s=null,r="";Le(Js(e),l=>{const c=as(le(l));if(c){const f=c;if(fs.get(f)||fs.set(f,f.style.overflow),f.style.overflow!=="hidden"&&(r=f.style.overflow),f.style.overflow==="hidden")return n.value=!0;if(n.value)return f.style.overflow="hidden"}},{immediate:!0});const i=()=>{const l=as(le(e));!l||n.value||(jr&&(s=Je(l,"touchmove",c=>{$a(c)},{passive:!1})),l.style.overflow="hidden",n.value=!0)},o=()=>{const l=as(le(e));!l||!n.value||(jr&&(s==null||s()),l.style.overflow=r,fs.delete(l),n.value=!1)};return ho(o),ie({get(){return n.value},set(l){l?i():o()}})}function If(e={}){const{window:t=ze,...n}=e;return Da(t,n)}function Lf(e={}){const{window:t=ze,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,listenOrientation:r=!0,includeScrollbar:i=!0,type:o="inner"}=e,l=Ie(n),c=Ie(s),f=()=>{if(t)if(o==="outer")l.value=t.outerWidth,c.value=t.outerHeight;else if(o==="visual"&&t.visualViewport){const{width:h,height:v,scale:y}=t.visualViewport;l.value=Math.round(h*y),c.value=Math.round(v*y)}else i?(l.value=t.innerWidth,c.value=t.innerHeight):(l.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight)};f(),Wn(f);const a={passive:!0};if(Je("resize",f,a),t&&o==="visual"&&t.visualViewport&&Je(t.visualViewport,"resize",f,a),r){const h=mo("(orientation: portrait)");Le(h,()=>f())}return{width:l,height:c}}const us={};var ds={};const _o=/^(?:[a-z]+:|\/\/)/i,ja="vitepress-theme-appearance",Va=/#.*$/,ka=/[?#].*$/,Ua=/(?:(^|\/)index)?\.(?:md|html)$/,ye=typeof document<"u",wo={relativePath:"404.md",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function Wa(e,t,n=!1){if(t===void 0)return!1;if(e=Wr(`/${e}`),n)return new RegExp(t).test(e);if(Wr(t)!==e)return!1;const s=t.match(Va);return s?(ye?location.hash:"")===s[0]:!0}function Wr(e){return decodeURI(e).replace(ka,"").replace(Ua,"$1")}function Ba(e){return _o.test(e)}function Ka(e,t){return Object.keys((e==null?void 0:e.locales)||{}).find(n=>n!=="root"&&!Ba(n)&&Wa(t,`/${n}/`,!0))||"root"}function qa(e,t){var s,r,i,o,l,c,f;const n=Ka(e,t);return Object.assign({},e,{localeIndex:n,lang:((s=e.locales[n])==null?void 0:s.lang)??e.lang,dir:((r=e.locales[n])==null?void 0:r.dir)??e.dir,title:((i=e.locales[n])==null?void 0:i.title)??e.title,titleTemplate:((o=e.locales[n])==null?void 0:o.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:xo(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(f=e.locales[n])==null?void 0:f.themeConfig}})}function So(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const r=Ga(e.title,s);return n===r.slice(3)?n:`${n}${r}`}function Ga(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function Xa(e,t){const[n,s]=t;if(n!=="meta")return!1;const r=Object.entries(s)[0];return r==null?!1:e.some(([i,o])=>i===n&&o[r[0]]===r[1])}function xo(e,t){return[...e.filter(n=>!Xa(t,n)),...t]}const Ya=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,za=/^[a-z]:/i;function Br(e){const t=za.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(Ya,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const hs=new Set;function Ja(e){if(hs.size===0){const n=typeof process=="object"&&(ds==null?void 0:ds.VITE_EXTRA_EXTENSIONS)||(us==null?void 0:us.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(s=>hs.add(s))}const t=e.split(".").pop();return t==null||!hs.has(t.toLowerCase())}const Qa=Symbol(),wt=Ie(fa);function Nf(e){const t=ie(()=>qa(wt.value,e.data.relativePath)),n=t.value.appearance,s=n==="force-dark"?We(!0):n==="force-auto"?yo():n?Ha({storageKey:ja,initialValue:()=>n==="dark"?"dark":"auto",...typeof n=="object"?n:{}}):We(!1),r=We(ye?location.hash:"");return ye&&window.addEventListener("hashchange",()=>{r.value=location.hash}),Le(()=>e.data,()=>{r.value=ye?location.hash:""}),{site:t,theme:ie(()=>t.value.themeConfig),page:ie(()=>e.data),frontmatter:ie(()=>e.data.frontmatter),params:ie(()=>e.data.params),lang:ie(()=>t.value.lang),dir:ie(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:ie(()=>t.value.localeIndex||"root"),title:ie(()=>So(t.value,e.data)),description:ie(()=>e.data.description||t.value.description),isDark:s,hash:ie(()=>r.value)}}function Za(){const e=bt(Qa);if(!e)throw new Error("vitepress data not properly injected in app");return e}function ef(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Kr(e){return _o.test(e)||!e.startsWith("/")?e:ef(wt.value.base,e)}function tf(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),ye){const n="/";t=Br(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];if(s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),!s)return null;t=`${n}assets/${t}.${s}.js`}else t=`./${Br(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let Sn=[];function Ff(e){Sn.push(e),Vn(()=>{Sn=Sn.filter(t=>t!==e)})}function nf(){let e=wt.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=qr(e,n);else if(Array.isArray(e))for(const s of e){const r=qr(s,n);if(r){t=r;break}}return t}function qr(e,t){const n=document.querySelector(e);if(!n)return 0;const s=n.getBoundingClientRect().bottom;return s<0?0:s+t}const sf=Symbol(),Eo="http://a.com",rf=()=>({path:"/",component:null,data:wo});function Hf(e,t){const n=It(rf()),s={route:n,go:r};async function r(l=ye?location.href:"/"){var c,f;l=ps(l),await((c=s.onBeforeRouteChange)==null?void 0:c.call(s,l))!==!1&&(ye&&l!==ps(location.href)&&(history.replaceState({scrollPosition:window.scrollY},""),history.pushState({},"",l)),await o(l),await((f=s.onAfterRouteChange??s.onAfterRouteChanged)==null?void 0:f(l)))}let i=null;async function o(l,c=0,f=!1){var v,y;if(await((v=s.onBeforePageLoad)==null?void 0:v.call(s,l))===!1)return;const a=new URL(l,Eo),h=i=a.pathname;try{let x=await e(h);if(!x)throw new Error(`Page not found: ${h}`);if(i===h){i=null;const{default:_,__pageData:V}=x;if(!_)throw new Error(`Invalid route component: ${_}`);await((y=s.onAfterPageLoad)==null?void 0:y.call(s,l)),n.path=ye?h:Kr(h),n.component=bn(_),n.data=bn(V),ye&&$n(()=>{let L=wt.value.base+V.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!wt.value.cleanUrls&&!L.endsWith("/")&&(L+=".html"),L!==a.pathname&&(a.pathname=L,l=L+a.search+a.hash,history.replaceState({},"",l)),a.hash&&!c){let D=null;try{D=document.getElementById(decodeURIComponent(a.hash).slice(1))}catch(p){console.warn(p)}if(D){Gr(D,a.hash);return}}window.scrollTo(0,c)})}}catch(x){if(!/fetch|Page not found/.test(x.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(x),!f)try{const _=await fetch(wt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await _.json(),await o(l,c,!0);return}catch{}if(i===h){i=null,n.path=ye?h:Kr(h),n.component=t?bn(t):null;const _=ye?h.replace(/(^|\/)$/,"$1index").replace(/(\.html)?$/,".md").replace(/^\//,""):"404.md";n.data={...wo,relativePath:_}}}}return ye&&(history.state===null&&history.replaceState({},""),window.addEventListener("click",l=>{if(l.defaultPrevented||!(l.target instanceof Element)||l.target.closest("button")||l.button!==0||l.ctrlKey||l.shiftKey||l.altKey||l.metaKey)return;const c=l.target.closest("a");if(!c||c.closest(".vp-raw")||c.hasAttribute("download")||c.hasAttribute("target"))return;const f=c.getAttribute("href")??(c instanceof SVGAElement?c.getAttribute("xlink:href"):null);if(f==null)return;const{href:a,origin:h,pathname:v,hash:y,search:x}=new URL(f,c.baseURI),_=new URL(location.href);h===_.origin&&Ja(v)&&(l.preventDefault(),v===_.pathname&&x===_.search?(y!==_.hash&&(history.pushState({},"",a),window.dispatchEvent(new HashChangeEvent("hashchange",{oldURL:_.href,newURL:a}))),y?Gr(c,y,c.classList.contains("header-anchor")):window.scrollTo(0,0)):r(a))},{capture:!0}),window.addEventListener("popstate",async l=>{var f;if(l.state===null)return;const c=ps(location.href);await o(c,l.state&&l.state.scrollPosition||0),await((f=s.onAfterRouteChange??s.onAfterRouteChanged)==null?void 0:f(c))}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function of(){const e=bt(sf);if(!e)throw new Error("useRouter() is called without provider.");return e}function To(){return of().route}function Gr(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(r){console.warn(r)}if(s){let r=function(){!n||Math.abs(o-window.scrollY)>window.innerHeight?window.scrollTo(0,o):window.scrollTo({left:0,top:o,behavior:"smooth"})};const i=parseInt(window.getComputedStyle(s).paddingTop,10),o=window.scrollY+s.getBoundingClientRect().top-nf()+i;requestAnimationFrame(r)}}function ps(e){const t=new URL(e,Eo);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),wt.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const mn=()=>Sn.forEach(e=>e()),Df=Bs({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=To(),{frontmatter:n,site:s}=Za();return Le(n,mn,{deep:!0,flush:"post"}),()=>Rs(e.as,s.value.contentProps??{style:{position:"relative"}},[t.component?Rs(t.component,{onVnodeMounted:mn,onVnodeUpdated:mn,onVnodeUnmounted:mn}):"404 Page Not Found"])}}),$f=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},lf="modulepreload",cf=function(e){return"/"+e},Xr={},jf=function(t,n,s){let r=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),l=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));r=Promise.allSettled(n.map(c=>{if(c=cf(c),c in Xr)return;Xr[c]=!0;const f=c.endsWith(".css"),a=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${a}`))return;const h=document.createElement("link");if(h.rel=f?"stylesheet":lf,f||(h.as="script"),h.crossOrigin="",h.href=c,l&&h.setAttribute("nonce",l),document.head.appendChild(h),f)return new Promise((v,y)=>{h.addEventListener("load",v),h.addEventListener("error",()=>y(new Error(`Unable to preload CSS for ${c}`)))})}))}function i(o){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=o,window.dispatchEvent(l),!l.defaultPrevented)throw o}return r.then(o=>{for(const l of o||[])l.status==="rejected"&&i(l.reason);return t().catch(i)})},Vf=Bs({setup(e,{slots:t}){const n=We(!1);return Nt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function kf(){ye&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const s=(n=t.parentElement)==null?void 0:n.parentElement;if(!s)return;const r=Array.from(s.querySelectorAll("input")).indexOf(t);if(r<0)return;const i=s.querySelector(".blocks");if(!i)return;const o=Array.from(i.children).find(f=>f.classList.contains("active"));if(!o)return;const l=i.children[r];if(!l||o===l)return;o.classList.remove("active"),l.classList.add("active");const c=s==null?void 0:s.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function Uf(){if(ye){const e=new WeakMap;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,i=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!r||!i)return;const o=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className),l=[".vp-copy-ignore",".diff.remove"],c=i.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(a=>a.remove());let f=c.textContent||"";o&&(f=f.replace(/^ *(\$|>) /gm,"").trim()),af(f).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const a=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,a)})}})}}async function af(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),r=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),r&&(s.removeAllRanges(),s.addRange(r)),n&&n.focus()}}function Wf(e,t){let n=!0,s=[];const r=i=>{if(n){n=!1,i.forEach(l=>{const c=gs(l);for(const f of document.head.children)if(f.isEqualNode(c)){s.push(f);return}});return}const o=i.map(gs);s.forEach((l,c)=>{const f=o.findIndex(a=>a==null?void 0:a.isEqualNode(l??null));f!==-1?delete o[f]:(l==null||l.remove(),delete s[c])}),o.forEach(l=>l&&document.head.appendChild(l)),s=[...s,...o].filter(Boolean)};Ji(()=>{const i=e.data,o=t.value,l=i&&i.description,c=i&&i.frontmatter.head||[],f=So(o,i);f!==document.title&&(document.title=f);const a=l||o.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==a&&h.setAttribute("content",a):gs(["meta",{name:"description",content:a}]),r(xo(o.head,uf(c)))})}function gs([e,t,n]){const s=document.createElement(e);for(const r in t)s.setAttribute(r,t[r]);return n&&(s.innerHTML=n),e==="script"&&t.async==null&&(s.async=!1),s}function ff(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function uf(e){return e.filter(t=>!ff(t))}const ms=new Set,Co=()=>document.createElement("link"),df=e=>{const t=Co();t.rel="prefetch",t.href=e,document.head.appendChild(t)},hf=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let vn;const pf=ye&&(vn=Co())&&vn.relList&&vn.relList.supports&&vn.relList.supports("prefetch")?df:hf;function Bf(){if(!ye||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(o=>{if(o.isIntersecting){const l=o.target;n.unobserve(l);const{pathname:c}=l;if(!ms.has(c)){ms.add(c);const f=tf(c);f&&pf(f)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{hostname:o,pathname:l}=new URL(i.href instanceof SVGAnimatedString?i.href.animVal:i.href,i.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||i.target!=="_blank"&&o===location.hostname&&(l!==location.pathname?n.observe(i):ms.add(l))})})};Nt(s);const r=To();Le(()=>r.path,s),Vn(()=>{n&&n.disconnect()})}export{Pi as $,nf as A,yf as B,mf as C,Ie as D,Ff as E,Se as F,ce as G,vf as H,_o as I,To as J,Sc as K,bt as L,Lf as M,Ns as N,Mf as O,$n as P,If as Q,ye as R,Dn as S,Cf as T,gf as U,jf as V,Pf as W,tc as X,_f as Y,Rf as Z,$f as _,oo as a,Af as a0,wf as a1,Wf as a2,sf as a3,Nf as a4,Qa as a5,Df as a6,Vf as a7,wt as a8,Hf as a9,tf as aa,Of as ab,Bf as ac,Uf as ad,kf as ae,Rs as af,Ef as ag,of as ah,Cs as b,xf as c,Bs as d,Tf as e,Ja as f,Kr as g,ie as h,Ba as i,io as j,Us as k,Wa as l,mo as m,Fs as n,Ts as o,We as p,Le as q,bf as r,Ji as s,Uo as t,Za as u,Nt as v,Cl as w,Vn as x,Sf as y,kl as z}; diff --git a/assets/chunks/theme.DJQtrHna.js b/assets/chunks/theme.DJQtrHna.js new file mode 100644 index 0000000000..ec8f83c73d --- /dev/null +++ b/assets/chunks/theme.DJQtrHna.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/VPAlgoliaSearchBox.BlguZ0-2.js","assets/chunks/framework.CSeR4K32.js"])))=>i.map(i=>d[i]); +import{d as m,c as u,r as c,n as I,o as a,a as z,t as M,b as k,w as f,T as ue,e as h,_ as b,u as Ae,i as He,f as Be,g as de,h as g,j as d,k as r,l as K,m as re,p as w,q as D,s as Y,v as j,x as Q,y as ve,z as Ee,A as Fe,F as A,B as H,C as W,D as ge,E as Z,G as _,H as E,I as $e,J as x,K as U,L as ee,M as De,N as ye,O as Oe,P as Pe,Q as Le,R as te,S as Ge,U as Ue,V as je,W as Ve,X as Se,Y as ze,Z as Ke,$ as We,a0 as qe,a1 as Re}from"./framework.CSeR4K32.js";const Je=m({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(s){return(e,t)=>(a(),u("span",{class:I(["VPBadge",e.type])},[c(e.$slots,"default",{},()=>[z(M(e.text),1)])],2))}}),Xe={key:0,class:"VPBackdrop"},Ye=m({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(s){return(e,t)=>(a(),k(ue,{name:"fade"},{default:f(()=>[e.show?(a(),u("div",Xe)):h("",!0)]),_:1}))}}),Qe=b(Ye,[["__scopeId","data-v-c79a1216"]]),V=Ae;function Ze(s,e){let t,o=!1;return()=>{t&&clearTimeout(t),o?t=setTimeout(s,e):(s(),(o=!0)&&setTimeout(()=>o=!1,e))}}function ie(s){return s.startsWith("/")?s:`/${s}`}function pe(s){const{pathname:e,search:t,hash:o,protocol:n}=new URL(s,"http://a.com");if(He(s)||s.startsWith("#")||!n.startsWith("http")||!Be(e))return s;const{site:i}=V(),l=e.endsWith("/")||e.endsWith(".html")?s:s.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,i.value.cleanUrls?"":".html")}${t}${o}`);return de(l)}function R({correspondingLink:s=!1}={}){const{site:e,localeIndex:t,page:o,theme:n,hash:i}=V(),l=g(()=>{var p,$;return{label:(p=e.value.locales[t.value])==null?void 0:p.label,link:(($=e.value.locales[t.value])==null?void 0:$.link)||(t.value==="root"?"/":`/${t.value}/`)}});return{localeLinks:g(()=>Object.entries(e.value.locales).flatMap(([p,$])=>l.value.label===$.label?[]:{text:$.label,link:xe($.link||(p==="root"?"/":`/${p}/`),n.value.i18nRouting!==!1&&s,o.value.relativePath.slice(l.value.link.length-1),!e.value.cleanUrls)+i.value})),currentLang:l}}function xe(s,e,t,o){return e?s.replace(/\/$/,"")+ie(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,o?".html":"")):s}const et={class:"NotFound"},tt={class:"code"},nt={class:"title"},ot={class:"quote"},st={class:"action"},at=["href","aria-label"],rt=m({__name:"NotFound",setup(s){const{theme:e}=V(),{currentLang:t}=R();return(o,n)=>{var i,l,v,p,$;return a(),u("div",et,[d("p",tt,M(((i=r(e).notFound)==null?void 0:i.code)??"404"),1),d("h1",nt,M(((l=r(e).notFound)==null?void 0:l.title)??"PAGE NOT FOUND"),1),n[0]||(n[0]=d("div",{class:"divider"},null,-1)),d("blockquote",ot,M(((v=r(e).notFound)==null?void 0:v.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),d("div",st,[d("a",{class:"link",href:r(de)(r(t).link),"aria-label":((p=r(e).notFound)==null?void 0:p.linkLabel)??"go to home"},M((($=r(e).notFound)==null?void 0:$.linkText)??"Take me home"),9,at)])])}}}),it=b(rt,[["__scopeId","data-v-d6be1790"]]);function Te(s,e){if(Array.isArray(s))return J(s);if(s==null)return[];e=ie(e);const t=Object.keys(s).sort((n,i)=>i.split("/").length-n.split("/").length).find(n=>e.startsWith(ie(n))),o=t?s[t]:[];return Array.isArray(o)?J(o):J(o.items,o.base)}function lt(s){const e=[];let t=0;for(const o in s){const n=s[o];if(n.items){t=e.push(n);continue}e[t]||e.push({items:[]}),e[t].items.push(n)}return e}function ct(s){const e=[];function t(o){for(const n of o)n.text&&n.link&&e.push({text:n.text,link:n.link,docFooterText:n.docFooterText}),n.items&&t(n.items)}return t(s),e}function le(s,e){return Array.isArray(e)?e.some(t=>le(s,t)):K(s,e.link)?!0:e.items?le(s,e.items):!1}function J(s,e){return[...s].map(t=>{const o={...t},n=o.base||e;return n&&o.link&&(o.link=n+o.link),o.items&&(o.items=J(o.items,n)),o})}function O(){const{frontmatter:s,page:e,theme:t}=V(),o=re("(min-width: 960px)"),n=w(!1),i=g(()=>{const C=t.value.sidebar,N=e.value.relativePath;return C?Te(C,N):[]}),l=w(i.value);D(i,(C,N)=>{JSON.stringify(C)!==JSON.stringify(N)&&(l.value=i.value)});const v=g(()=>s.value.sidebar!==!1&&l.value.length>0&&s.value.layout!=="home"),p=g(()=>$?s.value.aside==null?t.value.aside==="left":s.value.aside==="left":!1),$=g(()=>s.value.layout==="home"?!1:s.value.aside!=null?!!s.value.aside:t.value.aside!==!1),S=g(()=>v.value&&o.value),y=g(()=>v.value?lt(l.value):[]);function P(){n.value=!0}function T(){n.value=!1}function L(){n.value?T():P()}return{isOpen:n,sidebar:l,sidebarGroups:y,hasSidebar:v,hasAside:$,leftAside:p,isSidebarEnabled:S,open:P,close:T,toggle:L}}function ut(s,e){let t;Y(()=>{t=s.value?document.activeElement:void 0}),j(()=>{window.addEventListener("keyup",o)}),Q(()=>{window.removeEventListener("keyup",o)});function o(n){n.key==="Escape"&&s.value&&(e(),t==null||t.focus())}}function dt(s){const{page:e,hash:t}=V(),o=w(!1),n=g(()=>s.value.collapsed!=null),i=g(()=>!!s.value.link),l=w(!1),v=()=>{l.value=K(e.value.relativePath,s.value.link)};D([e,s,t],v),j(v);const p=g(()=>l.value?!0:s.value.items?le(e.value.relativePath,s.value.items):!1),$=g(()=>!!(s.value.items&&s.value.items.length));Y(()=>{o.value=!!(n.value&&s.value.collapsed)}),ve(()=>{(l.value||p.value)&&(o.value=!1)});function S(){n.value&&(o.value=!o.value)}return{collapsed:o,collapsible:n,isLink:i,isActiveLink:l,hasActiveLink:p,hasChildren:$,toggle:S}}function vt(){const{hasSidebar:s}=O(),e=re("(min-width: 960px)"),t=re("(min-width: 1280px)");return{isAsideEnabled:g(()=>!t.value&&!e.value?!1:s.value?t.value:e.value)}}const pt=/\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/,ce=[];function Ne(s){return typeof s.outline=="object"&&!Array.isArray(s.outline)&&s.outline.label||s.outlineTitle||"On this page"}function fe(s){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const o=Number(t.tagName[1]);return{element:t,title:ft(t),link:"#"+t.id,level:o}});return ht(e,s)}function ft(s){let e="";for(const t of s.childNodes)if(t.nodeType===1){if(pt.test(t.className))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function ht(s,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[o,n]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;return kt(s,o,n)}function mt(s,e){const{isAsideEnabled:t}=vt(),o=Ze(i,100);let n=null;j(()=>{requestAnimationFrame(i),window.addEventListener("scroll",o)}),Ee(()=>{l(location.hash)}),Q(()=>{window.removeEventListener("scroll",o)});function i(){if(!t.value)return;const v=window.scrollY,p=window.innerHeight,$=document.body.offsetHeight,S=Math.abs(v+p-$)<1,y=ce.map(({element:T,link:L})=>({link:L,top:_t(T)})).filter(({top:T})=>!Number.isNaN(T)).sort((T,L)=>T.top-L.top);if(!y.length){l(null);return}if(v<1){l(null);return}if(S){l(y[y.length-1].link);return}let P=null;for(const{link:T,top:L}of y){if(L>v+Fe()+4)break;P=T}l(P)}function l(v){n&&n.classList.remove("active"),v==null?n=null:n=s.value.querySelector(`a[href="${decodeURIComponent(v)}"]`);const p=n;p?(p.classList.add("active"),e.value.style.top=p.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function _t(s){let e=0;for(;s!==document.body;){if(s===null)return NaN;e+=s.offsetTop,s=s.offsetParent}return e}function kt(s,e,t){ce.length=0;const o=[],n=[];return s.forEach(i=>{const l={...i,children:[]};let v=n[n.length-1];for(;v&&v.level>=l.level;)n.pop(),v=n[n.length-1];if(l.element.classList.contains("ignore-header")||v&&"shouldIgnore"in v){n.push({level:l.level,shouldIgnore:!0});return}l.level>t||l.level{const n=W("VPDocOutlineItem",!0);return a(),u("ul",{class:I(["VPDocOutlineItem",t.root?"root":"nested"])},[(a(!0),u(A,null,H(t.headers,({children:i,link:l,title:v})=>(a(),u("li",null,[d("a",{class:"outline-link",href:l,onClick:e,title:v},M(v),9,bt),i!=null&&i.length?(a(),k(n,{key:0,headers:i},null,8,["headers"])):h("",!0)]))),256))],2)}}}),we=b(gt,[["__scopeId","data-v-b933a997"]]),$t={class:"content"},yt={"aria-level":"2",class:"outline-title",id:"doc-outline-aria-label",role:"heading"},Pt=m({__name:"VPDocAsideOutline",setup(s){const{frontmatter:e,theme:t}=V(),o=ge([]);Z(()=>{o.value=fe(e.value.outline??t.value.outline)});const n=w(),i=w();return mt(n,i),(l,v)=>(a(),u("nav",{"aria-labelledby":"doc-outline-aria-label",class:I(["VPDocAsideOutline",{"has-outline":o.value.length>0}]),ref_key:"container",ref:n},[d("div",$t,[d("div",{class:"outline-marker",ref_key:"marker",ref:i},null,512),d("div",yt,M(r(Ne)(r(t))),1),_(we,{headers:o.value,root:!0},null,8,["headers"])])],2))}}),Lt=b(Pt,[["__scopeId","data-v-a5bbad30"]]),Vt={class:"VPDocAsideCarbonAds"},St=m({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(s){const e=()=>null;return(t,o)=>(a(),u("div",Vt,[_(r(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Tt={class:"VPDocAside"},Nt=m({__name:"VPDocAside",setup(s){const{theme:e}=V();return(t,o)=>(a(),u("div",Tt,[c(t.$slots,"aside-top",{},void 0,!0),c(t.$slots,"aside-outline-before",{},void 0,!0),_(Lt),c(t.$slots,"aside-outline-after",{},void 0,!0),o[0]||(o[0]=d("div",{class:"spacer"},null,-1)),c(t.$slots,"aside-ads-before",{},void 0,!0),r(e).carbonAds?(a(),k(St,{key:0,"carbon-ads":r(e).carbonAds},null,8,["carbon-ads"])):h("",!0),c(t.$slots,"aside-ads-after",{},void 0,!0),c(t.$slots,"aside-bottom",{},void 0,!0)]))}}),wt=b(Nt,[["__scopeId","data-v-3f215769"]]);function It(){const{theme:s,page:e}=V();return g(()=>{const{text:t="Edit this page",pattern:o=""}=s.value.editLink||{};let n;return typeof o=="function"?n=o(e.value):n=o.replace(/:path/g,e.value.filePath),{url:n,text:t}})}function Mt(){const{page:s,theme:e,frontmatter:t}=V();return g(()=>{var $,S,y,P,T,L,C,N;const o=Te(e.value.sidebar,s.value.relativePath),n=ct(o),i=Ct(n,B=>B.link.replace(/[?#].*$/,"")),l=i.findIndex(B=>K(s.value.relativePath,B.link)),v=(($=e.value.docFooter)==null?void 0:$.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((S=e.value.docFooter)==null?void 0:S.next)===!1&&!t.value.next||t.value.next===!1;return{prev:v?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((y=i[l-1])==null?void 0:y.docFooterText)??((P=i[l-1])==null?void 0:P.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((T=i[l-1])==null?void 0:T.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((L=i[l+1])==null?void 0:L.docFooterText)??((C=i[l+1])==null?void 0:C.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((N=i[l+1])==null?void 0:N.link)}}})}function Ct(s,e){const t=new Set;return s.filter(o=>{const n=e(o);return t.has(n)?!1:t.add(n)})}const F=m({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(s){const e=s,t=g(()=>e.tag??(e.href?"a":"span")),o=g(()=>e.href&&$e.test(e.href)||e.target==="_blank");return(n,i)=>(a(),k(E(t.value),{class:I(["VPLink",{link:n.href,"vp-external-link-icon":o.value,"no-icon":n.noIcon}]),href:n.href?r(pe)(n.href):void 0,target:n.target??(o.value?"_blank":void 0),rel:n.rel??(o.value?"noreferrer":void 0)},{default:f(()=>[c(n.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),At={class:"VPLastUpdated"},Ht=["datetime"],Bt=m({__name:"VPDocFooterLastUpdated",setup(s){const{theme:e,page:t,lang:o}=V(),n=g(()=>new Date(t.value.lastUpdated)),i=g(()=>n.value.toISOString()),l=w("");return j(()=>{Y(()=>{var v,p,$;l.value=new Intl.DateTimeFormat((p=(v=e.value.lastUpdated)==null?void 0:v.formatOptions)!=null&&p.forceLocale?o.value:void 0,(($=e.value.lastUpdated)==null?void 0:$.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(n.value)})}),(v,p)=>{var $;return a(),u("p",At,[z(M((($=r(e).lastUpdated)==null?void 0:$.text)||r(e).lastUpdatedText||"Last updated")+": ",1),d("time",{datetime:i.value},M(l.value),9,Ht)])}}}),Et=b(Bt,[["__scopeId","data-v-e98dd255"]]),Ft={key:0,class:"VPDocFooter"},Dt={key:0,class:"edit-info"},Ot={key:0,class:"edit-link"},Gt={key:1,class:"last-updated"},Ut={key:1,class:"prev-next","aria-labelledby":"doc-footer-aria-label"},jt={class:"pager"},zt=["innerHTML"],Kt=["innerHTML"],Wt={class:"pager"},qt=["innerHTML"],Rt=["innerHTML"],Jt=m({__name:"VPDocFooter",setup(s){const{theme:e,page:t,frontmatter:o}=V(),n=It(),i=Mt(),l=g(()=>e.value.editLink&&o.value.editLink!==!1),v=g(()=>t.value.lastUpdated),p=g(()=>l.value||v.value||i.value.prev||i.value.next);return($,S)=>{var y,P,T,L;return p.value?(a(),u("footer",Ft,[c($.$slots,"doc-footer-before",{},void 0,!0),l.value||v.value?(a(),u("div",Dt,[l.value?(a(),u("div",Ot,[_(F,{class:"edit-link-button",href:r(n).url,"no-icon":!0},{default:f(()=>[S[0]||(S[0]=d("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),z(" "+M(r(n).text),1)]),_:1,__:[0]},8,["href"])])):h("",!0),v.value?(a(),u("div",Gt,[_(Et)])):h("",!0)])):h("",!0),(y=r(i).prev)!=null&&y.link||(P=r(i).next)!=null&&P.link?(a(),u("nav",Ut,[S[1]||(S[1]=d("span",{class:"visually-hidden",id:"doc-footer-aria-label"},"Pager",-1)),d("div",jt,[(T=r(i).prev)!=null&&T.link?(a(),k(F,{key:0,class:"pager-link prev",href:r(i).prev.link},{default:f(()=>{var C;return[d("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.prev)||"Previous page"},null,8,zt),d("span",{class:"title",innerHTML:r(i).prev.text},null,8,Kt)]}),_:1},8,["href"])):h("",!0)]),d("div",Wt,[(L=r(i).next)!=null&&L.link?(a(),k(F,{key:0,class:"pager-link next",href:r(i).next.link},{default:f(()=>{var C;return[d("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.next)||"Next page"},null,8,qt),d("span",{class:"title",innerHTML:r(i).next.text},null,8,Rt)]}),_:1},8,["href"])):h("",!0)])])):h("",!0)])):h("",!0)}}}),Xt=b(Jt,[["__scopeId","data-v-e257564d"]]),Yt={class:"container"},Qt={class:"aside-container"},Zt={class:"aside-content"},xt={class:"content"},en={class:"content-container"},tn={class:"main"},nn=m({__name:"VPDoc",setup(s){const{theme:e}=V(),t=x(),{hasSidebar:o,hasAside:n,leftAside:i}=O(),l=g(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(v,p)=>{const $=W("Content");return a(),u("div",{class:I(["VPDoc",{"has-sidebar":r(o),"has-aside":r(n)}])},[c(v.$slots,"doc-top",{},void 0,!0),d("div",Yt,[r(n)?(a(),u("div",{key:0,class:I(["aside",{"left-aside":r(i)}])},[p[0]||(p[0]=d("div",{class:"aside-curtain"},null,-1)),d("div",Qt,[d("div",Zt,[_(wt,null,{"aside-top":f(()=>[c(v.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":f(()=>[c(v.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":f(()=>[c(v.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":f(()=>[c(v.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":f(()=>[c(v.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":f(()=>[c(v.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):h("",!0),d("div",xt,[d("div",en,[c(v.$slots,"doc-before",{},void 0,!0),d("main",tn,[_($,{class:I(["vp-doc",[l.value,r(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),_(Xt,null,{"doc-footer-before":f(()=>[c(v.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),c(v.$slots,"doc-after",{},void 0,!0)])])]),c(v.$slots,"doc-bottom",{},void 0,!0)],2)}}}),on=b(nn,[["__scopeId","data-v-39a288b8"]]),sn=m({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(s){const e=s,t=g(()=>e.href&&$e.test(e.href)),o=g(()=>e.tag||(e.href?"a":"button"));return(n,i)=>(a(),k(E(o.value),{class:I(["VPButton",[n.size,n.theme]]),href:n.href?r(pe)(n.href):void 0,target:e.target??(t.value?"_blank":void 0),rel:e.rel??(t.value?"noreferrer":void 0)},{default:f(()=>[z(M(n.text),1)]),_:1},8,["class","href","target","rel"]))}}),an=b(sn,[["__scopeId","data-v-fa7799d5"]]),rn=["src","alt"],ln=m({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(s){return(e,t)=>{const o=W("VPImage",!0);return e.image?(a(),u(A,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),u("img",U({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:r(de)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,rn)):(a(),u(A,{key:1},[_(o,U({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),_(o,U({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):h("",!0)}}}),X=b(ln,[["__scopeId","data-v-8426fc1a"]]),cn={class:"container"},un={class:"main"},dn={class:"heading"},vn=["innerHTML"],pn=["innerHTML"],fn=["innerHTML"],hn={key:0,class:"actions"},mn={key:0,class:"image"},_n={class:"image-container"},kn=m({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(s){const e=ee("hero-image-slot-exists");return(t,o)=>(a(),u("div",{class:I(["VPHero",{"has-image":t.image||r(e)}])},[d("div",cn,[d("div",un,[c(t.$slots,"home-hero-info-before",{},void 0,!0),c(t.$slots,"home-hero-info",{},()=>[d("h1",dn,[t.name?(a(),u("span",{key:0,innerHTML:t.name,class:"name clip"},null,8,vn)):h("",!0),t.text?(a(),u("span",{key:1,innerHTML:t.text,class:"text"},null,8,pn)):h("",!0)]),t.tagline?(a(),u("p",{key:0,innerHTML:t.tagline,class:"tagline"},null,8,fn)):h("",!0)],!0),c(t.$slots,"home-hero-info-after",{},void 0,!0),t.actions?(a(),u("div",hn,[(a(!0),u(A,null,H(t.actions,n=>(a(),u("div",{key:n.link,class:"action"},[_(an,{tag:"a",size:"medium",theme:n.theme,text:n.text,href:n.link,target:n.target,rel:n.rel},null,8,["theme","text","href","target","rel"])]))),128))])):h("",!0),c(t.$slots,"home-hero-actions-after",{},void 0,!0)]),t.image||r(e)?(a(),u("div",mn,[d("div",_n,[o[0]||(o[0]=d("div",{class:"image-bg"},null,-1)),c(t.$slots,"home-hero-image",{},()=>[t.image?(a(),k(X,{key:0,class:"image-src",image:t.image},null,8,["image"])):h("",!0)],!0)])])):h("",!0)])],2))}}),bn=b(kn,[["__scopeId","data-v-4f9c455b"]]),gn=m({__name:"VPHomeHero",setup(s){const{frontmatter:e}=V();return(t,o)=>r(e).hero?(a(),k(bn,{key:0,class:"VPHomeHero",name:r(e).hero.name,text:r(e).hero.text,tagline:r(e).hero.tagline,image:r(e).hero.image,actions:r(e).hero.actions},{"home-hero-info-before":f(()=>[c(t.$slots,"home-hero-info-before")]),"home-hero-info":f(()=>[c(t.$slots,"home-hero-info")]),"home-hero-info-after":f(()=>[c(t.$slots,"home-hero-info-after")]),"home-hero-actions-after":f(()=>[c(t.$slots,"home-hero-actions-after")]),"home-hero-image":f(()=>[c(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):h("",!0)}}),$n={class:"box"},yn={key:0,class:"icon"},Pn=["innerHTML"],Ln=["innerHTML"],Vn=["innerHTML"],Sn={key:4,class:"link-text"},Tn={class:"link-text-value"},Nn=m({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(s){return(e,t)=>(a(),k(F,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:f(()=>[d("article",$n,[typeof e.icon=="object"&&e.icon.wrap?(a(),u("div",yn,[_(X,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),k(X,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),u("div",{key:2,class:"icon",innerHTML:e.icon},null,8,Pn)):h("",!0),d("h2",{class:"title",innerHTML:e.title},null,8,Ln),e.details?(a(),u("p",{key:3,class:"details",innerHTML:e.details},null,8,Vn)):h("",!0),e.linkText?(a(),u("div",Sn,[d("p",Tn,[z(M(e.linkText)+" ",1),t[0]||(t[0]=d("span",{class:"vpi-arrow-right link-text-icon"},null,-1))])])):h("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),wn=b(Nn,[["__scopeId","data-v-a3976bdc"]]),In={key:0,class:"VPFeatures"},Mn={class:"container"},Cn={class:"items"},An=m({__name:"VPFeatures",props:{features:{}},setup(s){const e=s,t=g(()=>{const o=e.features.length;if(o){if(o===2)return"grid-2";if(o===3)return"grid-3";if(o%3===0)return"grid-6";if(o>3)return"grid-4"}else return});return(o,n)=>o.features?(a(),u("div",In,[d("div",Mn,[d("div",Cn,[(a(!0),u(A,null,H(o.features,i=>(a(),u("div",{key:i.title,class:I(["item",[t.value]])},[_(wn,{icon:i.icon,title:i.title,details:i.details,link:i.link,"link-text":i.linkText,rel:i.rel,target:i.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):h("",!0)}}),Hn=b(An,[["__scopeId","data-v-a6181336"]]),Bn=m({__name:"VPHomeFeatures",setup(s){const{frontmatter:e}=V();return(t,o)=>r(e).features?(a(),k(Hn,{key:0,class:"VPHomeFeatures",features:r(e).features},null,8,["features"])):h("",!0)}}),En=m({__name:"VPHomeContent",setup(s){const{width:e}=De({initialWidth:0,includeScrollbar:!1});return(t,o)=>(a(),u("div",{class:"vp-doc container",style:ye(r(e)?{"--vp-offset":`calc(50% - ${r(e)/2}px)`}:{})},[c(t.$slots,"default",{},void 0,!0)],4))}}),Fn=b(En,[["__scopeId","data-v-8e2d4988"]]),Dn=m({__name:"VPHome",setup(s){const{frontmatter:e,theme:t}=V();return(o,n)=>{const i=W("Content");return a(),u("div",{class:I(["VPHome",{"external-link-icon-enabled":r(t).externalLinkIcon}])},[c(o.$slots,"home-hero-before",{},void 0,!0),_(gn,null,{"home-hero-info-before":f(()=>[c(o.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":f(()=>[c(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":f(()=>[c(o.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":f(()=>[c(o.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":f(()=>[c(o.$slots,"home-hero-image",{},void 0,!0)]),_:3}),c(o.$slots,"home-hero-after",{},void 0,!0),c(o.$slots,"home-features-before",{},void 0,!0),_(Bn),c(o.$slots,"home-features-after",{},void 0,!0),r(e).markdownStyles!==!1?(a(),k(Fn,{key:0},{default:f(()=>[_(i)]),_:1})):(a(),k(i,{key:1}))],2)}}}),On=b(Dn,[["__scopeId","data-v-8b561e3d"]]),Gn={},Un={class:"VPPage"};function jn(s,e){const t=W("Content");return a(),u("div",Un,[c(s.$slots,"page-top"),_(t),c(s.$slots,"page-bottom")])}const zn=b(Gn,[["render",jn]]),Kn=m({__name:"VPContent",setup(s){const{page:e,frontmatter:t}=V(),{hasSidebar:o}=O();return(n,i)=>(a(),u("div",{class:I(["VPContent",{"has-sidebar":r(o),"is-home":r(t).layout==="home"}]),id:"VPContent"},[r(e).isNotFound?c(n.$slots,"not-found",{key:0},()=>[_(it)],!0):r(t).layout==="page"?(a(),k(zn,{key:1},{"page-top":f(()=>[c(n.$slots,"page-top",{},void 0,!0)]),"page-bottom":f(()=>[c(n.$slots,"page-bottom",{},void 0,!0)]),_:3})):r(t).layout==="home"?(a(),k(On,{key:2},{"home-hero-before":f(()=>[c(n.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":f(()=>[c(n.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":f(()=>[c(n.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":f(()=>[c(n.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":f(()=>[c(n.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":f(()=>[c(n.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":f(()=>[c(n.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":f(()=>[c(n.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":f(()=>[c(n.$slots,"home-features-after",{},void 0,!0)]),_:3})):r(t).layout&&r(t).layout!=="doc"?(a(),k(E(r(t).layout),{key:3})):(a(),k(on,{key:4},{"doc-top":f(()=>[c(n.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":f(()=>[c(n.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":f(()=>[c(n.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":f(()=>[c(n.$slots,"doc-before",{},void 0,!0)]),"doc-after":f(()=>[c(n.$slots,"doc-after",{},void 0,!0)]),"aside-top":f(()=>[c(n.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":f(()=>[c(n.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":f(()=>[c(n.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":f(()=>[c(n.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":f(()=>[c(n.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":f(()=>[c(n.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),Wn=b(Kn,[["__scopeId","data-v-1428d186"]]),qn={class:"container"},Rn=["innerHTML"],Jn=["innerHTML"],Xn=m({__name:"VPFooter",setup(s){const{theme:e,frontmatter:t}=V(),{hasSidebar:o}=O();return(n,i)=>r(e).footer&&r(t).footer!==!1?(a(),u("footer",{key:0,class:I(["VPFooter",{"has-sidebar":r(o)}])},[d("div",qn,[r(e).footer.message?(a(),u("p",{key:0,class:"message",innerHTML:r(e).footer.message},null,8,Rn)):h("",!0),r(e).footer.copyright?(a(),u("p",{key:1,class:"copyright",innerHTML:r(e).footer.copyright},null,8,Jn)):h("",!0)])],2)):h("",!0)}}),Yn=b(Xn,[["__scopeId","data-v-e315a0ad"]]);function Qn(){const{theme:s,frontmatter:e}=V(),t=ge([]),o=g(()=>t.value.length>0);return Z(()=>{t.value=fe(e.value.outline??s.value.outline)}),{headers:t,hasLocalNav:o}}const Zn={class:"menu-text"},xn={class:"header"},eo={class:"outline"},to=m({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(s){const e=s,{theme:t}=V(),o=w(!1),n=w(0),i=w(),l=w();function v(y){var P;(P=i.value)!=null&&P.contains(y.target)||(o.value=!1)}D(o,y=>{if(y){document.addEventListener("click",v);return}document.removeEventListener("click",v)}),Oe("Escape",()=>{o.value=!1}),Z(()=>{o.value=!1});function p(){o.value=!o.value,n.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function $(y){y.target.classList.contains("outline-link")&&(l.value&&(l.value.style.transition="none"),Pe(()=>{o.value=!1}))}function S(){o.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(y,P)=>(a(),u("div",{class:"VPLocalNavOutlineDropdown",style:ye({"--vp-vh":n.value+"px"}),ref_key:"main",ref:i},[y.headers.length>0?(a(),u("button",{key:0,onClick:p,class:I({open:o.value})},[d("span",Zn,M(r(Ne)(r(t))),1),P[0]||(P[0]=d("span",{class:"vpi-chevron-right icon"},null,-1))],2)):(a(),u("button",{key:1,onClick:S},M(r(t).returnToTopLabel||"Return to top"),1)),_(ue,{name:"flyout"},{default:f(()=>[o.value?(a(),u("div",{key:0,ref_key:"items",ref:l,class:"items",onClick:$},[d("div",xn,[d("a",{class:"top-link",href:"#",onClick:S},M(r(t).returnToTopLabel||"Return to top"),1)]),d("div",eo,[_(we,{headers:y.headers},null,8,["headers"])])],512)):h("",!0)]),_:1})],4))}}),no=b(to,[["__scopeId","data-v-8a42e2b4"]]),oo={class:"container"},so=["aria-expanded"],ao={class:"menu-text"},ro=m({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(s){const{theme:e,frontmatter:t}=V(),{hasSidebar:o}=O(),{headers:n}=Qn(),{y:i}=Le(),l=w(0);j(()=>{l.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Z(()=>{n.value=fe(t.value.outline??e.value.outline)});const v=g(()=>n.value.length===0),p=g(()=>v.value&&!o.value),$=g(()=>({VPLocalNav:!0,"has-sidebar":o.value,empty:v.value,fixed:p.value}));return(S,y)=>r(t).layout!=="home"&&(!p.value||r(i)>=l.value)?(a(),u("div",{key:0,class:I($.value)},[d("div",oo,[r(o)?(a(),u("button",{key:0,class:"menu","aria-expanded":S.open,"aria-controls":"VPSidebarNav",onClick:y[0]||(y[0]=P=>S.$emit("open-menu"))},[y[1]||(y[1]=d("span",{class:"vpi-align-left menu-icon"},null,-1)),d("span",ao,M(r(e).sidebarMenuLabel||"Menu"),1)],8,so)):h("",!0),_(no,{headers:r(n),navHeight:l.value},null,8,["headers","navHeight"])])],2)):h("",!0)}}),io=b(ro,[["__scopeId","data-v-a6f0e41e"]]);function lo(){const s=w(!1);function e(){s.value=!0,window.addEventListener("resize",n)}function t(){s.value=!1,window.removeEventListener("resize",n)}function o(){s.value?t():e()}function n(){window.outerWidth>=768&&t()}const i=x();return D(()=>i.path,t),{isScreenOpen:s,openScreen:e,closeScreen:t,toggleScreen:o}}const co={},uo={class:"VPSwitch",type:"button",role:"switch"},vo={class:"check"},po={key:0,class:"icon"};function fo(s,e){return a(),u("button",uo,[d("span",vo,[s.$slots.default?(a(),u("span",po,[c(s.$slots,"default",{},void 0,!0)])):h("",!0)])])}const ho=b(co,[["render",fo],["__scopeId","data-v-1d5665e3"]]),mo=m({__name:"VPSwitchAppearance",setup(s){const{isDark:e,theme:t}=V(),o=ee("toggle-appearance",()=>{e.value=!e.value}),n=w("");return ve(()=>{n.value=e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme"}),(i,l)=>(a(),k(ho,{title:n.value,class:"VPSwitchAppearance","aria-checked":r(e),onClick:r(o)},{default:f(()=>l[0]||(l[0]=[d("span",{class:"vpi-sun sun"},null,-1),d("span",{class:"vpi-moon moon"},null,-1)])),_:1,__:[0]},8,["title","aria-checked","onClick"]))}}),he=b(mo,[["__scopeId","data-v-5337faa4"]]),_o={key:0,class:"VPNavBarAppearance"},ko=m({__name:"VPNavBarAppearance",setup(s){const{site:e}=V();return(t,o)=>r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),u("div",_o,[_(he)])):h("",!0)}}),bo=b(ko,[["__scopeId","data-v-6c893767"]]),me=w();let Ie=!1,ae=0;function go(s){const e=w(!1);if(te){!Ie&&$o(),ae++;const t=D(me,o=>{var n,i,l;o===s.el.value||(n=s.el.value)!=null&&n.contains(o)?(e.value=!0,(i=s.onFocus)==null||i.call(s)):(e.value=!1,(l=s.onBlur)==null||l.call(s))});Q(()=>{t(),ae--,ae||yo()})}return Ge(e)}function $o(){document.addEventListener("focusin",Me),Ie=!0,me.value=document.activeElement}function yo(){document.removeEventListener("focusin",Me)}function Me(){me.value=document.activeElement}const Po={class:"VPMenuLink"},Lo=["innerHTML"],Vo=m({__name:"VPMenuLink",props:{item:{}},setup(s){const{page:e}=V();return(t,o)=>(a(),u("div",Po,[_(F,{class:I({active:r(K)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon},{default:f(()=>[d("span",{innerHTML:t.item.text},null,8,Lo)]),_:1},8,["class","href","target","rel","no-icon"])]))}}),ne=b(Vo,[["__scopeId","data-v-35975db6"]]),So={class:"VPMenuGroup"},To={key:0,class:"title"},No=m({__name:"VPMenuGroup",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),u("div",So,[e.text?(a(),u("p",To,M(e.text),1)):h("",!0),(a(!0),u(A,null,H(e.items,o=>(a(),u(A,null,["link"in o?(a(),k(ne,{key:0,item:o},null,8,["item"])):h("",!0)],64))),256))]))}}),wo=b(No,[["__scopeId","data-v-69e747b5"]]),Io={class:"VPMenu"},Mo={key:0,class:"items"},Co=m({__name:"VPMenu",props:{items:{}},setup(s){return(e,t)=>(a(),u("div",Io,[e.items?(a(),u("div",Mo,[(a(!0),u(A,null,H(e.items,o=>(a(),u(A,{key:JSON.stringify(o)},["link"in o?(a(),k(ne,{key:0,item:o},null,8,["item"])):"component"in o?(a(),k(E(o.component),U({key:1,ref_for:!0},o.props),null,16)):(a(),k(wo,{key:2,text:o.text,items:o.items},null,8,["text","items"]))],64))),128))])):h("",!0),c(e.$slots,"default",{},void 0,!0)]))}}),Ao=b(Co,[["__scopeId","data-v-b98bc113"]]),Ho=["aria-expanded","aria-label"],Bo={key:0,class:"text"},Eo=["innerHTML"],Fo={key:1,class:"vpi-more-horizontal icon"},Do={class:"menu"},Oo=m({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(s){const e=w(!1),t=w();go({el:t,onBlur:o});function o(){e.value=!1}return(n,i)=>(a(),u("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:i[1]||(i[1]=l=>e.value=!0),onMouseleave:i[2]||(i[2]=l=>e.value=!1)},[d("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":n.label,onClick:i[0]||(i[0]=l=>e.value=!e.value)},[n.button||n.icon?(a(),u("span",Bo,[n.icon?(a(),u("span",{key:0,class:I([n.icon,"option-icon"])},null,2)):h("",!0),n.button?(a(),u("span",{key:1,innerHTML:n.button},null,8,Eo)):h("",!0),i[3]||(i[3]=d("span",{class:"vpi-chevron-down text-icon"},null,-1))])):(a(),u("span",Fo))],8,Ho),d("div",Do,[_(Ao,{items:n.items},{default:f(()=>[c(n.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),_e=b(Oo,[["__scopeId","data-v-cf11d7a2"]]),Go=["href","aria-label","innerHTML"],Uo=m({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(s){const e=s,t=w();j(async()=>{var i;await Pe();const n=(i=t.value)==null?void 0:i.children[0];n instanceof HTMLElement&&n.className.startsWith("vpi-social-")&&(getComputedStyle(n).maskImage||getComputedStyle(n).webkitMaskImage)==="none"&&n.style.setProperty("--icon",`url('https://api.iconify.design/simple-icons/${e.icon}.svg')`)});const o=g(()=>typeof e.icon=="object"?e.icon.svg:``);return(n,i)=>(a(),u("a",{ref_key:"el",ref:t,class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:o.value},null,8,Go))}}),jo=b(Uo,[["__scopeId","data-v-bd121fe5"]]),zo={class:"VPSocialLinks"},Ko=m({__name:"VPSocialLinks",props:{links:{}},setup(s){return(e,t)=>(a(),u("div",zo,[(a(!0),u(A,null,H(e.links,({link:o,icon:n,ariaLabel:i})=>(a(),k(jo,{key:o,icon:n,link:o,ariaLabel:i},null,8,["icon","link","ariaLabel"]))),128))]))}}),ke=b(Ko,[["__scopeId","data-v-7bc22406"]]),Wo={key:0,class:"group translations"},qo={class:"trans-title"},Ro={key:1,class:"group"},Jo={class:"item appearance"},Xo={class:"label"},Yo={class:"appearance-action"},Qo={key:2,class:"group"},Zo={class:"item social-links"},xo=m({__name:"VPNavBarExtra",setup(s){const{site:e,theme:t}=V(),{localeLinks:o,currentLang:n}=R({correspondingLink:!0}),i=g(()=>o.value.length&&n.value.label||e.value.appearance||t.value.socialLinks);return(l,v)=>i.value?(a(),k(_e,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:f(()=>[r(o).length&&r(n).label?(a(),u("div",Wo,[d("p",qo,M(r(n).label),1),(a(!0),u(A,null,H(r(o),p=>(a(),k(ne,{key:p.link,item:p},null,8,["item"]))),128))])):h("",!0),r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),u("div",Ro,[d("div",Jo,[d("p",Xo,M(r(t).darkModeSwitchLabel||"Appearance"),1),d("div",Yo,[_(he)])])])):h("",!0),r(t).socialLinks?(a(),u("div",Qo,[d("div",Zo,[_(ke,{class:"social-links-list",links:r(t).socialLinks},null,8,["links"])])])):h("",!0)]),_:1})):h("",!0)}}),es=b(xo,[["__scopeId","data-v-bb2aa2f0"]]),ts=["aria-expanded"],ns=m({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(s){return(e,t)=>(a(),u("button",{type:"button",class:I(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=o=>e.$emit("click"))},t[1]||(t[1]=[d("span",{class:"container"},[d("span",{class:"top"}),d("span",{class:"middle"}),d("span",{class:"bottom"})],-1)]),10,ts))}}),os=b(ns,[["__scopeId","data-v-e5dd9c1c"]]),ss=["innerHTML"],as=m({__name:"VPNavBarMenuLink",props:{item:{}},setup(s){const{page:e}=V();return(t,o)=>(a(),k(F,{class:I({VPNavBarMenuLink:!0,active:r(K)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,tabindex:"0"},{default:f(()=>[d("span",{innerHTML:t.item.text},null,8,ss)]),_:1},8,["class","href","target","rel","no-icon"]))}}),rs=b(as,[["__scopeId","data-v-e56f3d57"]]),is=m({__name:"VPNavBarMenuGroup",props:{item:{}},setup(s){const e=s,{page:t}=V(),o=i=>"component"in i?!1:"link"in i?K(t.value.relativePath,i.link,!!e.item.activeMatch):i.items.some(o),n=g(()=>o(e.item));return(i,l)=>(a(),k(_e,{class:I({VPNavBarMenuGroup:!0,active:r(K)(r(t).relativePath,i.item.activeMatch,!!i.item.activeMatch)||n.value}),button:i.item.text,items:i.item.items},null,8,["class","button","items"]))}}),ls={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},cs=m({__name:"VPNavBarMenu",setup(s){const{theme:e}=V();return(t,o)=>r(e).nav?(a(),u("nav",ls,[o[0]||(o[0]=d("span",{id:"main-nav-aria-label",class:"visually-hidden"}," Main Navigation ",-1)),(a(!0),u(A,null,H(r(e).nav,n=>(a(),u(A,{key:JSON.stringify(n)},["link"in n?(a(),k(rs,{key:0,item:n},null,8,["item"])):"component"in n?(a(),k(E(n.component),U({key:1,ref_for:!0},n.props),null,16)):(a(),k(is,{key:2,item:n},null,8,["item"]))],64))),128))])):h("",!0)}}),us=b(cs,[["__scopeId","data-v-dc692963"]]);function ds(s){const{localeIndex:e,theme:t}=V();function o(n){var L,C,N;const i=n.split("."),l=(L=t.value.search)==null?void 0:L.options,v=l&&typeof l=="object",p=v&&((N=(C=l.locales)==null?void 0:C[e.value])==null?void 0:N.translations)||null,$=v&&l.translations||null;let S=p,y=$,P=s;const T=i.pop();for(const B of i){let G=null;const q=P==null?void 0:P[B];q&&(G=P=q);const oe=y==null?void 0:y[B];oe&&(G=y=oe);const se=S==null?void 0:S[B];se&&(G=S=se),q||(P=G),oe||(y=G),se||(S=G)}return(S==null?void 0:S[T])??(y==null?void 0:y[T])??(P==null?void 0:P[T])??""}return o}const vs=["aria-label"],ps={class:"DocSearch-Button-Container"},fs={class:"DocSearch-Button-Placeholder"},be=m({__name:"VPNavBarSearchButton",setup(s){const t=ds({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(o,n)=>(a(),u("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":r(t)("button.buttonAriaLabel")},[d("span",ps,[n[0]||(n[0]=d("span",{class:"vp-icon DocSearch-Search-Icon"},null,-1)),d("span",fs,M(r(t)("button.buttonText")),1)]),n[1]||(n[1]=d("span",{class:"DocSearch-Button-Keys"},[d("kbd",{class:"DocSearch-Button-Key"}),d("kbd",{class:"DocSearch-Button-Key"},"K")],-1))],8,vs))}}),hs={class:"VPNavBarSearch"},ms={id:"local-search"},_s={key:1,id:"docsearch"},ks=m({__name:"VPNavBarSearch",setup(s){const e=()=>null,t=Ue(()=>je(()=>import("./VPAlgoliaSearchBox.BlguZ0-2.js"),__vite__mapDeps([0,1]))),{theme:o}=V(),n=w(!1),i=w(!1),l=()=>{const P="VPAlgoliaPreconnect";(window.requestIdleCallback||setTimeout)(()=>{var C;const L=document.createElement("link");L.id=P,L.rel="preconnect",L.href=`https://${(((C=o.value.search)==null?void 0:C.options)??o.value.algolia).appId}-dsn.algolia.net`,L.crossOrigin="",document.head.appendChild(L)})};j(()=>{l();const P=L=>{(L.key.toLowerCase()==="k"&&(L.metaKey||L.ctrlKey)||!$(L)&&L.key==="/")&&(L.preventDefault(),v(),T())},T=()=>{window.removeEventListener("keydown",P)};window.addEventListener("keydown",P),Q(T)});function v(){n.value||(n.value=!0,setTimeout(p,16))}function p(){const P=new Event("keydown");P.key="k",P.metaKey=!0,window.dispatchEvent(P),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||p()},16)}function $(P){const T=P.target,L=T.tagName;return T.isContentEditable||L==="INPUT"||L==="SELECT"||L==="TEXTAREA"}const S=w(!1),y="algolia";return(P,T)=>{var L;return a(),u("div",hs,[r(y)==="local"?(a(),u(A,{key:0},[S.value?(a(),k(r(e),{key:0,onClose:T[0]||(T[0]=C=>S.value=!1)})):h("",!0),d("div",ms,[_(be,{onClick:T[1]||(T[1]=C=>S.value=!0)})])],64)):r(y)==="algolia"?(a(),u(A,{key:1},[n.value?(a(),k(r(t),{key:0,algolia:((L=r(o).search)==null?void 0:L.options)??r(o).algolia,onVnodeBeforeMount:T[2]||(T[2]=C=>i.value=!0)},null,8,["algolia"])):h("",!0),i.value?h("",!0):(a(),u("div",_s,[_(be,{onClick:v})]))],64)):h("",!0)])}}}),bs=m({__name:"VPNavBarSocialLinks",setup(s){const{theme:e}=V();return(t,o)=>r(e).socialLinks?(a(),k(ke,{key:0,class:"VPNavBarSocialLinks",links:r(e).socialLinks},null,8,["links"])):h("",!0)}}),gs=b(bs,[["__scopeId","data-v-0394ad82"]]),$s=["href","rel","target"],ys=["innerHTML"],Ps={key:2},Ls=m({__name:"VPNavBarTitle",setup(s){const{site:e,theme:t}=V(),{hasSidebar:o}=O(),{currentLang:n}=R(),i=g(()=>{var p;return typeof t.value.logoLink=="string"?t.value.logoLink:(p=t.value.logoLink)==null?void 0:p.link}),l=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.rel}),v=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.target});return(p,$)=>(a(),u("div",{class:I(["VPNavBarTitle",{"has-sidebar":r(o)}])},[d("a",{class:"title",href:i.value??r(pe)(r(n).link),rel:l.value,target:v.value},[c(p.$slots,"nav-bar-title-before",{},void 0,!0),r(t).logo?(a(),k(X,{key:0,class:"logo",image:r(t).logo},null,8,["image"])):h("",!0),r(t).siteTitle?(a(),u("span",{key:1,innerHTML:r(t).siteTitle},null,8,ys)):r(t).siteTitle===void 0?(a(),u("span",Ps,M(r(e).title),1)):h("",!0),c(p.$slots,"nav-bar-title-after",{},void 0,!0)],8,$s)],2))}}),Vs=b(Ls,[["__scopeId","data-v-1168a8e4"]]),Ss={class:"items"},Ts={class:"title"},Ns=m({__name:"VPNavBarTranslations",setup(s){const{theme:e}=V(),{localeLinks:t,currentLang:o}=R({correspondingLink:!0});return(n,i)=>r(t).length&&r(o).label?(a(),k(_e,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:r(e).langMenuLabel||"Change language"},{default:f(()=>[d("div",Ss,[d("p",Ts,M(r(o).label),1),(a(!0),u(A,null,H(r(t),l=>(a(),k(ne,{key:l.link,item:l},null,8,["item"]))),128))])]),_:1},8,["label"])):h("",!0)}}),ws=b(Ns,[["__scopeId","data-v-88af2de4"]]),Is={class:"wrapper"},Ms={class:"container"},Cs={class:"title"},As={class:"content"},Hs={class:"content-body"},Bs=m({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(s){const e=s,{y:t}=Le(),{hasSidebar:o}=O(),{frontmatter:n}=V(),i=w({});return ve(()=>{i.value={"has-sidebar":o.value,home:n.value.layout==="home",top:t.value===0,"screen-open":e.isScreenOpen}}),(l,v)=>(a(),u("div",{class:I(["VPNavBar",i.value])},[d("div",Is,[d("div",Ms,[d("div",Cs,[_(Vs,null,{"nav-bar-title-before":f(()=>[c(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":f(()=>[c(l.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),d("div",As,[d("div",Hs,[c(l.$slots,"nav-bar-content-before",{},void 0,!0),_(ks,{class:"search"}),_(us,{class:"menu"}),_(ws,{class:"translations"}),_(bo,{class:"appearance"}),_(gs,{class:"social-links"}),_(es,{class:"extra"}),c(l.$slots,"nav-bar-content-after",{},void 0,!0),_(os,{class:"hamburger",active:l.isScreenOpen,onClick:v[0]||(v[0]=p=>l.$emit("toggle-screen"))},null,8,["active"])])])])]),v[1]||(v[1]=d("div",{class:"divider"},[d("div",{class:"divider-line"})],-1))],2))}}),Es=b(Bs,[["__scopeId","data-v-6aa21345"]]),Fs={key:0,class:"VPNavScreenAppearance"},Ds={class:"text"},Os=m({__name:"VPNavScreenAppearance",setup(s){const{site:e,theme:t}=V();return(o,n)=>r(e).appearance&&r(e).appearance!=="force-dark"&&r(e).appearance!=="force-auto"?(a(),u("div",Fs,[d("p",Ds,M(r(t).darkModeSwitchLabel||"Appearance"),1),_(he)])):h("",!0)}}),Gs=b(Os,[["__scopeId","data-v-b44890b2"]]),Us=["innerHTML"],js=m({__name:"VPNavScreenMenuLink",props:{item:{}},setup(s){const e=ee("close-screen");return(t,o)=>(a(),k(F,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,onClick:r(e)},{default:f(()=>[d("span",{innerHTML:t.item.text},null,8,Us)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),zs=b(js,[["__scopeId","data-v-df37e6dd"]]),Ks=["innerHTML"],Ws=m({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(s){const e=ee("close-screen");return(t,o)=>(a(),k(F,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,"no-icon":t.item.noIcon,onClick:r(e)},{default:f(()=>[d("span",{innerHTML:t.item.text},null,8,Ks)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),Ce=b(Ws,[["__scopeId","data-v-3e9c20e4"]]),qs={class:"VPNavScreenMenuGroupSection"},Rs={key:0,class:"title"},Js=m({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(s){return(e,t)=>(a(),u("div",qs,[e.text?(a(),u("p",Rs,M(e.text),1)):h("",!0),(a(!0),u(A,null,H(e.items,o=>(a(),k(Ce,{key:o.text,item:o},null,8,["item"]))),128))]))}}),Xs=b(Js,[["__scopeId","data-v-8133b170"]]),Ys=["aria-controls","aria-expanded"],Qs=["innerHTML"],Zs=["id"],xs={key:0,class:"item"},ea={key:1,class:"item"},ta={key:2,class:"group"},na=m({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(s){const e=s,t=w(!1),o=g(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function n(){t.value=!t.value}return(i,l)=>(a(),u("div",{class:I(["VPNavScreenMenuGroup",{open:t.value}])},[d("button",{class:"button","aria-controls":o.value,"aria-expanded":t.value,onClick:n},[d("span",{class:"button-text",innerHTML:i.text},null,8,Qs),l[0]||(l[0]=d("span",{class:"vpi-plus button-icon"},null,-1))],8,Ys),d("div",{id:o.value,class:"items"},[(a(!0),u(A,null,H(i.items,v=>(a(),u(A,{key:JSON.stringify(v)},["link"in v?(a(),u("div",xs,[_(Ce,{item:v},null,8,["item"])])):"component"in v?(a(),u("div",ea,[(a(),k(E(v.component),U({ref_for:!0},v.props,{"screen-menu":""}),null,16))])):(a(),u("div",ta,[_(Xs,{text:v.text,items:v.items},null,8,["text","items"])]))],64))),128))],8,Zs)],2))}}),oa=b(na,[["__scopeId","data-v-b9ab8c58"]]),sa={key:0,class:"VPNavScreenMenu"},aa=m({__name:"VPNavScreenMenu",setup(s){const{theme:e}=V();return(t,o)=>r(e).nav?(a(),u("nav",sa,[(a(!0),u(A,null,H(r(e).nav,n=>(a(),u(A,{key:JSON.stringify(n)},["link"in n?(a(),k(zs,{key:0,item:n},null,8,["item"])):"component"in n?(a(),k(E(n.component),U({key:1,ref_for:!0},n.props,{"screen-menu":""}),null,16)):(a(),k(oa,{key:2,text:n.text||"",items:n.items},null,8,["text","items"]))],64))),128))])):h("",!0)}}),ra=m({__name:"VPNavScreenSocialLinks",setup(s){const{theme:e}=V();return(t,o)=>r(e).socialLinks?(a(),k(ke,{key:0,class:"VPNavScreenSocialLinks",links:r(e).socialLinks},null,8,["links"])):h("",!0)}}),ia={class:"list"},la=m({__name:"VPNavScreenTranslations",setup(s){const{localeLinks:e,currentLang:t}=R({correspondingLink:!0}),o=w(!1);function n(){o.value=!o.value}return(i,l)=>r(e).length&&r(t).label?(a(),u("div",{key:0,class:I(["VPNavScreenTranslations",{open:o.value}])},[d("button",{class:"title",onClick:n},[l[0]||(l[0]=d("span",{class:"vpi-languages icon lang"},null,-1)),z(" "+M(r(t).label)+" ",1),l[1]||(l[1]=d("span",{class:"vpi-chevron-down icon chevron"},null,-1))]),d("ul",ia,[(a(!0),u(A,null,H(r(e),v=>(a(),u("li",{key:v.link,class:"item"},[_(F,{class:"link",href:v.link},{default:f(()=>[z(M(v.text),1)]),_:2},1032,["href"])]))),128))])],2)):h("",!0)}}),ca=b(la,[["__scopeId","data-v-858fe1a4"]]),ua={class:"container"},da=m({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(s){const e=w(null),t=Ve(te?document.body:null);return(o,n)=>(a(),k(ue,{name:"fade",onEnter:n[0]||(n[0]=i=>t.value=!0),onAfterLeave:n[1]||(n[1]=i=>t.value=!1)},{default:f(()=>[o.open?(a(),u("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[d("div",ua,[c(o.$slots,"nav-screen-content-before",{},void 0,!0),_(aa,{class:"menu"}),_(ca,{class:"translations"}),_(Gs,{class:"appearance"}),_(ra,{class:"social-links"}),c(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):h("",!0)]),_:3}))}}),va=b(da,[["__scopeId","data-v-f2779853"]]),pa={key:0,class:"VPNav"},fa=m({__name:"VPNav",setup(s){const{isScreenOpen:e,closeScreen:t,toggleScreen:o}=lo(),{frontmatter:n}=V(),i=g(()=>n.value.navbar!==!1);return Se("close-screen",t),Y(()=>{te&&document.documentElement.classList.toggle("hide-nav",!i.value)}),(l,v)=>i.value?(a(),u("header",pa,[_(Es,{"is-screen-open":r(e),onToggleScreen:r(o)},{"nav-bar-title-before":f(()=>[c(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":f(()=>[c(l.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":f(()=>[c(l.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":f(()=>[c(l.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),_(va,{open:r(e)},{"nav-screen-content-before":f(()=>[c(l.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":f(()=>[c(l.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):h("",!0)}}),ha=b(fa,[["__scopeId","data-v-ae24b3ad"]]),ma=["role","tabindex"],_a={key:1,class:"items"},ka=m({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(s){const e=s,{collapsed:t,collapsible:o,isLink:n,isActiveLink:i,hasActiveLink:l,hasChildren:v,toggle:p}=dt(g(()=>e.item)),$=g(()=>v.value?"section":"div"),S=g(()=>n.value?"a":"div"),y=g(()=>v.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),P=g(()=>n.value?void 0:"button"),T=g(()=>[[`level-${e.depth}`],{collapsible:o.value},{collapsed:t.value},{"is-link":n.value},{"is-active":i.value},{"has-active":l.value}]);function L(N){"key"in N&&N.key!=="Enter"||!e.item.link&&p()}function C(){e.item.link&&p()}return(N,B)=>{const G=W("VPSidebarItem",!0);return a(),k(E($.value),{class:I(["VPSidebarItem",T.value])},{default:f(()=>[N.item.text?(a(),u("div",U({key:0,class:"item",role:P.value},ze(N.item.items?{click:L,keydown:L}:{},!0),{tabindex:N.item.items&&0}),[B[1]||(B[1]=d("div",{class:"indicator"},null,-1)),N.item.link?(a(),k(F,{key:0,tag:S.value,class:"link",href:N.item.link,rel:N.item.rel,target:N.item.target},{default:f(()=>[(a(),k(E(y.value),{class:"text",innerHTML:N.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),k(E(y.value),{key:1,class:"text",innerHTML:N.item.text},null,8,["innerHTML"])),N.item.collapsed!=null&&N.item.items&&N.item.items.length?(a(),u("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:C,onKeydown:Ke(C,["enter"]),tabindex:"0"},B[0]||(B[0]=[d("span",{class:"vpi-chevron-right caret-icon"},null,-1)]),32)):h("",!0)],16,ma)):h("",!0),N.item.items&&N.item.items.length?(a(),u("div",_a,[N.depth<5?(a(!0),u(A,{key:0},H(N.item.items,q=>(a(),k(G,{key:q.text,item:q,depth:N.depth+1},null,8,["item","depth"]))),128)):h("",!0)])):h("",!0)]),_:1},8,["class"])}}}),ba=b(ka,[["__scopeId","data-v-b3fd67f8"]]),ga=m({__name:"VPSidebarGroup",props:{items:{}},setup(s){const e=w(!0);let t=null;return j(()=>{t=setTimeout(()=>{t=null,e.value=!1},300)}),We(()=>{t!=null&&(clearTimeout(t),t=null)}),(o,n)=>(a(!0),u(A,null,H(o.items,i=>(a(),u("div",{key:i.text,class:I(["group",{"no-transition":e.value}])},[_(ba,{item:i,depth:0},null,8,["item"])],2))),128))}}),$a=b(ga,[["__scopeId","data-v-c40bc020"]]),ya={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Pa=m({__name:"VPSidebar",props:{open:{type:Boolean}},setup(s){const{sidebarGroups:e,hasSidebar:t}=O(),o=s,n=w(null),i=Ve(te?document.body:null);D([o,n],()=>{var v;o.open?(i.value=!0,(v=n.value)==null||v.focus()):i.value=!1},{immediate:!0,flush:"post"});const l=w(0);return D(e,()=>{l.value+=1},{deep:!0}),(v,p)=>r(t)?(a(),u("aside",{key:0,class:I(["VPSidebar",{open:v.open}]),ref_key:"navEl",ref:n,onClick:p[0]||(p[0]=qe(()=>{},["stop"]))},[p[2]||(p[2]=d("div",{class:"curtain"},null,-1)),d("nav",ya,[p[1]||(p[1]=d("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),c(v.$slots,"sidebar-nav-before",{},void 0,!0),(a(),k($a,{items:r(e),key:l.value},null,8,["items"])),c(v.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):h("",!0)}}),La=b(Pa,[["__scopeId","data-v-319d5ca6"]]),Va=m({__name:"VPSkipLink",setup(s){const{theme:e}=V(),t=x(),o=w();D(()=>t.path,()=>o.value.focus());function n({target:i}){const l=document.getElementById(decodeURIComponent(i.hash).slice(1));if(l){const v=()=>{l.removeAttribute("tabindex"),l.removeEventListener("blur",v)};l.setAttribute("tabindex","-1"),l.addEventListener("blur",v),l.focus(),window.scrollTo(0,0)}}return(i,l)=>(a(),u(A,null,[d("span",{ref_key:"backToTop",ref:o,tabindex:"-1"},null,512),d("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:n},M(r(e).skipToContentLabel||"Skip to content"),1)],64))}}),Sa=b(Va,[["__scopeId","data-v-0b0ada53"]]),Ta=m({__name:"Layout",setup(s){const{isOpen:e,open:t,close:o}=O(),n=x();D(()=>n.path,o),ut(e,o);const{frontmatter:i}=V(),l=Re(),v=g(()=>!!l["home-hero-image"]);return Se("hero-image-slot-exists",v),(p,$)=>{const S=W("Content");return r(i).layout!==!1?(a(),u("div",{key:0,class:I(["Layout",r(i).pageClass])},[c(p.$slots,"layout-top",{},void 0,!0),_(Sa),_(Qe,{class:"backdrop",show:r(e),onClick:r(o)},null,8,["show","onClick"]),_(ha,null,{"nav-bar-title-before":f(()=>[c(p.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":f(()=>[c(p.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":f(()=>[c(p.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":f(()=>[c(p.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":f(()=>[c(p.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":f(()=>[c(p.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),_(io,{open:r(e),onOpenMenu:r(t)},null,8,["open","onOpenMenu"]),_(La,{open:r(e)},{"sidebar-nav-before":f(()=>[c(p.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":f(()=>[c(p.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),_(Wn,null,{"page-top":f(()=>[c(p.$slots,"page-top",{},void 0,!0)]),"page-bottom":f(()=>[c(p.$slots,"page-bottom",{},void 0,!0)]),"not-found":f(()=>[c(p.$slots,"not-found",{},void 0,!0)]),"home-hero-before":f(()=>[c(p.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":f(()=>[c(p.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":f(()=>[c(p.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":f(()=>[c(p.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":f(()=>[c(p.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":f(()=>[c(p.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":f(()=>[c(p.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":f(()=>[c(p.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":f(()=>[c(p.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":f(()=>[c(p.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":f(()=>[c(p.$slots,"doc-before",{},void 0,!0)]),"doc-after":f(()=>[c(p.$slots,"doc-after",{},void 0,!0)]),"doc-top":f(()=>[c(p.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":f(()=>[c(p.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":f(()=>[c(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":f(()=>[c(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":f(()=>[c(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":f(()=>[c(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":f(()=>[c(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":f(()=>[c(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),_(Yn),c(p.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),k(S,{key:1}))}}}),Na=b(Ta,[["__scopeId","data-v-5d98c3a5"]]),Ia={Layout:Na,enhanceApp:({app:s})=>{s.component("Badge",Je)}};export{Ia as t,V as u}; diff --git a/assets/chunks/theme.b9d97670.js b/assets/chunks/theme.b9d97670.js deleted file mode 100644 index 7ec24ee65c..0000000000 --- a/assets/chunks/theme.b9d97670.js +++ /dev/null @@ -1,7 +0,0 @@ -import{u as g,v as a,b as i,z as c,a as T,L as x,X as S,_ as m,C as b,O as v,$ as he,B as f,c as et,i as tt,P as nt,w as fe,r as k,d as w,A as F,F as u,N as l,e as z,f as D,o as st,g as ot,q as K,H as J,h as at,j as W,k as te,l as ie,T as rt,M as U,m as C,n as H,p as me,s as Z,t as h,x as j,E as De,V as se,y as ge,D as Fe,G as lt,R as it,I as Oe,J as xe,K as ct,Q as ut,S as dt,U as oe,W as _t,Y as vt,Z as pt,a0 as ht,a1 as ft}from"./framework.70afa331.js";const mt=g({__name:"VPBadge",props:{text:{},type:{}},setup(n){return(e,t)=>(a(),i("span",{class:T(["VPBadge",e.type??"tip"])},[c(e.$slots,"default",{},()=>[x(S(e.text),1)],!0)],2))}});const gt=m(mt,[["__scopeId","data-v-f026a7e7"]]),yt={key:0,class:"VPBackdrop"},bt=g({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(n){return(e,t)=>(a(),b(he,{name:"fade"},{default:v(()=>[e.show?(a(),i("div",yt)):f("",!0)]),_:1}))}});const kt=m(bt,[["__scopeId","data-v-c79a1216"]]),P=et;function $t(n,e){let t,s=!1;return()=>{t&&clearTimeout(t),s?t=setTimeout(n,e):(n(),s=!0,setTimeout(()=>{s=!1},e))}}function _e(n){return/^\//.test(n)?n:`/${n}`}function ee(n){if(tt(n))return n.replace(nt,"");const{site:e}=P(),{pathname:t,search:s,hash:o}=new URL(n,"http://a.com"),r=t.endsWith("/")||t.endsWith(".html")?n:n.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,e.value.cleanUrls?"":".html")}${s}${o}`);return fe(r)}function ne({removeCurrent:n=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:s,page:o,theme:r}=P(),d=k(()=>{var _,y;return{label:(_=t.value.locales[s.value])==null?void 0:_.label,link:((y=t.value.locales[s.value])==null?void 0:y.link)||(s.value==="root"?"/":`/${s.value}/`)}});return{localeLinks:k(()=>Object.entries(t.value.locales).flatMap(([_,y])=>n&&d.value.label===y.label?[]:{text:y.label,link:Pt(y.link||(_==="root"?"/":`/${_}/`),r.value.i18nRouting!==!1&&e,o.value.relativePath.slice(d.value.link.length-1),!t.value.cleanUrls)})),currentLang:d}}function Pt(n,e,t,s){return e?n.replace(/\/$/,"")+_e(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,s?".html":"")):n}const ce=n=>(z("data-v-c70503b8"),n=n(),D(),n),Vt={class:"NotFound"},wt=ce(()=>u("p",{class:"code"},"404",-1)),St=ce(()=>u("h1",{class:"title"},"PAGE NOT FOUND",-1)),Lt=ce(()=>u("div",{class:"divider"},null,-1)),Mt=ce(()=>u("blockquote",{class:"quote"}," But if you don't change your direction, and if you keep looking, you may end up where you are heading. ",-1)),Ct={class:"action"},It=["href"],Tt=g({__name:"NotFound",setup(n){const{site:e}=P(),{localeLinks:t}=ne({removeCurrent:!1}),s=w("/");return F(()=>{var r;const o=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");t.value.length&&(s.value=((r=t.value.find(({link:d})=>d.startsWith(o)))==null?void 0:r.link)||t.value[0].link)}),(o,r)=>(a(),i("div",Vt,[wt,St,Lt,Mt,u("div",Ct,[u("a",{class:"link",href:l(fe)(s.value),"aria-label":"go to home"}," Take me home ",8,It)])]))}});const Bt=m(Tt,[["__scopeId","data-v-c70503b8"]]);function Ge(n){return st()?(ot(n),!0):!1}function ye(n){return typeof n=="function"?n():l(n)}const At=typeof window<"u",Nt=()=>{};function xt(n){var e;const t=ye(n);return(e=t==null?void 0:t.$el)!=null?e:t}const be=At?window:void 0;function Ht(...n){let e,t,s,o;if(typeof n[0]=="string"||Array.isArray(n[0])?([t,s,o]=n,e=be):[e,t,s,o]=n,!e)return Nt;Array.isArray(t)||(t=[t]),Array.isArray(s)||(s=[s]);const r=[],d=()=>{r.forEach(L=>L()),r.length=0},p=(L,A,I,V)=>(L.addEventListener(A,I,V),()=>L.removeEventListener(A,I,V)),_=K(()=>[xt(e),ye(o)],([L,A])=>{d(),L&&r.push(...t.flatMap(I=>s.map(V=>p(L,I,V,A))))},{immediate:!0,flush:"post"}),y=()=>{_(),d()};return Ge(y),y}function Et(){const n=w(!1);return at()&&F(()=>{n.value=!0}),n}function zt(n){const e=Et();return k(()=>(e.value,!!n()))}function ve(n,e={}){const{window:t=be}=e,s=zt(()=>t&&"matchMedia"in t&&typeof t.matchMedia=="function");let o;const r=w(!1),d=y=>{r.value=y.matches},p=()=>{o&&("removeEventListener"in o?o.removeEventListener("change",d):o.removeListener(d))},_=J(()=>{s.value&&(p(),o=t.matchMedia(ye(n)),"addEventListener"in o?o.addEventListener("change",d):o.addListener(d),r.value=o.matches)});return Ge(()=>{_(),p(),o=void 0}),r}function Re({window:n=be}={}){if(!n)return{x:w(0),y:w(0)};const e=w(n.scrollX),t=w(n.scrollY);return Ht(n,"scroll",()=>{e.value=n.scrollX,t.value=n.scrollY},{capture:!1,passive:!0}),{x:e,y:t}}function Ue(n,e){if(Array.isArray(n))return n;if(n==null)return[];e=_e(e);const t=Object.keys(n).sort((s,o)=>o.split("/").length-s.split("/").length).find(s=>e.startsWith(_e(s)));return t?n[t]:[]}function Dt(n){const e=[];let t=0;for(const s in n){const o=n[s];if(o.items){t=e.push(o);continue}e[t]||e.push({items:[]}),e[t].items.push(o)}return e}function Ft(n){const e=[];function t(s){for(const o of s)o.text&&o.link&&e.push({text:o.text,link:o.link}),o.items&&t(o.items)}return t(n),e}function pe(n,e){return Array.isArray(e)?e.some(t=>pe(n,t)):W(n,e.link)?!0:e.items?pe(n,e.items):!1}function O(){const n=te(),{theme:e,frontmatter:t}=P(),s=ve("(min-width: 960px)"),o=w(!1),r=k(()=>{const N=e.value.sidebar,M=n.data.relativePath;return N?Ue(N,M):[]}),d=k(()=>t.value.sidebar!==!1&&r.value.length>0&&t.value.layout!=="home"),p=k(()=>_?t.value.aside==null?e.value.aside==="left":t.value.aside==="left":!1),_=k(()=>t.value.layout==="home"?!1:t.value.aside!=null?!!t.value.aside:e.value.aside!==!1),y=k(()=>d.value&&s.value),L=k(()=>d.value?Dt(r.value):[]);function A(){o.value=!0}function I(){o.value=!1}function V(){o.value?I():A()}return{isOpen:o,sidebar:r,sidebarGroups:L,hasSidebar:d,hasAside:_,leftAside:p,isSidebarEnabled:y,open:A,close:I,toggle:V}}function Ot(n,e){let t;J(()=>{t=n.value?document.activeElement:void 0}),F(()=>{window.addEventListener("keyup",s)}),ie(()=>{window.removeEventListener("keyup",s)});function s(o){o.key==="Escape"&&n.value&&(e(),t==null||t.focus())}}function Gt(n){const{page:e}=P(),t=w(!1),s=k(()=>n.value.collapsed!=null),o=k(()=>!!n.value.link),r=k(()=>W(e.value.relativePath,n.value.link)),d=k(()=>r.value?!0:n.value.items?pe(e.value.relativePath,n.value.items):!1),p=k(()=>!!(n.value.items&&n.value.items.length));J(()=>{t.value=!!(s.value&&n.value.collapsed)}),J(()=>{(r.value||d.value)&&(t.value=!1)});function _(){s.value&&(t.value=!t.value)}return{collapsed:t,collapsible:s,isLink:o,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}}function Rt(){const{hasSidebar:n}=O(),e=ve("(min-width: 960px)"),t=ve("(min-width: 1280px)");return{isAsideEnabled:k(()=>!t.value&&!e.value?!1:n.value?t.value:e.value)}}const Ut=71;function ke(n){return typeof n.outline=="object"&&!Array.isArray(n.outline)&&n.outline.label||n.outlineTitle||"On this page"}function $e(n){const e=[...document.querySelectorAll(".VPDoc h2,h3,h4,h5,h6")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const s=Number(t.tagName[1]);return{title:jt(t),link:"#"+t.id,level:s}});return qt(e,n)}function jt(n){let e="";for(const t of n.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function qt(n,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[s,o]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;n=n.filter(d=>d.level>=s&&d.level<=o);const r=[];e:for(let d=0;d=0;_--){const y=n[_];if(y.level{requestAnimationFrame(r),window.addEventListener("scroll",s)}),rt(()=>{d(location.hash)}),ie(()=>{window.removeEventListener("scroll",s)});function r(){if(!t.value)return;const p=[].slice.call(n.value.querySelectorAll(".outline-link")),_=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(V=>p.some(N=>N.hash===V.hash&&V.offsetParent!==null)),y=window.scrollY,L=window.innerHeight,A=document.body.offsetHeight,I=Math.abs(y+L-A)<1;if(_.length&&I){d(_[_.length-1].hash);return}for(let V=0;V<_.length;V++){const N=_[V],M=_[V+1],[$,B]=Wt(V,N,M);if($){d(B);return}}}function d(p){o&&o.classList.remove("active"),p!==null&&(o=n.value.querySelector(`a[href="${decodeURIComponent(p)}"]`));const _=o;_?(_.classList.add("active"),e.value.style.top=_.offsetTop+33+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function He(n){return n.parentElement.offsetTop-Ut}function Wt(n,e,t){const s=window.scrollY;return n===0&&s===0?[!0,null]:s{const o=U("VPDocOutlineItem",!0);return a(),i("ul",{class:T(t.root?"root":"nested")},[(a(!0),i(C,null,H(t.headers,({children:r,link:d,title:p})=>(a(),i("li",null,[u("a",{class:"outline-link",href:d,onClick:e,title:p},S(p),9,Yt),r!=null&&r.length?(a(),b(o,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}});const Pe=m(Xt,[["__scopeId","data-v-b0ff2abe"]]),Qt=n=>(z("data-v-ff0f39c8"),n=n(),D(),n),Jt={class:"content"},Zt={class:"outline-title"},en={"aria-labelledby":"doc-outline-aria-label"},tn=Qt(()=>u("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),nn=g({__name:"VPDocAsideOutline",setup(n){const{frontmatter:e,theme:t}=P(),s=me([]);Z(()=>{s.value=$e(e.value.outline??t.value.outline)});const o=w(),r=w();return Kt(o,r),(d,p)=>(a(),i("div",{class:T(["VPDocAsideOutline",{"has-outline":s.value.length>0}]),ref_key:"container",ref:o},[u("div",Jt,[u("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),u("div",Zt,S(l(ke)(l(t))),1),u("nav",en,[tn,h(Pe,{headers:s.value,root:!0},null,8,["headers"])])])],2))}});const sn=m(nn,[["__scopeId","data-v-ff0f39c8"]]),on={class:"VPDocAsideCarbonAds"},an=g({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(n){const e=()=>null;return(t,s)=>(a(),i("div",on,[h(l(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),rn=n=>(z("data-v-3f215769"),n=n(),D(),n),ln={class:"VPDocAside"},cn=rn(()=>u("div",{class:"spacer"},null,-1)),un=g({__name:"VPDocAside",setup(n){const{theme:e}=P();return(t,s)=>(a(),i("div",ln,[c(t.$slots,"aside-top",{},void 0,!0),c(t.$slots,"aside-outline-before",{},void 0,!0),h(sn),c(t.$slots,"aside-outline-after",{},void 0,!0),cn,c(t.$slots,"aside-ads-before",{},void 0,!0),l(e).carbonAds?(a(),b(an,{key:0,"carbon-ads":l(e).carbonAds},null,8,["carbon-ads"])):f("",!0),c(t.$slots,"aside-ads-after",{},void 0,!0),c(t.$slots,"aside-bottom",{},void 0,!0)]))}});const dn=m(un,[["__scopeId","data-v-3f215769"]]);function _n(){const{theme:n,page:e}=P();return k(()=>{const{text:t="Edit this page",pattern:s=""}=n.value.editLink||{};let o;return typeof s=="function"?o=s(e.value):o=s.replace(/:path/g,e.value.filePath),{url:o,text:t}})}function vn(){const{page:n,theme:e,frontmatter:t}=P();return k(()=>{var _,y,L,A,I,V;const s=Ue(e.value.sidebar,n.value.relativePath),o=Ft(s),r=o.findIndex(N=>W(n.value.relativePath,N.link)),d=((_=e.value.docFooter)==null?void 0:_.prev)===!1&&!t.value.prev||t.value.prev===!1,p=((y=e.value.docFooter)==null?void 0:y.next)===!1&&!t.value.next||t.value.next===!1;return{prev:d?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((L=o[r-1])==null?void 0:L.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((A=o[r-1])==null?void 0:A.link)},next:p?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((I=o[r+1])==null?void 0:I.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((V=o[r+1])==null?void 0:V.link)}}})}const pn={},hn={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},fn=u("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),mn=u("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),gn=[fn,mn];function yn(n,e){return a(),i("svg",hn,gn)}const bn=m(pn,[["render",yn]]),G=g({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(n){const e=n,t=k(()=>e.tag??(e.href?"a":"span")),s=k(()=>e.href&&De.test(e.href));return(o,r)=>(a(),b(j(t.value),{class:T(["VPLink",{link:o.href,"vp-external-link-icon":s.value,"no-icon":o.noIcon}]),href:o.href?l(ee)(o.href):void 0,target:o.target??(s.value?"_blank":void 0),rel:o.rel??(s.value?"noreferrer":void 0)},{default:v(()=>[c(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),kn={class:"VPLastUpdated"},$n=["datetime"],Pn=g({__name:"VPDocFooterLastUpdated",setup(n){const{theme:e,page:t}=P(),s=k(()=>new Date(t.value.lastUpdated)),o=k(()=>s.value.toISOString()),r=w("");return F(()=>{J(()=>{var d;r.value=new Intl.DateTimeFormat(void 0,((d=e.value.lastUpdated)==null?void 0:d.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(s.value)})}),(d,p)=>{var _;return a(),i("p",kn,[x(S(((_=l(e).lastUpdated)==null?void 0:_.text)||l(e).lastUpdatedText||"Last updated")+": ",1),u("time",{datetime:o.value},S(r.value),9,$n)])}}});const Vn=m(Pn,[["__scopeId","data-v-149a99df"]]),wn={key:0,class:"VPDocFooter"},Sn={key:0,class:"edit-info"},Ln={key:0,class:"edit-link"},Mn={key:1,class:"last-updated"},Cn={key:1,class:"prev-next"},In={class:"pager"},Tn=["href"],Bn=["innerHTML"],An=["innerHTML"],Nn={class:"pager"},xn=["href"],Hn=["innerHTML"],En=["innerHTML"],zn=g({__name:"VPDocFooter",setup(n){const{theme:e,page:t,frontmatter:s}=P(),o=_n(),r=vn(),d=k(()=>e.value.editLink&&s.value.editLink!==!1),p=k(()=>t.value.lastUpdated&&s.value.lastUpdated!==!1),_=k(()=>d.value||p.value||r.value.prev||r.value.next);return(y,L)=>{var A,I,V,N,M,$;return _.value?(a(),i("footer",wn,[c(y.$slots,"doc-footer-before",{},void 0,!0),d.value||p.value?(a(),i("div",Sn,[d.value?(a(),i("div",Ln,[h(G,{class:"edit-link-button",href:l(o).url,"no-icon":!0},{default:v(()=>[h(bn,{class:"edit-link-icon","aria-label":"edit icon"}),x(" "+S(l(o).text),1)]),_:1},8,["href"])])):f("",!0),p.value?(a(),i("div",Mn,[h(Vn)])):f("",!0)])):f("",!0),(A=l(r).prev)!=null&&A.link||(I=l(r).next)!=null&&I.link?(a(),i("nav",Cn,[u("div",In,[(V=l(r).prev)!=null&&V.link?(a(),i("a",{key:0,class:"pager-link prev",href:l(ee)(l(r).prev.link)},[u("span",{class:"desc",innerHTML:((N=l(e).docFooter)==null?void 0:N.prev)||"Previous page"},null,8,Bn),u("span",{class:"title",innerHTML:l(r).prev.text},null,8,An)],8,Tn)):f("",!0)]),u("div",Nn,[(M=l(r).next)!=null&&M.link?(a(),i("a",{key:0,class:"pager-link next",href:l(ee)(l(r).next.link)},[u("span",{class:"desc",innerHTML:(($=l(e).docFooter)==null?void 0:$.next)||"Next page"},null,8,Hn),u("span",{class:"title",innerHTML:l(r).next.text},null,8,En)],8,xn)):f("",!0)])])):f("",!0)])):f("",!0)}}});const Dn=m(zn,[["__scopeId","data-v-37656e44"]]),Fn={},On={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Gn=u("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),Rn=[Gn];function Un(n,e){return a(),i("svg",On,Rn)}const Ve=m(Fn,[["render",Un]]),jn={key:0,class:"VPDocOutlineDropdown"},qn={key:0,class:"items"},Kn=g({__name:"VPDocOutlineDropdown",setup(n){const{frontmatter:e,theme:t}=P(),s=w(!1);Z(()=>{s.value=!1});const o=me([]);return Z(()=>{o.value=$e(e.value.outline??t.value.outline)}),(r,d)=>o.value.length>0?(a(),i("div",jn,[u("button",{onClick:d[0]||(d[0]=p=>s.value=!s.value),class:T({open:s.value})},[x(S(l(ke)(l(t)))+" ",1),h(Ve,{class:"icon"})],2),s.value?(a(),i("div",qn,[h(Pe,{headers:o.value},null,8,["headers"])])):f("",!0)])):f("",!0)}});const Wn=m(Kn,[["__scopeId","data-v-2edece88"]]),Yn=n=>(z("data-v-6b87e69f"),n=n(),D(),n),Xn={class:"container"},Qn=Yn(()=>u("div",{class:"aside-curtain"},null,-1)),Jn={class:"aside-container"},Zn={class:"aside-content"},es={class:"content"},ts={class:"content-container"},ns={class:"main"},ss=g({__name:"VPDoc",setup(n){const{theme:e}=P(),t=te(),{hasSidebar:s,hasAside:o,leftAside:r}=O(),d=k(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(p,_)=>{const y=U("Content");return a(),i("div",{class:T(["VPDoc",{"has-sidebar":l(s),"has-aside":l(o)}])},[c(p.$slots,"doc-top",{},void 0,!0),u("div",Xn,[l(o)?(a(),i("div",{key:0,class:T(["aside",{"left-aside":l(r)}])},[Qn,u("div",Jn,[u("div",Zn,[h(dn,null,{"aside-top":v(()=>[c(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),u("div",es,[u("div",ts,[c(p.$slots,"doc-before",{},void 0,!0),h(Wn),u("main",ns,[h(y,{class:T(["vp-doc",[d.value,l(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),h(Dn,null,{"doc-footer-before":v(()=>[c(p.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),c(p.$slots,"doc-after",{},void 0,!0)])])]),c(p.$slots,"doc-bottom",{},void 0,!0)],2)}}});const os=m(ss,[["__scopeId","data-v-6b87e69f"]]),as=g({__name:"VPButton",props:{tag:{},size:{},theme:{},text:{},href:{}},setup(n){const e=n,t=k(()=>[e.size??"medium",e.theme??"brand"]),s=k(()=>e.href&&De.test(e.href)),o=k(()=>e.tag?e.tag:e.href?"a":"button");return(r,d)=>(a(),b(j(o.value),{class:T(["VPButton",t.value]),href:r.href?l(ee)(r.href):void 0,target:s.value?"_blank":void 0,rel:s.value?"noreferrer":void 0},{default:v(()=>[x(S(r.text),1)]),_:1},8,["class","href","target","rel"]))}});const rs=m(as,[["__scopeId","data-v-567ba664"]]),ls=["src","alt"],is={inheritAttrs:!1},cs=g({...is,__name:"VPImage",props:{image:{},alt:{}},setup(n){return(e,t)=>{const s=U("VPImage",!0);return e.image?(a(),i(C,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),i("img",se({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:l(fe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,ls)):(a(),i(C,{key:1},[h(s,se({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),h(s,se({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}});const we=m(cs,[["__scopeId","data-v-6db2186b"]]),us=n=>(z("data-v-da5d1713"),n=n(),D(),n),ds={class:"container"},_s={class:"main"},vs={key:0,class:"name"},ps=["innerHTML"],hs=["innerHTML"],fs=["innerHTML"],ms={key:0,class:"actions"},gs={key:0,class:"image"},ys={class:"image-container"},bs=us(()=>u("div",{class:"image-bg"},null,-1)),ks=g({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(n){const e=ge("hero-image-slot-exists");return(t,s)=>(a(),i("div",{class:T(["VPHero",{"has-image":t.image||l(e)}])},[u("div",ds,[u("div",_s,[c(t.$slots,"home-hero-info",{},()=>[t.name?(a(),i("h1",vs,[u("span",{innerHTML:t.name,class:"clip"},null,8,ps)])):f("",!0),t.text?(a(),i("p",{key:1,innerHTML:t.text,class:"text"},null,8,hs)):f("",!0),t.tagline?(a(),i("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,fs)):f("",!0)],!0),t.actions?(a(),i("div",ms,[(a(!0),i(C,null,H(t.actions,o=>(a(),i("div",{key:o.link,class:"action"},[h(rs,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||l(e)?(a(),i("div",gs,[u("div",ys,[bs,c(t.$slots,"home-hero-image",{},()=>[t.image?(a(),b(we,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}});const $s=m(ks,[["__scopeId","data-v-da5d1713"]]),Ps=g({__name:"VPHomeHero",setup(n){const{frontmatter:e}=P();return(t,s)=>l(e).hero?(a(),b($s,{key:0,class:"VPHomeHero",name:l(e).hero.name,text:l(e).hero.text,tagline:l(e).hero.tagline,image:l(e).hero.image,actions:l(e).hero.actions},{"home-hero-info":v(()=>[c(t.$slots,"home-hero-info")]),"home-hero-image":v(()=>[c(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Vs={},ws={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Ss=u("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Ls=[Ss];function Ms(n,e){return a(),i("svg",ws,Ls)}const Cs=m(Vs,[["render",Ms]]),Is={class:"box"},Ts=["innerHTML"],Bs=["innerHTML"],As=["innerHTML"],Ns={key:3,class:"link-text"},xs={class:"link-text-value"},Hs=g({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{}},setup(n){return(e,t)=>(a(),b(G,{class:"VPFeature",href:e.link,rel:e.rel,"no-icon":!0,tag:e.link?"a":"div"},{default:v(()=>[u("article",Is,[typeof e.icon=="object"?(a(),b(we,{key:0,image:e.icon,alt:e.icon.alt,height:e.icon.height,width:e.icon.width},null,8,["image","alt","height","width"])):e.icon?(a(),i("div",{key:1,class:"icon",innerHTML:e.icon},null,8,Ts)):f("",!0),u("h2",{class:"title",innerHTML:e.title},null,8,Bs),e.details?(a(),i("p",{key:2,class:"details",innerHTML:e.details},null,8,As)):f("",!0),e.linkText?(a(),i("div",Ns,[u("p",xs,[x(S(e.linkText)+" ",1),h(Cs,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","tag"]))}});const Es=m(Hs,[["__scopeId","data-v-f7bdba60"]]),zs={key:0,class:"VPFeatures"},Ds={class:"container"},Fs={class:"items"},Os=g({__name:"VPFeatures",props:{features:{}},setup(n){const e=n,t=k(()=>{const s=e.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s>3)return"grid-4"}else return});return(s,o)=>s.features?(a(),i("div",zs,[u("div",Ds,[u("div",Fs,[(a(!0),i(C,null,H(s.features,r=>(a(),i("div",{key:r.title,class:T(["item",[t.value]])},[h(Es,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel},null,8,["icon","title","details","link","link-text","rel"])],2))),128))])])])):f("",!0)}});const Gs=m(Os,[["__scopeId","data-v-39646fad"]]),Rs=g({__name:"VPHomeFeatures",setup(n){const{frontmatter:e}=P();return(t,s)=>l(e).features?(a(),b(Gs,{key:0,class:"VPHomeFeatures",features:l(e).features},null,8,["features"])):f("",!0)}}),Us={class:"VPHome"},js=g({__name:"VPHome",setup(n){return(e,t)=>{const s=U("Content");return a(),i("div",Us,[c(e.$slots,"home-hero-before",{},void 0,!0),h(Ps,null,{"home-hero-info":v(()=>[c(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),c(e.$slots,"home-hero-after",{},void 0,!0),c(e.$slots,"home-features-before",{},void 0,!0),h(Rs),c(e.$slots,"home-features-after",{},void 0,!0),h(s)])}}});const qs=m(js,[["__scopeId","data-v-d82743a8"]]),Ks={},Ws={class:"VPPage"};function Ys(n,e){const t=U("Content");return a(),i("div",Ws,[c(n.$slots,"page-top"),h(t),c(n.$slots,"page-bottom")])}const Xs=m(Ks,[["render",Ys]]),Qs=g({__name:"VPContent",setup(n){const{page:e,frontmatter:t}=P(),{hasSidebar:s}=O();return(o,r)=>(a(),i("div",{class:T(["VPContent",{"has-sidebar":l(s),"is-home":l(t).layout==="home"}]),id:"VPContent"},[l(e).isNotFound?c(o.$slots,"not-found",{key:0},()=>[h(Bt)],!0):l(t).layout==="page"?(a(),b(Xs,{key:1},{"page-top":v(()=>[c(o.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(o.$slots,"page-bottom",{},void 0,!0)]),_:3})):l(t).layout==="home"?(a(),b(qs,{key:2},{"home-hero-before":v(()=>[c(o.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(o.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(o.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(o.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(o.$slots,"home-features-after",{},void 0,!0)]),_:3})):(a(),b(os,{key:3},{"doc-top":v(()=>[c(o.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(o.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":v(()=>[c(o.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(o.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(o.$slots,"doc-after",{},void 0,!0)]),"aside-top":v(()=>[c(o.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":v(()=>[c(o.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(o.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(o.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(o.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":v(()=>[c(o.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const Js=m(Qs,[["__scopeId","data-v-3107c4ee"]]),Zs={class:"container"},eo=["innerHTML"],to=["innerHTML"],no=g({__name:"VPFooter",setup(n){const{theme:e,frontmatter:t}=P(),{hasSidebar:s}=O();return(o,r)=>l(e).footer&&l(t).footer!==!1?(a(),i("footer",{key:0,class:T(["VPFooter",{"has-sidebar":l(s)}])},[u("div",Zs,[l(e).footer.message?(a(),i("p",{key:0,class:"message",innerHTML:l(e).footer.message},null,8,eo)):f("",!0),l(e).footer.copyright?(a(),i("p",{key:1,class:"copyright",innerHTML:l(e).footer.copyright},null,8,to)):f("",!0)])],2)):f("",!0)}});const so=m(no,[["__scopeId","data-v-e03eb2e1"]]),oo=g({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(n){const e=n,{theme:t}=P(),s=w(!1),o=w(0),r=w();Z(()=>{s.value=!1});function d(){s.value=!s.value,o.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(y){y.target.classList.contains("outline-link")&&(r.value&&(r.value.style.transition="none"),lt(()=>{s.value=!1}))}function _(){s.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(y,L)=>(a(),i("div",{class:"VPLocalNavOutlineDropdown",style:Fe({"--vp-vh":o.value+"px"})},[y.headers.length>0?(a(),i("button",{key:0,onClick:d,class:T({open:s.value})},[x(S(l(ke)(l(t)))+" ",1),h(Ve,{class:"icon"})],2)):(a(),i("button",{key:1,onClick:_},S(l(t).returnToTopLabel||"Return to top"),1)),h(he,{name:"flyout"},{default:v(()=>[s.value?(a(),i("div",{key:0,ref_key:"items",ref:r,class:"items",onClick:p},[u("a",{class:"top-link",href:"#",onClick:_},S(l(t).returnToTopLabel||"Return to top"),1),h(Pe,{headers:y.headers},null,8,["headers"])],512)):f("",!0)]),_:1})],4))}});const ao=m(oo,[["__scopeId","data-v-d5bb9d56"]]),ro={},lo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},io=u("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),co=u("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),uo=u("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),_o=u("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),vo=[io,co,uo,_o];function po(n,e){return a(),i("svg",lo,vo)}const ho=m(ro,[["render",po]]),fo=["aria-expanded"],mo={class:"menu-text"},go=g({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(n){const{theme:e,frontmatter:t}=P(),{hasSidebar:s}=O(),{y:o}=Re(),r=me([]),d=w(0);F(()=>{d.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Z(()=>{r.value=$e(t.value.outline??e.value.outline)});const p=k(()=>r.value.length===0&&!s.value),_=k(()=>({VPLocalNav:!0,fixed:p.value,"reached-top":o.value>=d.value}));return(y,L)=>l(t).layout!=="home"&&(!p.value||l(o)>=d.value)?(a(),i("div",{key:0,class:T(_.value)},[l(s)?(a(),i("button",{key:0,class:"menu","aria-expanded":y.open,"aria-controls":"VPSidebarNav",onClick:L[0]||(L[0]=A=>y.$emit("open-menu"))},[h(ho,{class:"menu-icon"}),u("span",mo,S(l(e).sidebarMenuLabel||"Menu"),1)],8,fo)):f("",!0),h(ao,{headers:r.value,navHeight:d.value},null,8,["headers","navHeight"])],2)):f("",!0)}});const yo=m(go,[["__scopeId","data-v-5cfd5582"]]);function bo(){const n=w(!1);function e(){n.value=!0,window.addEventListener("resize",o)}function t(){n.value=!1,window.removeEventListener("resize",o)}function s(){n.value?t():e()}function o(){window.outerWidth>=768&&t()}const r=te();return K(()=>r.path,t),{isScreenOpen:n,openScreen:e,closeScreen:t,toggleScreen:s}}const ko={},$o={class:"VPSwitch",type:"button",role:"switch"},Po={class:"check"},Vo={key:0,class:"icon"};function wo(n,e){return a(),i("button",$o,[u("span",Po,[n.$slots.default?(a(),i("span",Vo,[c(n.$slots,"default",{},void 0,!0)])):f("",!0)])])}const So=m(ko,[["render",wo],["__scopeId","data-v-f3c41672"]]),Lo={},Mo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Co=it('',9),Io=[Co];function To(n,e){return a(),i("svg",Mo,Io)}const Bo=m(Lo,[["render",To]]),Ao={},No={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},xo=u("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),Ho=[xo];function Eo(n,e){return a(),i("svg",No,Ho)}const zo=m(Ao,[["render",Eo]]),Do=g({__name:"VPSwitchAppearance",setup(n){const{site:e,isDark:t}=P(),s=w(!1),o=Oe?r():()=>{};F(()=>{s.value=document.documentElement.classList.contains("dark")});function r(){const d=window.matchMedia("(prefers-color-scheme: dark)"),p=document.documentElement.classList;let _=localStorage.getItem(xe),y=e.value.appearance==="dark"&&_==null||(_==="auto"||_==null?d.matches:_==="dark");d.onchange=I=>{_==="auto"&&A(y=I.matches)};function L(){A(y=!y),_=y?d.matches?"auto":"dark":d.matches?"light":"auto",localStorage.setItem(xe,_)}function A(I){const V=document.createElement("style");V.type="text/css",V.appendChild(document.createTextNode(`:not(.VPSwitchAppearance):not(.VPSwitchAppearance *) { - -webkit-transition: none !important; - -moz-transition: none !important; - -o-transition: none !important; - -ms-transition: none !important; - transition: none !important; -}`)),document.head.appendChild(V),s.value=I,p[I?"add":"remove"]("dark"),window.getComputedStyle(V).opacity,document.head.removeChild(V)}return L}return K(s,d=>{t.value=d}),(d,p)=>(a(),b(So,{title:"toggle dark mode",class:"VPSwitchAppearance","aria-checked":s.value,onClick:l(o)},{default:v(()=>[h(Bo,{class:"sun"}),h(zo,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const Se=m(Do,[["__scopeId","data-v-82b282f1"]]),Fo={key:0,class:"VPNavBarAppearance"},Oo=g({__name:"VPNavBarAppearance",setup(n){const{site:e}=P();return(t,s)=>l(e).appearance?(a(),i("div",Fo,[h(Se)])):f("",!0)}});const Go=m(Oo,[["__scopeId","data-v-f6a63727"]]),Le=w();let je=!1,de=0;function Ro(n){const e=w(!1);if(Oe){!je&&Uo(),de++;const t=K(Le,s=>{var o,r,d;s===n.el.value||(o=n.el.value)!=null&&o.contains(s)?(e.value=!0,(r=n.onFocus)==null||r.call(n)):(e.value=!1,(d=n.onBlur)==null||d.call(n))});ie(()=>{t(),de--,de||jo()})}return ct(e)}function Uo(){document.addEventListener("focusin",qe),je=!0,Le.value=document.activeElement}function jo(){document.removeEventListener("focusin",qe)}function qe(){Le.value=document.activeElement}const qo={},Ko={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Wo=u("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),Yo=[Wo];function Xo(n,e){return a(),i("svg",Ko,Yo)}const Ke=m(qo,[["render",Xo]]),Qo={},Jo={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Zo=u("circle",{cx:"12",cy:"12",r:"2"},null,-1),ea=u("circle",{cx:"19",cy:"12",r:"2"},null,-1),ta=u("circle",{cx:"5",cy:"12",r:"2"},null,-1),na=[Zo,ea,ta];function sa(n,e){return a(),i("svg",Jo,na)}const oa=m(Qo,[["render",sa]]),aa={class:"VPMenuLink"},ra=g({__name:"VPMenuLink",props:{item:{}},setup(n){const{page:e}=P();return(t,s)=>(a(),i("div",aa,[h(G,{class:T({active:l(W)(l(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:v(()=>[x(S(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}});const ue=m(ra,[["__scopeId","data-v-2f2cfafc"]]),la={class:"VPMenuGroup"},ia={key:0,class:"title"},ca=g({__name:"VPMenuGroup",props:{text:{},items:{}},setup(n){return(e,t)=>(a(),i("div",la,[e.text?(a(),i("p",ia,S(e.text),1)):f("",!0),(a(!0),i(C,null,H(e.items,s=>(a(),i(C,null,["link"in s?(a(),b(ue,{key:0,item:s},null,8,["item"])):f("",!0)],64))),256))]))}});const ua=m(ca,[["__scopeId","data-v-69e747b5"]]),da={class:"VPMenu"},_a={key:0,class:"items"},va=g({__name:"VPMenu",props:{items:{}},setup(n){return(e,t)=>(a(),i("div",da,[e.items?(a(),i("div",_a,[(a(!0),i(C,null,H(e.items,s=>(a(),i(C,{key:s.text},["link"in s?(a(),b(ue,{key:0,item:s},null,8,["item"])):(a(),b(ua,{key:1,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):f("",!0),c(e.$slots,"default",{},void 0,!0)]))}});const pa=m(va,[["__scopeId","data-v-e7ea1737"]]),ha=["aria-expanded","aria-label"],fa={key:0,class:"text"},ma={class:"menu"},ga=g({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(n){const e=w(!1),t=w();Ro({el:t,onBlur:s});function s(){e.value=!1}return(o,r)=>(a(),i("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=d=>e.value=!0),onMouseleave:r[2]||(r[2]=d=>e.value=!1)},[u("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":o.label,onClick:r[0]||(r[0]=d=>e.value=!e.value)},[o.button||o.icon?(a(),i("span",fa,[o.icon?(a(),b(j(o.icon),{key:0,class:"option-icon"})):f("",!0),x(" "+S(o.button)+" ",1),h(Ke,{class:"text-icon"})])):(a(),b(oa,{key:1,class:"icon"}))],8,ha),u("div",ma,[h(pa,{items:o.items},{default:v(()=>[c(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const Me=m(ga,[["__scopeId","data-v-764effdf"]]),ya={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',youtube:'YouTube'},ba=["href","aria-label","innerHTML"],ka=g({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(n){const e=n,t=k(()=>typeof e.icon=="object"?e.icon.svg:ya[e.icon]);return(s,o)=>(a(),i("a",{class:"VPSocialLink no-icon",href:s.link,"aria-label":s.ariaLabel??(typeof s.icon=="string"?s.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,ba))}});const $a=m(ka,[["__scopeId","data-v-f80f8133"]]),Pa={class:"VPSocialLinks"},Va=g({__name:"VPSocialLinks",props:{links:{}},setup(n){return(e,t)=>(a(),i("div",Pa,[(a(!0),i(C,null,H(e.links,({link:s,icon:o,ariaLabel:r})=>(a(),b($a,{key:s,icon:o,link:s,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}});const Ce=m(Va,[["__scopeId","data-v-7bc22406"]]),wa={key:0,class:"group translations"},Sa={class:"trans-title"},La={key:1,class:"group"},Ma={class:"item appearance"},Ca={class:"label"},Ia={class:"appearance-action"},Ta={key:2,class:"group"},Ba={class:"item social-links"},Aa=g({__name:"VPNavBarExtra",setup(n){const{site:e,theme:t}=P(),{localeLinks:s,currentLang:o}=ne({correspondingLink:!0}),r=k(()=>s.value.length&&o.value.label||e.value.appearance||t.value.socialLinks);return(d,p)=>r.value?(a(),b(Me,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:v(()=>[l(s).length&&l(o).label?(a(),i("div",wa,[u("p",Sa,S(l(o).label),1),(a(!0),i(C,null,H(l(s),_=>(a(),b(ue,{key:_.link,item:_},null,8,["item"]))),128))])):f("",!0),l(e).appearance?(a(),i("div",La,[u("div",Ma,[u("p",Ca,S(l(t).darkModeSwitchLabel||"Appearance"),1),u("div",Ia,[h(Se)])])])):f("",!0),l(t).socialLinks?(a(),i("div",Ta,[u("div",Ba,[h(Ce,{class:"social-links-list",links:l(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}});const Na=m(Aa,[["__scopeId","data-v-40855f84"]]),xa=n=>(z("data-v-e5dd9c1c"),n=n(),D(),n),Ha=["aria-expanded"],Ea=xa(()=>u("span",{class:"container"},[u("span",{class:"top"}),u("span",{class:"middle"}),u("span",{class:"bottom"})],-1)),za=[Ea],Da=g({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(n){return(e,t)=>(a(),i("button",{type:"button",class:T(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=s=>e.$emit("click"))},za,10,Ha))}});const Fa=m(Da,[["__scopeId","data-v-e5dd9c1c"]]),Oa=g({__name:"VPNavBarMenuLink",props:{item:{}},setup(n){const{page:e}=P();return(t,s)=>(a(),b(G,{class:T({VPNavBarMenuLink:!0,active:l(W)(l(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:v(()=>[x(S(t.item.text),1)]),_:1},8,["class","href","target","rel"]))}});const Ga=m(Oa,[["__scopeId","data-v-5e623618"]]),Ra=g({__name:"VPNavBarMenuGroup",props:{item:{}},setup(n){const{page:e}=P();return(t,s)=>(a(),b(Me,{class:T({VPNavBarMenuGroup:!0,active:l(W)(l(e).relativePath,t.item.activeMatch,!!t.item.activeMatch)}),button:t.item.text,items:t.item.items},null,8,["class","button","items"]))}}),Ua=n=>(z("data-v-7f418b0f"),n=n(),D(),n),ja={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},qa=Ua(()=>u("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Ka=g({__name:"VPNavBarMenu",setup(n){const{theme:e}=P();return(t,s)=>l(e).nav?(a(),i("nav",ja,[qa,(a(!0),i(C,null,H(l(e).nav,o=>(a(),i(C,{key:o.text},["link"in o?(a(),b(Ga,{key:0,item:o},null,8,["item"])):(a(),b(Ra,{key:1,item:o},null,8,["item"]))],64))),128))])):f("",!0)}});const Wa=m(Ka,[["__scopeId","data-v-7f418b0f"]]);const Ya={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Xa={class:"DocSearch-Button-Container"},Qa=u("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[u("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Ja={class:"DocSearch-Button-Placeholder"},Za=u("span",{class:"DocSearch-Button-Keys"},[u("kbd",{class:"DocSearch-Button-Key"}),u("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Ee=g({__name:"VPNavBarSearchButton",props:{placeholder:{}},setup(n){return(e,t)=>(a(),i("button",Ya,[u("span",Xa,[Qa,u("span",Ja,S(e.placeholder),1)]),Za]))}});const er={id:"local-search"},tr={key:1,id:"docsearch"},nr=g({__name:"VPNavBarSearch",setup(n){const e=()=>null,t=ut(()=>dt(()=>import("./VPAlgoliaSearchBox.faa390b4.js"),["assets/chunks/VPAlgoliaSearchBox.faa390b4.js","assets/chunks/framework.70afa331.js"])),{theme:s,localeIndex:o}=P(),r=w(!1),d=w(!1),p=k(()=>{var $,B,E,Y,Be,Ae,Ne;const M=(($=s.value.search)==null?void 0:$.options)??s.value.algolia;return((Be=(Y=(E=(B=M==null?void 0:M.locales)==null?void 0:B[o.value])==null?void 0:E.translations)==null?void 0:Y.button)==null?void 0:Be.buttonText)||((Ne=(Ae=M==null?void 0:M.translations)==null?void 0:Ae.button)==null?void 0:Ne.buttonText)||"Search"}),_=()=>{const M="VPAlgoliaPreconnect";(window.requestIdleCallback||setTimeout)(()=>{var E;const B=document.createElement("link");B.id=M,B.rel="preconnect",B.href=`https://${(((E=s.value.search)==null?void 0:E.options)??s.value.algolia).appId}-dsn.algolia.net`,B.crossOrigin="",document.head.appendChild(B)})};F(()=>{_();const M=B=>{(B.key.toLowerCase()==="k"&&(B.metaKey||B.ctrlKey)||!A(B)&&B.key==="/")&&(B.preventDefault(),y(),$())},$=()=>{window.removeEventListener("keydown",M)};window.addEventListener("keydown",M),ie($)});function y(){r.value||(r.value=!0,setTimeout(L,16))}function L(){const M=new Event("keydown");M.key="k",M.metaKey=!0,window.dispatchEvent(M),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||L()},16)}function A(M){const $=M.target,B=$.tagName;return $.isContentEditable||B==="INPUT"||B==="SELECT"||B==="TEXTAREA"}const I=w(!1),V=w("'Meta'");F(()=>{V.value=/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"'⌘'":"'Ctrl'"});const N="algolia";return(M,$)=>{var B;return a(),i("div",{class:"VPNavBarSearch",style:Fe({"--vp-meta-key":V.value})},[l(N)==="local"?(a(),i(C,{key:0},[I.value?(a(),b(l(e),{key:0,placeholder:p.value,onClose:$[0]||($[0]=E=>I.value=!1)},null,8,["placeholder"])):f("",!0),u("div",er,[h(Ee,{placeholder:p.value,onClick:$[1]||($[1]=E=>I.value=!0)},null,8,["placeholder"])])],64)):l(N)==="algolia"?(a(),i(C,{key:1},[r.value?(a(),b(l(t),{key:0,algolia:((B=l(s).search)==null?void 0:B.options)??l(s).algolia,onVnodeBeforeMount:$[2]||($[2]=E=>d.value=!0)},null,8,["algolia"])):f("",!0),d.value?f("",!0):(a(),i("div",tr,[h(Ee,{placeholder:p.value,onClick:y},null,8,["placeholder"])]))],64)):f("",!0)],4)}}});const sr=g({__name:"VPNavBarSocialLinks",setup(n){const{theme:e}=P();return(t,s)=>l(e).socialLinks?(a(),b(Ce,{key:0,class:"VPNavBarSocialLinks",links:l(e).socialLinks},null,8,["links"])):f("",!0)}});const or=m(sr,[["__scopeId","data-v-0394ad82"]]),ar=["href"],rr=g({__name:"VPNavBarTitle",setup(n){const{site:e,theme:t}=P(),{hasSidebar:s}=O(),{currentLang:o}=ne();return(r,d)=>(a(),i("div",{class:T(["VPNavBarTitle",{"has-sidebar":l(s)}])},[u("a",{class:"title",href:l(ee)(l(o).link)},[c(r.$slots,"nav-bar-title-before",{},void 0,!0),l(t).logo?(a(),b(we,{key:0,class:"logo",image:l(t).logo},null,8,["image"])):f("",!0),l(t).siteTitle?(a(),i(C,{key:1},[x(S(l(t).siteTitle),1)],64)):l(t).siteTitle===void 0?(a(),i(C,{key:2},[x(S(l(e).title),1)],64)):f("",!0),c(r.$slots,"nav-bar-title-after",{},void 0,!0)],8,ar)],2))}});const lr=m(rr,[["__scopeId","data-v-8bbac535"]]),ir={},cr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ur=u("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),dr=u("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),_r=[ur,dr];function vr(n,e){return a(),i("svg",cr,_r)}const We=m(ir,[["render",vr]]),pr={class:"items"},hr={class:"title"},fr=g({__name:"VPNavBarTranslations",setup(n){const{theme:e}=P(),{localeLinks:t,currentLang:s}=ne({correspondingLink:!0});return(o,r)=>l(t).length&&l(s).label?(a(),b(Me,{key:0,class:"VPNavBarTranslations",icon:We,label:l(e).langMenuLabel||"Change language"},{default:v(()=>[u("div",pr,[u("p",hr,S(l(s).label),1),(a(!0),i(C,null,H(l(t),d=>(a(),b(ue,{key:d.link,item:d},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}});const mr=m(fr,[["__scopeId","data-v-74abcbb9"]]),gr=n=>(z("data-v-faa4ef78"),n=n(),D(),n),yr={class:"container"},br={class:"title"},kr={class:"content"},$r=gr(()=>u("div",{class:"curtain"},null,-1)),Pr={class:"content-body"},Vr=g({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(n){const{y:e}=Re(),{hasSidebar:t}=O(),s=k(()=>({"has-sidebar":t.value,fill:e.value>0}));return(o,r)=>(a(),i("div",{class:T(["VPNavBar",s.value])},[u("div",yr,[u("div",br,[h(lr,null,{"nav-bar-title-before":v(()=>[c(o.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(o.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),u("div",kr,[$r,u("div",Pr,[c(o.$slots,"nav-bar-content-before",{},void 0,!0),h(nr,{class:"search"}),h(Wa,{class:"menu"}),h(mr,{class:"translations"}),h(Go,{class:"appearance"}),h(or,{class:"social-links"}),h(Na,{class:"extra"}),c(o.$slots,"nav-bar-content-after",{},void 0,!0),h(Fa,{class:"hamburger",active:o.isScreenOpen,onClick:r[0]||(r[0]=d=>o.$emit("toggle-screen"))},null,8,["active"])])])])],2))}});const wr=m(Vr,[["__scopeId","data-v-faa4ef78"]]);function Sr(n){if(Array.isArray(n)){for(var e=0,t=Array(n.length);e1),q=[],re=!1,Te=-1,X=void 0,R=void 0,Q=void 0,Ye=function(e){return q.some(function(t){return!!(t.options.allowTouchMove&&t.options.allowTouchMove(e))})},le=function(e){var t=e||window.event;return Ye(t.target)||t.touches.length>1?!0:(t.preventDefault&&t.preventDefault(),!1)},Lr=function(e){if(Q===void 0){var t=!!e&&e.reserveScrollBarGap===!0,s=window.innerWidth-document.documentElement.clientWidth;if(t&&s>0){var o=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);Q=document.body.style.paddingRight,document.body.style.paddingRight=o+s+"px"}}X===void 0&&(X=document.body.style.overflow,document.body.style.overflow="hidden")},Mr=function(){Q!==void 0&&(document.body.style.paddingRight=Q,Q=void 0),X!==void 0&&(document.body.style.overflow=X,X=void 0)},Cr=function(){return window.requestAnimationFrame(function(){if(R===void 0){R={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var e=window,t=e.scrollY,s=e.scrollX,o=e.innerHeight;document.body.style.position="fixed",document.body.style.top=-t,document.body.style.left=-s,setTimeout(function(){return window.requestAnimationFrame(function(){var r=o-window.innerHeight;r&&t>=o&&(document.body.style.top=-(t+r))})},300)}})},Ir=function(){if(R!==void 0){var e=-parseInt(document.body.style.top,10),t=-parseInt(document.body.style.left,10);document.body.style.position=R.position,document.body.style.top=R.top,document.body.style.left=R.left,window.scrollTo(t,e),R=void 0}},Tr=function(e){return e?e.scrollHeight-e.scrollTop<=e.clientHeight:!1},Br=function(e,t){var s=e.targetTouches[0].clientY-Te;return Ye(e.target)?!1:t&&t.scrollTop===0&&s>0||Tr(t)&&s<0?le(e):(e.stopPropagation(),!0)},Xe=function(e,t){if(!e){console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");return}if(!q.some(function(o){return o.targetElement===e})){var s={targetElement:e,options:t||{}};q=[].concat(Sr(q),[s]),ae?Cr():Lr(t),ae&&(e.ontouchstart=function(o){o.targetTouches.length===1&&(Te=o.targetTouches[0].clientY)},e.ontouchmove=function(o){o.targetTouches.length===1&&Br(o,e)},re||(document.addEventListener("touchmove",le,Ie?{passive:!1}:void 0),re=!0))}},Qe=function(){ae&&(q.forEach(function(e){e.targetElement.ontouchstart=null,e.targetElement.ontouchmove=null}),re&&(document.removeEventListener("touchmove",le,Ie?{passive:!1}:void 0),re=!1),Te=-1),ae?Ir():Mr(),q=[]};const Ar=g({__name:"VPNavScreenMenuLink",props:{item:{}},setup(n){const e=ge("close-screen");return(t,s)=>(a(),b(G,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:l(e)},{default:v(()=>[x(S(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const Nr=m(Ar,[["__scopeId","data-v-30be0acb"]]),xr={},Hr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Er=u("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),zr=[Er];function Dr(n,e){return a(),i("svg",Hr,zr)}const Fr=m(xr,[["render",Dr]]),Or=g({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(n){const e=ge("close-screen");return(t,s)=>(a(),b(G,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:l(e)},{default:v(()=>[x(S(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}});const Je=m(Or,[["__scopeId","data-v-6656c42a"]]),Gr={class:"VPNavScreenMenuGroupSection"},Rr={key:0,class:"title"},Ur=g({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(n){return(e,t)=>(a(),i("div",Gr,[e.text?(a(),i("p",Rr,S(e.text),1)):f("",!0),(a(!0),i(C,null,H(e.items,s=>(a(),b(Je,{key:s.text,item:s},null,8,["item"]))),128))]))}});const jr=m(Ur,[["__scopeId","data-v-8133b170"]]),qr=["aria-controls","aria-expanded"],Kr={class:"button-text"},Wr=["id"],Yr={key:1,class:"group"},Xr=g({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(n){const e=n,t=w(!1),s=k(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function o(){t.value=!t.value}return(r,d)=>(a(),i("div",{class:T(["VPNavScreenMenuGroup",{open:t.value}])},[u("button",{class:"button","aria-controls":s.value,"aria-expanded":t.value,onClick:o},[u("span",Kr,S(r.text),1),h(Fr,{class:"button-icon"})],8,qr),u("div",{id:s.value,class:"items"},[(a(!0),i(C,null,H(r.items,p=>(a(),i(C,{key:p.text},["link"in p?(a(),i("div",{key:p.text,class:"item"},[h(Je,{item:p},null,8,["item"])])):(a(),i("div",Yr,[h(jr,{text:p.text,items:p.items},null,8,["text","items"])]))],64))),128))],8,Wr)],2))}});const Qr=m(Xr,[["__scopeId","data-v-338a1689"]]),Jr={key:0,class:"VPNavScreenMenu"},Zr=g({__name:"VPNavScreenMenu",setup(n){const{theme:e}=P();return(t,s)=>l(e).nav?(a(),i("nav",Jr,[(a(!0),i(C,null,H(l(e).nav,o=>(a(),i(C,{key:o.text},["link"in o?(a(),b(Nr,{key:0,item:o},null,8,["item"])):(a(),b(Qr,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),el={key:0,class:"VPNavScreenAppearance"},tl={class:"text"},nl=g({__name:"VPNavScreenAppearance",setup(n){const{site:e,theme:t}=P();return(s,o)=>l(e).appearance?(a(),i("div",el,[u("p",tl,S(l(t).darkModeSwitchLabel||"Appearance"),1),h(Se)])):f("",!0)}});const sl=m(nl,[["__scopeId","data-v-add8f686"]]),ol={class:"list"},al=g({__name:"VPNavScreenTranslations",setup(n){const{localeLinks:e,currentLang:t}=ne({correspondingLink:!0}),s=w(!1);function o(){s.value=!s.value}return(r,d)=>l(e).length&&l(t).label?(a(),i("div",{key:0,class:T(["VPNavScreenTranslations",{open:s.value}])},[u("button",{class:"title",onClick:o},[h(We,{class:"icon lang"}),x(" "+S(l(t).label)+" ",1),h(Ke,{class:"icon chevron"})]),u("ul",ol,[(a(!0),i(C,null,H(l(e),p=>(a(),i("li",{key:p.link,class:"item"},[h(G,{class:"link",href:p.link},{default:v(()=>[x(S(p.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}});const rl=m(al,[["__scopeId","data-v-d72aa483"]]),ll=g({__name:"VPNavScreenSocialLinks",setup(n){const{theme:e}=P();return(t,s)=>l(e).socialLinks?(a(),b(Ce,{key:0,class:"VPNavScreenSocialLinks",links:l(e).socialLinks},null,8,["links"])):f("",!0)}}),il={class:"container"},cl=g({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(n){const e=w(null);function t(){Xe(e.value,{reserveScrollBarGap:!0})}function s(){Qe()}return(o,r)=>(a(),b(he,{name:"fade",onEnter:t,onAfterLeave:s},{default:v(()=>[o.open?(a(),i("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[u("div",il,[c(o.$slots,"nav-screen-content-before",{},void 0,!0),h(Zr,{class:"menu"}),h(rl,{class:"translations"}),h(sl,{class:"appearance"}),h(ll,{class:"social-links"}),c(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}});const ul=m(cl,[["__scopeId","data-v-69fcc70f"]]),dl={class:"VPNav"},_l=g({__name:"VPNav",setup(n){const{isScreenOpen:e,closeScreen:t,toggleScreen:s}=bo();return oe("close-screen",t),(o,r)=>(a(),i("header",dl,[h(wr,{"is-screen-open":l(e),onToggleScreen:l(s)},{"nav-bar-title-before":v(()=>[c(o.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(o.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(o.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(o.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),h(ul,{open:l(e)},{"nav-screen-content-before":v(()=>[c(o.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(o.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])]))}});const vl=m(_l,[["__scopeId","data-v-7e5bc4a5"]]),pl=n=>(z("data-v-4fbabd82"),n=n(),D(),n),hl=["role","tabindex"],fl=pl(()=>u("div",{class:"indicator"},null,-1)),ml=["onKeydown"],gl={key:1,class:"items"},yl=g({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(n){const e=n,{collapsed:t,collapsible:s,isLink:o,isActiveLink:r,hasActiveLink:d,hasChildren:p,toggle:_}=Gt(k(()=>e.item)),y=k(()=>p.value?"section":"div"),L=k(()=>o.value?"a":"div"),A=k(()=>p.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),I=k(()=>o.value?void 0:"button"),V=k(()=>[[`level-${e.depth}`],{collapsible:s.value},{collapsed:t.value},{"is-link":o.value},{"is-active":r.value},{"has-active":d.value}]);function N($){"key"in $&&$.key!=="Enter"||!e.item.link&&_()}function M(){e.item.link&&_()}return($,B)=>{const E=U("VPSidebarItem",!0);return a(),b(j(y.value),{class:T(["VPSidebarItem",V.value])},{default:v(()=>[$.item.text?(a(),i("div",se({key:0,class:"item",role:I.value},vt($.item.items?{click:N,keydown:N}:{},!0),{tabindex:$.item.items&&0}),[fl,$.item.link?(a(),b(G,{key:0,tag:L.value,class:"link",href:$.item.link},{default:v(()=>[(a(),b(j(A.value),{class:"text",innerHTML:$.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href"])):(a(),b(j(A.value),{key:1,class:"text",innerHTML:$.item.text},null,8,["innerHTML"])),$.item.collapsed!=null?(a(),i("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:M,onKeydown:_t(M,["enter"]),tabindex:"0"},[h(Ve,{class:"caret-icon"})],40,ml)):f("",!0)],16,hl)):f("",!0),$.item.items&&$.item.items.length?(a(),i("div",gl,[$.depth<5?(a(!0),i(C,{key:0},H($.item.items,Y=>(a(),b(E,{key:Y.text,item:Y,depth:$.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}});const bl=m(yl,[["__scopeId","data-v-4fbabd82"]]),Ze=n=>(z("data-v-845b8fc6"),n=n(),D(),n),kl=Ze(()=>u("div",{class:"curtain"},null,-1)),$l={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Pl=Ze(()=>u("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Vl=g({__name:"VPSidebar",props:{open:{type:Boolean}},setup(n){const e=n,{sidebarGroups:t,hasSidebar:s}=O();let o=w(null);function r(){Xe(o.value,{reserveScrollBarGap:!0})}function d(){Qe()}return pt(async()=>{var p;e.open?(r(),(p=o.value)==null||p.focus()):d()}),(p,_)=>l(s)?(a(),i("aside",{key:0,class:T(["VPSidebar",{open:p.open}]),ref_key:"navEl",ref:o,onClick:_[0]||(_[0]=ht(()=>{},["stop"]))},[kl,u("nav",$l,[Pl,c(p.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),i(C,null,H(l(t),y=>(a(),i("div",{key:y.text,class:"group"},[h(bl,{item:y,depth:0},null,8,["item"])]))),128)),c(p.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}});const wl=m(Vl,[["__scopeId","data-v-845b8fc6"]]),Sl=g({__name:"VPSkipLink",setup(n){const e=te(),t=w();K(()=>e.path,()=>t.value.focus());function s({target:o}){const r=document.getElementById(decodeURIComponent(o.hash).slice(1));if(r){const d=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",d)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",d),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(a(),i(C,null,[u("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),u("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:s}," Skip to content ")],64))}});const Ll=m(Sl,[["__scopeId","data-v-ae3e3f51"]]),Ml=g({__name:"Layout",setup(n){const{isOpen:e,open:t,close:s}=O(),o=te();K(()=>o.path,s),Ot(e,s),oe("close-sidebar",s),oe("is-sidebar-open",e);const{frontmatter:r}=P(),d=ft(),p=k(()=>!!d["home-hero-image"]);return oe("hero-image-slot-exists",p),(_,y)=>{const L=U("Content");return l(r).layout!==!1?(a(),i("div",{key:0,class:T(["Layout",l(r).pageClass])},[c(_.$slots,"layout-top",{},void 0,!0),h(Ll),h(kt,{class:"backdrop",show:l(e),onClick:l(s)},null,8,["show","onClick"]),l(r).navbar!==!1?(a(),b(vl,{key:0},{"nav-bar-title-before":v(()=>[c(_.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":v(()=>[c(_.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":v(()=>[c(_.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":v(()=>[c(_.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":v(()=>[c(_.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":v(()=>[c(_.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3})):f("",!0),h(yo,{open:l(e),onOpenMenu:l(t)},null,8,["open","onOpenMenu"]),h(wl,{open:l(e)},{"sidebar-nav-before":v(()=>[c(_.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":v(()=>[c(_.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),h(Js,null,{"page-top":v(()=>[c(_.$slots,"page-top",{},void 0,!0)]),"page-bottom":v(()=>[c(_.$slots,"page-bottom",{},void 0,!0)]),"not-found":v(()=>[c(_.$slots,"not-found",{},void 0,!0)]),"home-hero-before":v(()=>[c(_.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":v(()=>[c(_.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":v(()=>[c(_.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":v(()=>[c(_.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":v(()=>[c(_.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":v(()=>[c(_.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":v(()=>[c(_.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":v(()=>[c(_.$slots,"doc-before",{},void 0,!0)]),"doc-after":v(()=>[c(_.$slots,"doc-after",{},void 0,!0)]),"doc-top":v(()=>[c(_.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":v(()=>[c(_.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":v(()=>[c(_.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":v(()=>[c(_.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":v(()=>[c(_.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":v(()=>[c(_.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":v(()=>[c(_.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":v(()=>[c(_.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),h(so),c(_.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),b(L,{key:1}))}}});const Cl=m(Ml,[["__scopeId","data-v-255ec12d"]]);const Tl={Layout:Cl,enhanceApp:({app:n})=>{n.component("Badge",gt)}};export{Tl as t,P as u}; diff --git a/assets/chunks/wk7.6fe7513d.js b/assets/chunks/wk7.6fe7513d.js deleted file mode 100644 index f58e8af9e1..0000000000 --- a/assets/chunks/wk7.6fe7513d.js +++ /dev/null @@ -1 +0,0 @@ -const s="/assets/wk7.38e3cd7d.png";export{s as _}; diff --git a/assets/chunks/wk7.776871bd.js b/assets/chunks/wk7.776871bd.js deleted file mode 100644 index f58e8af9e1..0000000000 --- a/assets/chunks/wk7.776871bd.js +++ /dev/null @@ -1 +0,0 @@ -const s="/assets/wk7.38e3cd7d.png";export{s as _}; diff --git a/assets/chunks/wk7.Bl1-W8YX.js b/assets/chunks/wk7.Bl1-W8YX.js new file mode 100644 index 0000000000..b1ed72e944 --- /dev/null +++ b/assets/chunks/wk7.Bl1-W8YX.js @@ -0,0 +1 @@ +const s="/assets/wk7.B0gH-0gL.png";export{s as _}; diff --git a/assets/chunks/wk7.BpuwpIoq.js b/assets/chunks/wk7.BpuwpIoq.js new file mode 100644 index 0000000000..b1ed72e944 --- /dev/null +++ b/assets/chunks/wk7.BpuwpIoq.js @@ -0,0 +1 @@ +const s="/assets/wk7.B0gH-0gL.png";export{s as _}; diff --git a/assets/cpu.4618bc7b.png b/assets/cpu.DedcVQ_T.png similarity index 100% rename from assets/cpu.4618bc7b.png rename to assets/cpu.DedcVQ_T.png diff --git a/assets/developer_index.md.4b11aa55.js b/assets/developer_index.md.CXHgEkLk.js similarity index 67% rename from assets/developer_index.md.4b11aa55.js rename to assets/developer_index.md.CXHgEkLk.js index f88e84439f..8869e38f91 100644 --- a/assets/developer_index.md.4b11aa55.js +++ b/assets/developer_index.md.CXHgEkLk.js @@ -1 +1 @@ -import{_ as e,v as t,b as a}from"./chunks/framework.70afa331.js";const c=JSON.parse('{"title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","description":"","frontmatter":{"layout":"home","title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","hero":{"name":"开发手册","text":"开发手册","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/developer/l10n"}]}},"headers":[],"relativePath":"developer/index.md","filePath":"developer/index.md","lastUpdated":1747972048000}'),s={name:"developer/index.md"};function n(r,i,l,o,p,d){return t(),a("div")}const h=e(s,[["render",n]]);export{c as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","description":"","frontmatter":{"layout":"home","title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","hero":{"name":"开发手册","text":"开发手册","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/developer/l10n"}]}},"headers":[],"relativePath":"developer/index.md","filePath":"developer/index.md","lastUpdated":1747984962000}'),n={name:"developer/index.md"};function l(o,r,s,i,p,d){return a(),t("div")}const h=e(n,[["render",l]]);export{m as __pageData,h as default}; diff --git a/assets/developer_index.md.4b11aa55.lean.js b/assets/developer_index.md.CXHgEkLk.lean.js similarity index 67% rename from assets/developer_index.md.4b11aa55.lean.js rename to assets/developer_index.md.CXHgEkLk.lean.js index f88e84439f..8869e38f91 100644 --- a/assets/developer_index.md.4b11aa55.lean.js +++ b/assets/developer_index.md.CXHgEkLk.lean.js @@ -1 +1 @@ -import{_ as e,v as t,b as a}from"./chunks/framework.70afa331.js";const c=JSON.parse('{"title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","description":"","frontmatter":{"layout":"home","title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","hero":{"name":"开发手册","text":"开发手册","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/developer/l10n"}]}},"headers":[],"relativePath":"developer/index.md","filePath":"developer/index.md","lastUpdated":1747972048000}'),s={name:"developer/index.md"};function n(r,i,l,o,p,d){return t(),a("div")}const h=e(s,[["render",n]]);export{c as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","description":"","frontmatter":{"layout":"home","title":"开发手册","titleTemplate":"欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好!","hero":{"name":"开发手册","text":"开发手册","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/developer/l10n"}]}},"headers":[],"relativePath":"developer/index.md","filePath":"developer/index.md","lastUpdated":1747984962000}'),n={name:"developer/index.md"};function l(o,r,s,i,p,d){return a(),t("div")}const h=e(n,[["render",l]]);export{m as __pageData,h as default}; diff --git a/assets/developer_l10n.md.DbKLx65f.js b/assets/developer_l10n.md.DbKLx65f.js new file mode 100644 index 0000000000..f7f0a2718f --- /dev/null +++ b/assets/developer_l10n.md.DbKLx65f.js @@ -0,0 +1 @@ +import{_ as o,c as l,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"developer/l10n.md","filePath":"developer/l10n.md","lastUpdated":1747984962000}'),r={name:"developer/l10n.md"};function d(n,e,i,c,s,_){return a(),l("div",null,e[0]||(e[0]=[t('

你可以在开发新功能时遵循以下步骤来支持本地化

介绍

  1. 你可以直接使用 /resource/l10n/zh-CN.toml 中已有的文本配置来替换新功能中的文本
  2. 如果新功能中有新增文本,请参考 zh-CN.toml 的配置文本,将新文本拉取到 zh-CN.toml 等其他语言的配置文件中,并添加翻译

新本地化文本的添加

  1. /resource/l10n/ 中添加新的语言文本配置
  2. 在新的语言文本配置中拉取其他语言已有的文本配置
  3. 为新的语言文本配置添加翻译
',5)]))}const m=o(r,[["render",d]]);export{h as __pageData,m as default}; diff --git a/assets/developer_l10n.md.DbKLx65f.lean.js b/assets/developer_l10n.md.DbKLx65f.lean.js new file mode 100644 index 0000000000..520f8c53ec --- /dev/null +++ b/assets/developer_l10n.md.DbKLx65f.lean.js @@ -0,0 +1 @@ +import{_ as o,c as l,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"developer/l10n.md","filePath":"developer/l10n.md","lastUpdated":1747984962000}'),r={name:"developer/l10n.md"};function d(n,e,i,c,s,_){return a(),l("div",null,e[0]||(e[0]=[t("",5)]))}const m=o(r,[["render",d]]);export{h as __pageData,m as default}; diff --git a/assets/developer_l10n.md.f381c679.js b/assets/developer_l10n.md.f381c679.js deleted file mode 100644 index 2e10afbc9e..0000000000 --- a/assets/developer_l10n.md.f381c679.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as o,b as t,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"developer/l10n.md","filePath":"developer/l10n.md","lastUpdated":1747972048000}'),l={name:"developer/l10n.md"},r=a('

你可以在开发新功能时遵循以下步骤来支持本地化

介绍

  1. 你可以直接使用 /resource/l10n/zh-CN.toml 中已有的文本配置来替换新功能中的文本
  2. 如果新功能中有新增文本,请参考 zh-CN.toml 的配置文本,将新文本拉取到 zh-CN.toml 等其他语言的配置文件中,并添加翻译

新本地化文本的添加

  1. /resource/l10n/ 中添加新的语言文本配置
  2. 在新的语言文本配置中拉取其他语言已有的文本配置
  3. 为新的语言文本配置添加翻译
',5),s=[r];function d(i,n,c,h,p,_){return o(),t("div",null,s)}const f=e(l,[["render",d]]);export{u as __pageData,f as default}; diff --git a/assets/developer_l10n.md.f381c679.lean.js b/assets/developer_l10n.md.f381c679.lean.js deleted file mode 100644 index 2e10afbc9e..0000000000 --- a/assets/developer_l10n.md.f381c679.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as o,b as t,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"developer/l10n.md","filePath":"developer/l10n.md","lastUpdated":1747972048000}'),l={name:"developer/l10n.md"},r=a('

你可以在开发新功能时遵循以下步骤来支持本地化

介绍

  1. 你可以直接使用 /resource/l10n/zh-CN.toml 中已有的文本配置来替换新功能中的文本
  2. 如果新功能中有新增文本,请参考 zh-CN.toml 的配置文本,将新文本拉取到 zh-CN.toml 等其他语言的配置文件中,并添加翻译

新本地化文本的添加

  1. /resource/l10n/ 中添加新的语言文本配置
  2. 在新的语言文本配置中拉取其他语言已有的文本配置
  3. 为新的语言文本配置添加翻译
',5),s=[r];function d(i,n,c,h,p,_){return o(),t("div",null,s)}const f=e(l,[["render",d]]);export{u as __pageData,f as default}; diff --git a/assets/disks.8065a143.png b/assets/disks.BJniy5pO.png similarity index 100% rename from assets/disks.8065a143.png rename to assets/disks.BJniy5pO.png diff --git a/assets/dlwiniso.a2c0c1ef.png b/assets/dlwiniso.BxXucu9m.png similarity index 100% rename from assets/dlwiniso.a2c0c1ef.png rename to assets/dlwiniso.BxXucu9m.png diff --git a/assets/dlwiniso1.4fa2fea0.png b/assets/dlwiniso1.CQyxWlSu.png similarity index 100% rename from assets/dlwiniso1.4fa2fea0.png rename to assets/dlwiniso1.CQyxWlSu.png diff --git a/assets/dns0.1beb9fa7.png b/assets/dns0.DDagSewr.png similarity index 100% rename from assets/dns0.1beb9fa7.png rename to assets/dns0.DDagSewr.png diff --git a/assets/en_developer_index.md.a033415e.js b/assets/en_developer_index.md.zTlMOyHV.js similarity index 77% rename from assets/en_developer_index.md.a033415e.js rename to assets/en_developer_index.md.zTlMOyHV.js index d46f6de227..fb75f9170b 100644 --- a/assets/en_developer_index.md.a033415e.js +++ b/assets/en_developer_index.md.zTlMOyHV.js @@ -1 +1 @@ -import{_ as e,v as t,b as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","description":"","frontmatter":{"layout":"home","title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","hero":{"name":"Development Manual","text":"Welcome to the oneclickvirt Development Manual.","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Start Now →","link":"/en_US/developer/l10n"}]}},"headers":[],"relativePath":"en/developer/index.md","filePath":"en/developer/index.md","lastUpdated":1747972048000}'),a={name:"en/developer/index.md"};function o(l,i,r,p,m,s){return t(),n("div")}const v=e(a,[["render",o]]);export{d as __pageData,v as default}; +import{_ as e,c as t,o as n}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","description":"","frontmatter":{"layout":"home","title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","hero":{"name":"Development Manual","text":"Welcome to the oneclickvirt Development Manual.","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Start Now →","link":"/en_US/developer/l10n"}]}},"headers":[],"relativePath":"en/developer/index.md","filePath":"en/developer/index.md","lastUpdated":1747984962000}'),a={name:"en/developer/index.md"};function o(l,r,i,p,c,m){return n(),t("div")}const v=e(a,[["render",o]]);export{d as __pageData,v as default}; diff --git a/assets/en_developer_index.md.a033415e.lean.js b/assets/en_developer_index.md.zTlMOyHV.lean.js similarity index 77% rename from assets/en_developer_index.md.a033415e.lean.js rename to assets/en_developer_index.md.zTlMOyHV.lean.js index d46f6de227..fb75f9170b 100644 --- a/assets/en_developer_index.md.a033415e.lean.js +++ b/assets/en_developer_index.md.zTlMOyHV.lean.js @@ -1 +1 @@ -import{_ as e,v as t,b as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","description":"","frontmatter":{"layout":"home","title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","hero":{"name":"Development Manual","text":"Welcome to the oneclickvirt Development Manual.","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Start Now →","link":"/en_US/developer/l10n"}]}},"headers":[],"relativePath":"en/developer/index.md","filePath":"en/developer/index.md","lastUpdated":1747972048000}'),a={name:"en/developer/index.md"};function o(l,i,r,p,m,s){return t(),n("div")}const v=e(a,[["render",o]]);export{d as __pageData,v as default}; +import{_ as e,c as t,o as n}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","description":"","frontmatter":{"layout":"home","title":"Development Manual","titleTemplate":"Welcome to the oneclickvirt Development Manual.","hero":{"name":"Development Manual","text":"Welcome to the oneclickvirt Development Manual.","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Start Now →","link":"/en_US/developer/l10n"}]}},"headers":[],"relativePath":"en/developer/index.md","filePath":"en/developer/index.md","lastUpdated":1747984962000}'),a={name:"en/developer/index.md"};function o(l,r,i,p,c,m){return n(),t("div")}const v=e(a,[["render",o]]);export{d as __pageData,v as default}; diff --git a/assets/en_developer_l10n.md.2567a7c2.js b/assets/en_developer_l10n.md.2567a7c2.js deleted file mode 100644 index 5596b9f813..0000000000 --- a/assets/en_developer_l10n.md.2567a7c2.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as n,R as o}from"./chunks/framework.70afa331.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/developer/l10n.md","filePath":"en/developer/l10n.md","lastUpdated":1747972048000}'),a={name:"en/developer/l10n.md"},i=o('

You can follow these steps to support localization when developing new features

Introduction

  1. You can directly use the text configuration already available in /resource/l10n/en-US.toml to replace the text in the new feature.
  2. If there is new text in the new feature, please refer to the configuration text in en-US.toml, pull the new text into the configuration files of other languages such as en-US.toml, and add translations.

Adding a new localized text file

  1. Add a new language text configuration in /resource/l10n/.
  2. Pull existing text configurations from other languages in the new language text configuration.
  3. Add translations for the new language text configuration.
',5),l=[i];function r(d,s,c,u,f,h){return t(),n("div",null,l)}const x=e(a,[["render",r]]);export{p as __pageData,x as default}; diff --git a/assets/en_developer_l10n.md.2567a7c2.lean.js b/assets/en_developer_l10n.md.2567a7c2.lean.js deleted file mode 100644 index 5596b9f813..0000000000 --- a/assets/en_developer_l10n.md.2567a7c2.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as n,R as o}from"./chunks/framework.70afa331.js";const p=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/developer/l10n.md","filePath":"en/developer/l10n.md","lastUpdated":1747972048000}'),a={name:"en/developer/l10n.md"},i=o('

You can follow these steps to support localization when developing new features

Introduction

  1. You can directly use the text configuration already available in /resource/l10n/en-US.toml to replace the text in the new feature.
  2. If there is new text in the new feature, please refer to the configuration text in en-US.toml, pull the new text into the configuration files of other languages such as en-US.toml, and add translations.

Adding a new localized text file

  1. Add a new language text configuration in /resource/l10n/.
  2. Pull existing text configurations from other languages in the new language text configuration.
  3. Add translations for the new language text configuration.
',5),l=[i];function r(d,s,c,u,f,h){return t(),n("div",null,l)}const x=e(a,[["render",r]]);export{p as __pageData,x as default}; diff --git a/assets/en_developer_l10n.md.CFaXJ2l2.js b/assets/en_developer_l10n.md.CFaXJ2l2.js new file mode 100644 index 0000000000..417d5e230c --- /dev/null +++ b/assets/en_developer_l10n.md.CFaXJ2l2.js @@ -0,0 +1 @@ +import{_ as t,c as n,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/developer/l10n.md","filePath":"en/developer/l10n.md","lastUpdated":1747984962000}'),i={name:"en/developer/l10n.md"};function l(r,e,d,c,s,u){return a(),n("div",null,e[0]||(e[0]=[o('

You can follow these steps to support localization when developing new features

Introduction

  1. You can directly use the text configuration already available in /resource/l10n/en-US.toml to replace the text in the new feature.
  2. If there is new text in the new feature, please refer to the configuration text in en-US.toml, pull the new text into the configuration files of other languages such as en-US.toml, and add translations.

Adding a new localized text file

  1. Add a new language text configuration in /resource/l10n/.
  2. Pull existing text configurations from other languages in the new language text configuration.
  3. Add translations for the new language text configuration.
',5)]))}const h=t(i,[["render",l]]);export{g as __pageData,h as default}; diff --git a/assets/en_developer_l10n.md.CFaXJ2l2.lean.js b/assets/en_developer_l10n.md.CFaXJ2l2.lean.js new file mode 100644 index 0000000000..2b637f5bf1 --- /dev/null +++ b/assets/en_developer_l10n.md.CFaXJ2l2.lean.js @@ -0,0 +1 @@ +import{_ as t,c as n,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/developer/l10n.md","filePath":"en/developer/l10n.md","lastUpdated":1747984962000}'),i={name:"en/developer/l10n.md"};function l(r,e,d,c,s,u){return a(),n("div",null,e[0]||(e[0]=[o("",5)]))}const h=t(i,[["render",l]]);export{g as __pageData,h as default}; diff --git a/assets/en_guide_block_block_docker.md.2627dfbd.js b/assets/en_guide_block_block_docker.md.2627dfbd.js deleted file mode 100644 index 3c87c8ed16..0000000000 --- a/assets/en_guide_block_block_docker.md.2627dfbd.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as o,b as d,F as e,L as a}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"To be developed, stay tuned","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_docker.md","filePath":"en/guide/block/block_docker.md","lastUpdated":1747972048000}'),s={name:"en/guide/block/block_docker.md"},n=e("h1",{id:"to-be-developed-stay-tuned",tabindex:"-1"},[a("To be developed, stay tuned "),e("a",{class:"header-anchor",href:"#to-be-developed-stay-tuned","aria-label":'Permalink to "To be developed, stay tuned"'},"​")],-1),c=[n];function r(l,i,_,p,b,u){return o(),d("div",null,c)}const f=t(s,[["render",r]]);export{h as __pageData,f as default}; diff --git a/assets/en_guide_block_block_docker.md.2627dfbd.lean.js b/assets/en_guide_block_block_docker.md.2627dfbd.lean.js deleted file mode 100644 index 3c87c8ed16..0000000000 --- a/assets/en_guide_block_block_docker.md.2627dfbd.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as o,b as d,F as e,L as a}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"To be developed, stay tuned","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_docker.md","filePath":"en/guide/block/block_docker.md","lastUpdated":1747972048000}'),s={name:"en/guide/block/block_docker.md"},n=e("h1",{id:"to-be-developed-stay-tuned",tabindex:"-1"},[a("To be developed, stay tuned "),e("a",{class:"header-anchor",href:"#to-be-developed-stay-tuned","aria-label":'Permalink to "To be developed, stay tuned"'},"​")],-1),c=[n];function r(l,i,_,p,b,u){return o(),d("div",null,c)}const f=t(s,[["render",r]]);export{h as __pageData,f as default}; diff --git a/assets/en_guide_block_block_docker.md.Bu7zbkEq.js b/assets/en_guide_block_block_docker.md.Bu7zbkEq.js new file mode 100644 index 0000000000..c1bfb91853 --- /dev/null +++ b/assets/en_guide_block_block_docker.md.Bu7zbkEq.js @@ -0,0 +1 @@ +import{_ as o,c as a,o as d,j as t,a as r}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"To be developed, stay tuned","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_docker.md","filePath":"en/guide/block/block_docker.md","lastUpdated":1747984962000}'),n={name:"en/guide/block/block_docker.md"};function l(s,e,c,i,p,b){return d(),a("div",null,e[0]||(e[0]=[t("h1",{id:"to-be-developed-stay-tuned",tabindex:"-1"},[r("To be developed, stay tuned "),t("a",{class:"header-anchor",href:"#to-be-developed-stay-tuned","aria-label":'Permalink to "To be developed, stay tuned"'},"​")],-1)]))}const _=o(n,[["render",l]]);export{u as __pageData,_ as default}; diff --git a/assets/en_guide_block_block_docker.md.Bu7zbkEq.lean.js b/assets/en_guide_block_block_docker.md.Bu7zbkEq.lean.js new file mode 100644 index 0000000000..c1bfb91853 --- /dev/null +++ b/assets/en_guide_block_block_docker.md.Bu7zbkEq.lean.js @@ -0,0 +1 @@ +import{_ as o,c as a,o as d,j as t,a as r}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"To be developed, stay tuned","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_docker.md","filePath":"en/guide/block/block_docker.md","lastUpdated":1747984962000}'),n={name:"en/guide/block/block_docker.md"};function l(s,e,c,i,p,b){return d(),a("div",null,e[0]||(e[0]=[t("h1",{id:"to-be-developed-stay-tuned",tabindex:"-1"},[r("To be developed, stay tuned "),t("a",{class:"header-anchor",href:"#to-be-developed-stay-tuned","aria-label":'Permalink to "To be developed, stay tuned"'},"​")],-1)]))}const _=o(n,[["render",l]]);export{u as __pageData,_ as default}; diff --git a/assets/en_guide_block_block_incus.md.95762549.js b/assets/en_guide_block_block_incus.md.95762549.js deleted file mode 100644 index a47eb7cd55..0000000000 --- a/assets/en_guide_block_block_incus.md.95762549.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as n,b as o,R as a}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_incus.md","filePath":"en/guide/block/block_incus.md","lastUpdated":1747972048000}'),e={name:"en/guide/block/block_incus.md"},t=a('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9),l=[t];function i(r,c,p,d,m,u){return n(),o("div",null,l)}const y=s(e,[["render",i]]);export{C as __pageData,y as default}; diff --git a/assets/en_guide_block_block_incus.md.95762549.lean.js b/assets/en_guide_block_block_incus.md.95762549.lean.js deleted file mode 100644 index a47eb7cd55..0000000000 --- a/assets/en_guide_block_block_incus.md.95762549.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as n,b as o,R as a}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_incus.md","filePath":"en/guide/block/block_incus.md","lastUpdated":1747972048000}'),e={name:"en/guide/block/block_incus.md"},t=a('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9),l=[t];function i(r,c,p,d,m,u){return n(),o("div",null,l)}const y=s(e,[["render",i]]);export{C as __pageData,y as default}; diff --git a/assets/en_guide_block_block_incus.md.BTs-piI_.js b/assets/en_guide_block_block_incus.md.BTs-piI_.js new file mode 100644 index 0000000000..f140f157ce --- /dev/null +++ b/assets/en_guide_block_block_incus.md.BTs-piI_.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_incus.md","filePath":"en/guide/block/block_incus.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_incus.md"};function o(l,i,r,h,p,c){return e(),a("div",null,i[0]||(i[0]=[n('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9)]))}const g=s(t,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_block_block_incus.md.BTs-piI_.lean.js b/assets/en_guide_block_block_incus.md.BTs-piI_.lean.js new file mode 100644 index 0000000000..9981902dae --- /dev/null +++ b/assets/en_guide_block_block_incus.md.BTs-piI_.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_incus.md","filePath":"en/guide/block/block_incus.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_incus.md"};function o(l,i,r,h,p,c){return e(),a("div",null,i[0]||(i[0]=[n("",9)]))}const g=s(t,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_block_block_iptables.md.6506e0bc.js b/assets/en_guide_block_block_iptables.md.6506e0bc.js deleted file mode 100644 index bf15a1f84d..0000000000 --- a/assets/en_guide_block_block_iptables.md.6506e0bc.js +++ /dev/null @@ -1,54 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Blocking abuse through iptables","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_iptables.md","filePath":"en/guide/block/block_iptables.md","lastUpdated":1747972048000}'),l={name:"en/guide/block/block_iptables.md"},o=e(`

Blocking abuse through iptables

Basic Usage of iptables

1. Start iptables

In most Linux distributions, the iptables service can be started using the following command:

bash
sudo systemctl start iptables

2. Set Rules

After starting iptables, you can set rules to block abusive traffic. For example, the following command will block traffic from a specific IPv4 address:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. Query Rules

After setting the rules, you can use the following command to view the current iptables rules:

bash
sudo iptables -L

This will list all input, output, and forwarding rules.

4. Stop iptables

If you need to stop the iptables service, you can use the following command:

bash
sudo systemctl stop iptables

5. Save Rules

To ensure that the rules persist after a reboot, you can save the current rules:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. Restore Rules

When you need to restore the rules, you can use the following command:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. Other Common Commands

  • List Rules (Detailed Information):

    bash
    sudo iptables -L -v
  • Delete Specific Rule:

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • Flush All Rules:

    bash
    sudo iptables -F

Block abusive traffic on the host

  • prevention in advance

Blocking Mining Behavior

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking BT behavior

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking Speed Test Behavior

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
`,31),t=[o];function p(c,r,i,u,C,d){return a(),n("div",null,t)}const y=s(l,[["render",p]]);export{h as __pageData,y as default}; diff --git a/assets/en_guide_block_block_iptables.md.6506e0bc.lean.js b/assets/en_guide_block_block_iptables.md.6506e0bc.lean.js deleted file mode 100644 index bf15a1f84d..0000000000 --- a/assets/en_guide_block_block_iptables.md.6506e0bc.lean.js +++ /dev/null @@ -1,54 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Blocking abuse through iptables","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_iptables.md","filePath":"en/guide/block/block_iptables.md","lastUpdated":1747972048000}'),l={name:"en/guide/block/block_iptables.md"},o=e(`

Blocking abuse through iptables

Basic Usage of iptables

1. Start iptables

In most Linux distributions, the iptables service can be started using the following command:

bash
sudo systemctl start iptables

2. Set Rules

After starting iptables, you can set rules to block abusive traffic. For example, the following command will block traffic from a specific IPv4 address:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. Query Rules

After setting the rules, you can use the following command to view the current iptables rules:

bash
sudo iptables -L

This will list all input, output, and forwarding rules.

4. Stop iptables

If you need to stop the iptables service, you can use the following command:

bash
sudo systemctl stop iptables

5. Save Rules

To ensure that the rules persist after a reboot, you can save the current rules:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. Restore Rules

When you need to restore the rules, you can use the following command:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. Other Common Commands

  • List Rules (Detailed Information):

    bash
    sudo iptables -L -v
  • Delete Specific Rule:

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • Flush All Rules:

    bash
    sudo iptables -F

Block abusive traffic on the host

  • prevention in advance

Blocking Mining Behavior

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking BT behavior

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking Speed Test Behavior

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
`,31),t=[o];function p(c,r,i,u,C,d){return a(),n("div",null,t)}const y=s(l,[["render",p]]);export{h as __pageData,y as default}; diff --git a/assets/en_guide_block_block_iptables.md.ByV6snur.js b/assets/en_guide_block_block_iptables.md.ByV6snur.js new file mode 100644 index 0000000000..bddf453ada --- /dev/null +++ b/assets/en_guide_block_block_iptables.md.ByV6snur.js @@ -0,0 +1,54 @@ +import{_ as a,c as n,o as e,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Blocking abuse through iptables","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_iptables.md","filePath":"en/guide/block/block_iptables.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_iptables.md"};function p(l,s,o,h,c,r){return e(),n("div",null,s[0]||(s[0]=[i(`

Blocking abuse through iptables

Basic Usage of iptables

1. Start iptables

In most Linux distributions, the iptables service can be started using the following command:

bash
sudo systemctl start iptables

2. Set Rules

After starting iptables, you can set rules to block abusive traffic. For example, the following command will block traffic from a specific IPv4 address:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. Query Rules

After setting the rules, you can use the following command to view the current iptables rules:

bash
sudo iptables -L

This will list all input, output, and forwarding rules.

4. Stop iptables

If you need to stop the iptables service, you can use the following command:

bash
sudo systemctl stop iptables

5. Save Rules

To ensure that the rules persist after a reboot, you can save the current rules:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. Restore Rules

When you need to restore the rules, you can use the following command:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. Other Common Commands

  • List Rules (Detailed Information):

    bash
    sudo iptables -L -v
  • Delete Specific Rule:

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • Flush All Rules:

    bash
    sudo iptables -F

Block abusive traffic on the host

  • prevention in advance

Blocking Mining Behavior

strings=(
+    "ethermine.com"
+    "antpool.one"
+    "antpool.com"
+    "pool.bar"
+    "get_peers"
+    "announce_peer"
+    "find_node"
+    "seed_hash"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

Blocking BT behavior

strings=(
+    "torrent"
+    ".torrent"
+    "peer_id="
+    "announce"
+    "info_hash"
+    "get_peers"
+    "find_node"
+    "BitTorrent"
+    "announce_peer"
+    "BitTorrent protocol"
+    "announce.php?passkey="
+    "magnet:"
+    "xunlei"
+    "sandai"
+    "Thunder"
+    "XLLiveUD"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

Blocking Speed Test Behavior

strings=(
+    ".speed"
+    "speed."
+    ".speed."
+    "fast.com"
+    "speedtest.net"
+    "speedtest.com"
+    "speedtest.cn"
+    "test.ustc.edu.cn"
+    "10000.gd.cn"
+    "db.laomoe.com"
+    "jiyou.cloud"
+    "ovo.speedtestcustom.com"
+    "speed.cloudflare.com"
+    "speedtest"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done
`,31)]))}const k=a(t,[["render",p]]);export{u as __pageData,k as default}; diff --git a/assets/en_guide_block_block_iptables.md.ByV6snur.lean.js b/assets/en_guide_block_block_iptables.md.ByV6snur.lean.js new file mode 100644 index 0000000000..6ef76b4773 --- /dev/null +++ b/assets/en_guide_block_block_iptables.md.ByV6snur.lean.js @@ -0,0 +1 @@ +import{_ as a,c as n,o as e,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Blocking abuse through iptables","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_iptables.md","filePath":"en/guide/block/block_iptables.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_iptables.md"};function p(l,s,o,h,c,r){return e(),n("div",null,s[0]||(s[0]=[i("",31)]))}const k=a(t,[["render",p]]);export{u as __pageData,k as default}; diff --git a/assets/en_guide_block_block_lxd.md.616a5093.js b/assets/en_guide_block_block_lxd.md.616a5093.js deleted file mode 100644 index ea73007e5e..0000000000 --- a/assets/en_guide_block_block_lxd.md.616a5093.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as o,b as n,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_lxd.md","filePath":"en/guide/block/block_lxd.md","lastUpdated":1747972048000}'),e={name:"en/guide/block/block_lxd.md"},l=a('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9),t=[l];function i(r,p,c,d,m,h){return o(),n("div",null,t)}const y=s(e,[["render",i]]);export{u as __pageData,y as default}; diff --git a/assets/en_guide_block_block_lxd.md.616a5093.lean.js b/assets/en_guide_block_block_lxd.md.616a5093.lean.js deleted file mode 100644 index ea73007e5e..0000000000 --- a/assets/en_guide_block_block_lxd.md.616a5093.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as o,b as n,R as a}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_lxd.md","filePath":"en/guide/block/block_lxd.md","lastUpdated":1747972048000}'),e={name:"en/guide/block/block_lxd.md"},l=a('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9),t=[l];function i(r,p,c,d,m,h){return o(),n("div",null,t)}const y=s(e,[["render",i]]);export{u as __pageData,y as default}; diff --git a/assets/en_guide_block_block_lxd.md.BToyiHH5.js b/assets/en_guide_block_block_lxd.md.BToyiHH5.js new file mode 100644 index 0000000000..da3435bb3f --- /dev/null +++ b/assets/en_guide_block_block_lxd.md.BToyiHH5.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_lxd.md","filePath":"en/guide/block/block_lxd.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_lxd.md"};function o(l,i,r,h,p,c){return e(),a("div",null,i[0]||(i[0]=[n('

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',9)]))}const g=s(t,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_block_block_lxd.md.BToyiHH5.lean.js b/assets/en_guide_block_block_lxd.md.BToyiHH5.lean.js new file mode 100644 index 0000000000..83788026bd --- /dev/null +++ b/assets/en_guide_block_block_lxd.md.BToyiHH5.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Blocking Abusive Behavior via Shell Scripts","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_lxd.md","filePath":"en/guide/block/block_lxd.md","lastUpdated":1747984962000}'),t={name:"en/guide/block/block_lxd.md"};function o(l,i,r,h,p,c){return e(),a("div",null,i[0]||(i[0]=[n("",9)]))}const g=s(t,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_block_block_pve.md.86088ae1.js b/assets/en_guide_block_block_pve.md.86088ae1.js deleted file mode 100644 index 8b2a515654..0000000000 --- a/assets/en_guide_block_block_pve.md.86088ae1.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const b=JSON.parse('{"title":"Avoid theft by setting up a firewall to limit the IPs used by the VMs","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_pve.md","filePath":"en/guide/block/block_pve.md","lastUpdated":1747972048000}'),n={name:"en/guide/block/block_pve.md"},o=a(`

Avoid theft by setting up a firewall to limit the IPs used by the VMs

Create the following file under the PVE's host machine

shell
/etc/pve/firewall/<VMID>.fw
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID> is replaced with the VMID number of the virtual machine, <net0> is replaced with the corresponding alias in the network device (which generally doesn't need to be changed unless you're restricted to IPV6), and xxx.xxx.xxx.xxx is replaced with the public IP address, noting that this IP corresponds to the network device in front of it.

The idea here is that net0 can only use the IP xxx.xxx.xxx.xxx, if you use any other IP the data will be dropped, thus restricting the VM to only use this IP.

There can be more than one IP, once this rule is enabled the VM can't use any other IP, if you don't write an IPv6 address it means the VM can't use an IPv6 address.

TIP

This setting is only recommended when opening VMs with separate IPs that are not NAT full port mapped, otherwise it may cause strange issues resulting in the server being without a network.

This method is not suitable for use on PVEs that open any NAT VMs/containers.

`,8),i=[o];function l(r,p,h,c,d,u){return t(),s("div",null,i)}const g=e(n,[["render",l]]);export{b as __pageData,g as default}; diff --git a/assets/en_guide_block_block_pve.md.86088ae1.lean.js b/assets/en_guide_block_block_pve.md.86088ae1.lean.js deleted file mode 100644 index 8b2a515654..0000000000 --- a/assets/en_guide_block_block_pve.md.86088ae1.lean.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const b=JSON.parse('{"title":"Avoid theft by setting up a firewall to limit the IPs used by the VMs","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_pve.md","filePath":"en/guide/block/block_pve.md","lastUpdated":1747972048000}'),n={name:"en/guide/block/block_pve.md"},o=a(`

Avoid theft by setting up a firewall to limit the IPs used by the VMs

Create the following file under the PVE's host machine

shell
/etc/pve/firewall/<VMID>.fw
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID> is replaced with the VMID number of the virtual machine, <net0> is replaced with the corresponding alias in the network device (which generally doesn't need to be changed unless you're restricted to IPV6), and xxx.xxx.xxx.xxx is replaced with the public IP address, noting that this IP corresponds to the network device in front of it.

The idea here is that net0 can only use the IP xxx.xxx.xxx.xxx, if you use any other IP the data will be dropped, thus restricting the VM to only use this IP.

There can be more than one IP, once this rule is enabled the VM can't use any other IP, if you don't write an IPv6 address it means the VM can't use an IPv6 address.

TIP

This setting is only recommended when opening VMs with separate IPs that are not NAT full port mapped, otherwise it may cause strange issues resulting in the server being without a network.

This method is not suitable for use on PVEs that open any NAT VMs/containers.

`,8),i=[o];function l(r,p,h,c,d,u){return t(),s("div",null,i)}const g=e(n,[["render",l]]);export{b as __pageData,g as default}; diff --git a/assets/en_guide_block_block_pve.md.Bi62dGs9.js b/assets/en_guide_block_block_pve.md.Bi62dGs9.js new file mode 100644 index 0000000000..dc98b154b1 --- /dev/null +++ b/assets/en_guide_block_block_pve.md.Bi62dGs9.js @@ -0,0 +1,3 @@ +import{_ as t,c as s,o as i,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Avoid theft by setting up a firewall to limit the IPs used by the VMs","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_pve.md","filePath":"en/guide/block/block_pve.md","lastUpdated":1747984962000}'),n={name:"en/guide/block/block_pve.md"};function l(o,e,h,r,p,d){return i(),s("div",null,e[0]||(e[0]=[a(`

Avoid theft by setting up a firewall to limit the IPs used by the VMs

Create the following file under the PVE's host machine

shell
/etc/pve/firewall/<VMID>.fw
+[IPSET ipfilter-<net0>]
+xxx.xxx.xxx.xxx

<VMID> is replaced with the VMID number of the virtual machine, <net0> is replaced with the corresponding alias in the network device (which generally doesn't need to be changed unless you're restricted to IPV6), and xxx.xxx.xxx.xxx is replaced with the public IP address, noting that this IP corresponds to the network device in front of it.

The idea here is that net0 can only use the IP xxx.xxx.xxx.xxx, if you use any other IP the data will be dropped, thus restricting the VM to only use this IP.

There can be more than one IP, once this rule is enabled the VM can't use any other IP, if you don't write an IPv6 address it means the VM can't use an IPv6 address.

TIP

This setting is only recommended when opening VMs with separate IPs that are not NAT full port mapped, otherwise it may cause strange issues resulting in the server being without a network.

This method is not suitable for use on PVEs that open any NAT VMs/containers.

`,8)]))}const g=t(n,[["render",l]]);export{u as __pageData,g as default}; diff --git a/assets/en_guide_block_block_pve.md.Bi62dGs9.lean.js b/assets/en_guide_block_block_pve.md.Bi62dGs9.lean.js new file mode 100644 index 0000000000..3552d25a74 --- /dev/null +++ b/assets/en_guide_block_block_pve.md.Bi62dGs9.lean.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as i,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Avoid theft by setting up a firewall to limit the IPs used by the VMs","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/block/block_pve.md","filePath":"en/guide/block/block_pve.md","lastUpdated":1747984962000}'),n={name:"en/guide/block/block_pve.md"};function l(o,e,h,r,p,d){return i(),s("div",null,e[0]||(e[0]=[a("",8)]))}const g=t(n,[["render",l]]);export{u as __pageData,g as default}; diff --git a/assets/en_guide_dashboard.md.04c46e68.js b/assets/en_guide_dashboard.md.04c46e68.js deleted file mode 100644 index 23b1d3636d..0000000000 --- a/assets/en_guide_dashboard.md.04c46e68.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as r}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/dashboard.md","filePath":"en/guide/dashboard.md","lastUpdated":1747972048000}'),i={name:"en/guide/dashboard.md"},o=r('

Preparation Work

To virtualize a server, you will need:

  1. A server (VPS or Dedicated Server) that can connect to the public internet. It's preferable if this server can access GitHub's RAW pages perfectly, as some projects and components might not use CDN acceleration.

  2. A stable SSH connection from your local machine. If the connection isn't stable, you can use the screen command to create a window and execute commands within that window.

TIP

If you're unfamiliar with the screen command, please search for relevant tutorials to learn it, or you can use tmux as an alternative.

  1. Ensure that the server's system and hardware meet the requirements specified by the corresponding project. Refer to the project's documentation for detailed information.

This document will use a VPS as an example, and the VPS should be clean without any native environment issues. If necessary, reinstall the system to ensure the initial environment's cleanliness.

WARNING

The PVE project might cause problems on the host machine. If you're not familiar with debugging bugs and fixing system issues, it's not recommended to use PVE in a production environment. When using PVE-related scripts, make sure the host machine can be reinstalled at any time.

Project Repository

Welcome Star and Fork, all resources are open source, no non-open source parts, reproduced as well as the use of please write on the source of this site, thank you!

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',21),s=[o];function n(l,c,h,p,d,u){return t(),a("div",null,s)}const b=e(i,[["render",n]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_dashboard.md.04c46e68.lean.js b/assets/en_guide_dashboard.md.04c46e68.lean.js deleted file mode 100644 index 23b1d3636d..0000000000 --- a/assets/en_guide_dashboard.md.04c46e68.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as r}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/dashboard.md","filePath":"en/guide/dashboard.md","lastUpdated":1747972048000}'),i={name:"en/guide/dashboard.md"},o=r('

Preparation Work

To virtualize a server, you will need:

  1. A server (VPS or Dedicated Server) that can connect to the public internet. It's preferable if this server can access GitHub's RAW pages perfectly, as some projects and components might not use CDN acceleration.

  2. A stable SSH connection from your local machine. If the connection isn't stable, you can use the screen command to create a window and execute commands within that window.

TIP

If you're unfamiliar with the screen command, please search for relevant tutorials to learn it, or you can use tmux as an alternative.

  1. Ensure that the server's system and hardware meet the requirements specified by the corresponding project. Refer to the project's documentation for detailed information.

This document will use a VPS as an example, and the VPS should be clean without any native environment issues. If necessary, reinstall the system to ensure the initial environment's cleanliness.

WARNING

The PVE project might cause problems on the host machine. If you're not familiar with debugging bugs and fixing system issues, it's not recommended to use PVE in a production environment. When using PVE-related scripts, make sure the host machine can be reinstalled at any time.

Project Repository

Welcome Star and Fork, all resources are open source, no non-open source parts, reproduced as well as the use of please write on the source of this site, thank you!

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',21),s=[o];function n(l,c,h,p,d,u){return t(),a("div",null,s)}const b=e(i,[["render",n]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_dashboard.md.CwRb4UsX.js b/assets/en_guide_dashboard.md.CwRb4UsX.js new file mode 100644 index 0000000000..0079a00045 --- /dev/null +++ b/assets/en_guide_dashboard.md.CwRb4UsX.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as r,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/dashboard.md","filePath":"en/guide/dashboard.md","lastUpdated":1747984962000}'),o={name:"en/guide/dashboard.md"};function s(n,e,l,c,h,p){return r(),a("div",null,e[0]||(e[0]=[i('

Preparation Work

To virtualize a server, you will need:

  1. A server (VPS or Dedicated Server) that can connect to the public internet. It's preferable if this server can access GitHub's RAW pages perfectly, as some projects and components might not use CDN acceleration.

  2. A stable SSH connection from your local machine. If the connection isn't stable, you can use the screen command to create a window and execute commands within that window.

TIP

If you're unfamiliar with the screen command, please search for relevant tutorials to learn it, or you can use tmux as an alternative.

  1. Ensure that the server's system and hardware meet the requirements specified by the corresponding project. Refer to the project's documentation for detailed information.

This document will use a VPS as an example, and the VPS should be clean without any native environment issues. If necessary, reinstall the system to ensure the initial environment's cleanliness.

WARNING

The PVE project might cause problems on the host machine. If you're not familiar with debugging bugs and fixing system issues, it's not recommended to use PVE in a production environment. When using PVE-related scripts, make sure the host machine can be reinstalled at any time.

Project Repository

Welcome Star and Fork, all resources are open source, no non-open source parts, reproduced as well as the use of please write on the source of this site, thank you!

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',21)]))}const m=t(o,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_dashboard.md.CwRb4UsX.lean.js b/assets/en_guide_dashboard.md.CwRb4UsX.lean.js new file mode 100644 index 0000000000..0178f95b2a --- /dev/null +++ b/assets/en_guide_dashboard.md.CwRb4UsX.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as r,ag as i}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/dashboard.md","filePath":"en/guide/dashboard.md","lastUpdated":1747984962000}'),o={name:"en/guide/dashboard.md"};function s(n,e,l,c,h,p){return r(),a("div",null,e[0]||(e[0]=[i("",21)]))}const m=t(o,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_dashboardq.md.220142b4.js b/assets/en_guide_dashboardq.md.220142b4.js deleted file mode 100644 index d9d2e06641..0000000000 --- a/assets/en_guide_dashboardq.md.220142b4.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as t}from"./chunks/framework.70afa331.js";const p="/assets/wechat.e3b2e06e.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/dashboardq.md","filePath":"en/guide/dashboardq.md","lastUpdated":1747972048000}'),o={name:"en/guide/dashboardq.md"},n=t('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8),c=[n];function i(l,r,d,h,b,f){return s(),e("div",null,c)}const g=a(o,[["render",i]]);export{_ as __pageData,g as default}; diff --git a/assets/en_guide_dashboardq.md.220142b4.lean.js b/assets/en_guide_dashboardq.md.220142b4.lean.js deleted file mode 100644 index d9d2e06641..0000000000 --- a/assets/en_guide_dashboardq.md.220142b4.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as t}from"./chunks/framework.70afa331.js";const p="/assets/wechat.e3b2e06e.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/dashboardq.md","filePath":"en/guide/dashboardq.md","lastUpdated":1747972048000}'),o={name:"en/guide/dashboardq.md"},n=t('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8),c=[n];function i(l,r,d,h,b,f){return s(),e("div",null,c)}const g=a(o,[["render",i]]);export{_ as __pageData,g as default}; diff --git a/assets/en_guide_dashboardq.md.BaUPP2a8.js b/assets/en_guide_dashboardq.md.BaUPP2a8.js new file mode 100644 index 0000000000..196924f9bf --- /dev/null +++ b/assets/en_guide_dashboardq.md.BaUPP2a8.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const p="/assets/wechat.BhfskdFa.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/dashboardq.md","filePath":"en/guide/dashboardq.md","lastUpdated":1747984962000}'),o={name:"en/guide/dashboardq.md"};function n(d,a,c,l,r,h){return t(),s("div",null,a[0]||(a[0]=[i('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8)]))}const g=e(o,[["render",n]]);export{_ as __pageData,g as default}; diff --git a/assets/en_guide_dashboardq.md.BaUPP2a8.lean.js b/assets/en_guide_dashboardq.md.BaUPP2a8.lean.js new file mode 100644 index 0000000000..d16d7ef17a --- /dev/null +++ b/assets/en_guide_dashboardq.md.BaUPP2a8.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const p="/assets/wechat.BhfskdFa.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/dashboardq.md","filePath":"en/guide/dashboardq.md","lastUpdated":1747984962000}'),o={name:"en/guide/dashboardq.md"};function n(d,a,c,l,r,h){return t(),s("div",null,a[0]||(a[0]=[i("",8)]))}const g=e(o,[["render",n]]);export{_ as __pageData,g as default}; diff --git a/assets/en_guide_docker_docker_android.md.BulF4nM1.js b/assets/en_guide_docker_docker_android.md.BulF4nM1.js new file mode 100644 index 0000000000..902e1d6072 --- /dev/null +++ b/assets/en_guide_docker_docker_android.md.BulF4nM1.js @@ -0,0 +1,6 @@ +import{_ as e,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Running Android Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_android.md","filePath":"en/guide/docker/docker_android.md","lastUpdated":1747984962000}'),t={name:"en/guide/docker/docker_android.md"};function r(o,i,l,h,d,p){return a(),s("div",null,i[0]||(i[0]=[n(`

Running Android Virtual Machine in Docker

One-Click Deployment

  • Customizable Android version
  • Automatically creates a validated web website
  • Automatically installs Nginx and configures reverse proxy. Option to bind a domain is available. Default is port 80 if no domain binding is chosen.
  • No need to worry about host machine supporting nested virtualization
  • Supports x86_64 and ARM architectures

Host machine should have a minimum configuration of 1 core, 2GB RAM, and 15GB storage, else starting the setup might lead to host machine freezing.

Ubuntu is recommended for hosting, Debian may cause white screen on Android.

Newer Android versions occupy more resources. The above configuration requirements are for the minimum version of Android. (Personally tested with the tag "12.0.0-latest", higher versions resulted in a blank screen. Test which version works for you.)

If, after 5 minutes after opening, the login verification of the browser page still keeps failing, then please check the logs of the Android container, it is probable that the Android container has crashed, and it is recommended to replace the container with a lower version of the Android system for installation.

Setup:

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

After executing the command, follow the prompts to input the required information. Make sure to choose the version by entering the corresponding number index. Once the installation is complete, open YourMachineIPv4+80Port to log in.

If you need to check the generated Android information and web login details, execute cat /root/android_info to retrieve the information.

Default username: onea Default password: oneclick

For remote desktop, click on H264 Converter to initiate the redirection.

Please note that currently only one Android container can be generated. Do not generate duplicates. If you need to replace the version, please execute the subsequent commands after deletion.

Temporarily only support the opening has been used, can not restart the server, reboot may not be able to restart after the mapping success, self-test

Deletion:

  • Delete the container
  • Delete the corresponding container image
  • Delete the configuration file
shell
docker rm -f android
+docker rmi $(docker images | grep "redroid" | awk '{print $3}')
+rm -rf /etc/nginx/sites-enabled/reverse-proxy
+rm -rf /etc/nginx/sites-available/reverse-proxy
+rm -rf /etc/nginx/passwd_scrcpy_web
+rm -rf /root/android_info
`,19)]))}const g=e(t,[["render",r]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_docker_docker_android.md.BulF4nM1.lean.js b/assets/en_guide_docker_docker_android.md.BulF4nM1.lean.js new file mode 100644 index 0000000000..b372236de5 --- /dev/null +++ b/assets/en_guide_docker_docker_android.md.BulF4nM1.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Running Android Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_android.md","filePath":"en/guide/docker/docker_android.md","lastUpdated":1747984962000}'),t={name:"en/guide/docker/docker_android.md"};function r(o,i,l,h,d,p){return a(),s("div",null,i[0]||(i[0]=[n("",19)]))}const g=e(t,[["render",r]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_docker_docker_android.md.ffbfb237.js b/assets/en_guide_docker_docker_android.md.ffbfb237.js deleted file mode 100644 index 630caf3522..0000000000 --- a/assets/en_guide_docker_docker_android.md.ffbfb237.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as e,v as n,b as s,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Running Android Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_android.md","filePath":"en/guide/docker/docker_android.md","lastUpdated":1747972048000}'),a={name:"en/guide/docker/docker_android.md"},t=o(`

Running Android Virtual Machine in Docker

One-Click Deployment

  • Customizable Android version
  • Automatically creates a validated web website
  • Automatically installs Nginx and configures reverse proxy. Option to bind a domain is available. Default is port 80 if no domain binding is chosen.
  • No need to worry about host machine supporting nested virtualization
  • Supports x86_64 and ARM architectures

Host machine should have a minimum configuration of 1 core, 2GB RAM, and 15GB storage, else starting the setup might lead to host machine freezing.

Ubuntu is recommended for hosting, Debian may cause white screen on Android.

Newer Android versions occupy more resources. The above configuration requirements are for the minimum version of Android. (Personally tested with the tag "12.0.0-latest", higher versions resulted in a blank screen. Test which version works for you.)

If, after 5 minutes after opening, the login verification of the browser page still keeps failing, then please check the logs of the Android container, it is probable that the Android container has crashed, and it is recommended to replace the container with a lower version of the Android system for installation.

Setup:

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

After executing the command, follow the prompts to input the required information. Make sure to choose the version by entering the corresponding number index. Once the installation is complete, open YourMachineIPv4+80Port to log in.

If you need to check the generated Android information and web login details, execute cat /root/android_info to retrieve the information.

Default username: onea Default password: oneclick

For remote desktop, click on H264 Converter to initiate the redirection.

Please note that currently only one Android container can be generated. Do not generate duplicates. If you need to replace the version, please execute the subsequent commands after deletion.

Temporarily only support the opening has been used, can not restart the server, reboot may not be able to restart after the mapping success, self-test

Deletion:

  • Delete the container
  • Delete the corresponding container image
  • Delete the configuration file
shell
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
`,19),r=[t];function l(p,i,c,d,y,C){return n(),s("div",null,r)}const D=e(a,[["render",l]]);export{u as __pageData,D as default}; diff --git a/assets/en_guide_docker_docker_android.md.ffbfb237.lean.js b/assets/en_guide_docker_docker_android.md.ffbfb237.lean.js deleted file mode 100644 index 630caf3522..0000000000 --- a/assets/en_guide_docker_docker_android.md.ffbfb237.lean.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as e,v as n,b as s,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Running Android Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_android.md","filePath":"en/guide/docker/docker_android.md","lastUpdated":1747972048000}'),a={name:"en/guide/docker/docker_android.md"},t=o(`

Running Android Virtual Machine in Docker

One-Click Deployment

  • Customizable Android version
  • Automatically creates a validated web website
  • Automatically installs Nginx and configures reverse proxy. Option to bind a domain is available. Default is port 80 if no domain binding is chosen.
  • No need to worry about host machine supporting nested virtualization
  • Supports x86_64 and ARM architectures

Host machine should have a minimum configuration of 1 core, 2GB RAM, and 15GB storage, else starting the setup might lead to host machine freezing.

Ubuntu is recommended for hosting, Debian may cause white screen on Android.

Newer Android versions occupy more resources. The above configuration requirements are for the minimum version of Android. (Personally tested with the tag "12.0.0-latest", higher versions resulted in a blank screen. Test which version works for you.)

If, after 5 minutes after opening, the login verification of the browser page still keeps failing, then please check the logs of the Android container, it is probable that the Android container has crashed, and it is recommended to replace the container with a lower version of the Android system for installation.

Setup:

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

After executing the command, follow the prompts to input the required information. Make sure to choose the version by entering the corresponding number index. Once the installation is complete, open YourMachineIPv4+80Port to log in.

If you need to check the generated Android information and web login details, execute cat /root/android_info to retrieve the information.

Default username: onea Default password: oneclick

For remote desktop, click on H264 Converter to initiate the redirection.

Please note that currently only one Android container can be generated. Do not generate duplicates. If you need to replace the version, please execute the subsequent commands after deletion.

Temporarily only support the opening has been used, can not restart the server, reboot may not be able to restart after the mapping success, self-test

Deletion:

  • Delete the container
  • Delete the corresponding container image
  • Delete the configuration file
shell
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
`,19),r=[t];function l(p,i,c,d,y,C){return n(),s("div",null,r)}const D=e(a,[["render",l]]);export{u as __pageData,D as default}; diff --git a/assets/en_guide_docker_docker_build.md.5395d3b9.js b/assets/en_guide_docker_docker_build.md.5395d3b9.js deleted file mode 100644 index 89d2357f87..0000000000 --- a/assets/en_guide_docker_docker_build.md.5395d3b9.js +++ /dev/null @@ -1,24 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_build.md","filePath":"en/guide/docker/docker_build.md","lastUpdated":1747972048000}'),e={name:"en/guide/docker/docker_build.md"},l=o(`

Introduction

There are two methods of building

Setting Up Standalone

  • Generate only one docker
  • Can be configured to bind a separate IPV6 address, but requires a docker previously installed using the environment installation command of this set of scripts, and requires the host to be bound to at least the /112 IPV6 subnet
  • Support for x86_64 and ARM architecture servers

Download the Script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

Example

Run

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

Currently, the system only supports selecting:

  • alpine
  • debian
  • ubuntu
  • almalinux

with Debian being the default choice.

The following is the information for the created example container:

AttributeValue
Container Nametest
Username for SSH Loginroot
Password for SSH Login123456
Number of CPU Cores1
Memory Size512MB
SSH Port25000
Port Range for Internal and External Mapping34975 to 35000
Operating Systemdebian
Whether to bind a separate IPV6 addressN
shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

Deleting the test container

shell
docker rm -f test
-rm -rf test
-ls

Accessing the test container

shell
docker exec -it test /bin/bash

To exit the container, simply execute exit.

Inquiry Information

shell
cat Container_Name(change me)

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

The docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration

Batch Deployment

  • Run inheritance configuration generation multiple times in bulk.
  • When generating multiple instances, it is recommended to execute within a screen session to avoid SSH connection interruptions.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

Querying information on batch openings

shell
cat dclog

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

One line corresponds to information about a container, the docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration.

Uninstall all Docker containers and images

The following command offload ignores ndpresponder to prevent IPV6 configuration failure

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

Start all containers after host reboot

The default containers are not set to restart themselves after stopping, you need to execute the following command to start all stopped containers.

docker start $(docker ps -aq)

Start SSH service for all containers after host reboot

Since the container itself does not have a daemon, the SSH service cannot start itself, and you need to execute the following command to start the SSH process for all containers.

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
`,50),t=[l];function p(r,c,i,C,y,d){return a(),n("div",null,t)}const A=s(e,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_docker_docker_build.md.5395d3b9.lean.js b/assets/en_guide_docker_docker_build.md.5395d3b9.lean.js deleted file mode 100644 index 89d2357f87..0000000000 --- a/assets/en_guide_docker_docker_build.md.5395d3b9.lean.js +++ /dev/null @@ -1,24 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_build.md","filePath":"en/guide/docker/docker_build.md","lastUpdated":1747972048000}'),e={name:"en/guide/docker/docker_build.md"},l=o(`

Introduction

There are two methods of building

Setting Up Standalone

  • Generate only one docker
  • Can be configured to bind a separate IPV6 address, but requires a docker previously installed using the environment installation command of this set of scripts, and requires the host to be bound to at least the /112 IPV6 subnet
  • Support for x86_64 and ARM architecture servers

Download the Script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

Example

Run

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

Currently, the system only supports selecting:

  • alpine
  • debian
  • ubuntu
  • almalinux

with Debian being the default choice.

The following is the information for the created example container:

AttributeValue
Container Nametest
Username for SSH Loginroot
Password for SSH Login123456
Number of CPU Cores1
Memory Size512MB
SSH Port25000
Port Range for Internal and External Mapping34975 to 35000
Operating Systemdebian
Whether to bind a separate IPV6 addressN
shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

Deleting the test container

shell
docker rm -f test
-rm -rf test
-ls

Accessing the test container

shell
docker exec -it test /bin/bash

To exit the container, simply execute exit.

Inquiry Information

shell
cat Container_Name(change me)

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

The docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration

Batch Deployment

  • Run inheritance configuration generation multiple times in bulk.
  • When generating multiple instances, it is recommended to execute within a screen session to avoid SSH connection interruptions.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

Querying information on batch openings

shell
cat dclog

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

One line corresponds to information about a container, the docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration.

Uninstall all Docker containers and images

The following command offload ignores ndpresponder to prevent IPV6 configuration failure

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

Start all containers after host reboot

The default containers are not set to restart themselves after stopping, you need to execute the following command to start all stopped containers.

docker start $(docker ps -aq)

Start SSH service for all containers after host reboot

Since the container itself does not have a daemon, the SSH service cannot start itself, and you need to execute the following command to start the SSH process for all containers.

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
`,50),t=[l];function p(r,c,i,C,y,d){return a(),n("div",null,t)}const A=s(e,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_docker_docker_build.md.DvGO9A3O.js b/assets/en_guide_docker_docker_build.md.DvGO9A3O.js new file mode 100644 index 0000000000..4034e285a1 --- /dev/null +++ b/assets/en_guide_docker_docker_build.md.DvGO9A3O.js @@ -0,0 +1,24 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_build.md","filePath":"en/guide/docker/docker_build.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_build.md"};function h(l,s,p,r,o,k){return t(),a("div",null,s[0]||(s[0]=[e(`

Introduction

There are two methods of building

Setting Up Standalone

  • Generate only one docker
  • Can be configured to bind a separate IPV6 address, but requires a docker previously installed using the environment installation command of this set of scripts, and requires the host to be bound to at least the /112 IPV6 subnet
  • Support for x86_64 and ARM architecture servers

Download the Script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

Example

Run

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

Currently, the system only supports selecting:

  • alpine
  • debian
  • ubuntu
  • almalinux

with Debian being the default choice.

The following is the information for the created example container:

AttributeValue
Container Nametest
Username for SSH Loginroot
Password for SSH Login123456
Number of CPU Cores1
Memory Size512MB
SSH Port25000
Port Range for Internal and External Mapping34975 to 35000
Operating Systemdebian
Whether to bind a separate IPV6 addressN
shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

Deleting the test container

shell
docker rm -f test
+rm -rf test
+ls

Accessing the test container

shell
docker exec -it test /bin/bash

To exit the container, simply execute exit.

Inquiry Information

shell
cat Container_Name(change me)

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

The docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration

Batch Deployment

  • Run inheritance configuration generation multiple times in bulk.
  • When generating multiple instances, it is recommended to execute within a screen session to avoid SSH connection interruptions.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

Querying information on batch openings

shell
cat dclog

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

One line corresponds to information about a container, the docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration.

Uninstall all Docker containers and images

The following command offload ignores ndpresponder to prevent IPV6 configuration failure

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
+docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
+rm -rf dclog
+ls

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/onedocker.sh
+rm -rf /root/create_docker.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

Start all containers after host reboot

The default containers are not set to restart themselves after stopping, you need to execute the following command to start all stopped containers.

docker start $(docker ps -aq)

Start SSH service for all containers after host reboot

Since the container itself does not have a daemon, the SSH service cannot start itself, and you need to execute the following command to start the SSH process for all containers.

container_ids=$(docker ps -q)
+for container_id in $container_ids
+do
+    docker exec -it $container_id bash -c "service ssh start"
+    docker exec -it $container_id bash -c "service sshd restart"
+    docker exec -it $container_id sh -c "service ssh start"
+    docker exec -it $container_id sh -c "/usr/sbin/sshd"
+done
`,50)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_docker_docker_build.md.DvGO9A3O.lean.js b/assets/en_guide_docker_docker_build.md.DvGO9A3O.lean.js new file mode 100644 index 0000000000..e5dec46312 --- /dev/null +++ b/assets/en_guide_docker_docker_build.md.DvGO9A3O.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_build.md","filePath":"en/guide/docker/docker_build.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_build.md"};function h(l,s,p,r,o,k){return t(),a("div",null,s[0]||(s[0]=[e("",50)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_docker_docker_custom.md.4e05a2c3.js b/assets/en_guide_docker_docker_custom.md.4e05a2c3.js deleted file mode 100644 index 5a80fbb663..0000000000 --- a/assets/en_guide_docker_docker_custom.md.4e05a2c3.js +++ /dev/null @@ -1,10 +0,0 @@ -import{_ as s,v as o,b as e,R as a}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Script for One-Click Installation of Certain Containers using Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_custom.md","filePath":"en/guide/docker/docker_custom.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_custom.md"},l=a(`

Script for One-Click Installation of Certain Containers using Docker

Each container has specific configuration requirements; please refer to them individually.

If the configured memory is not enough, then it's okay to make up for it with the virtual memory here.

Note that the following scripts must be pre-installed using the environment installation scripts in this set of tutorials before using them

One-Click Setup of Firefox Browser Container

  • Crash recovery on startup has been configured.
  • Chinese fonts have been integrated into the container.
  • Built-in web validation with the option to set a custom password.
  • Maximum memory usage for the container is customizable.
  • Choice to enable VNC port, disabled by default.
  • No need to consider support for nested virtualization or server architecture.
  • Audio mapping is not supported; sound transmission is unavailable on both the web and VNC.

The host machine should have at least 1 core, 1GB RAM, and 5GB disk space. The created container will occupy a minimum of 1GB disk space.

Setup:

After setup, the default password is oneclick.

The default web port is 3003. Once the setup is complete, simply open HOST_IPV4:PORT in your browser.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

Deletion

Modify the following port number 3003 to your actual port number, and then execute the command to delete the container, configuration file, and corresponding image

shell
PORT="3003"
-docker stop firefox_\${PORT}
-docker rm -f firefox_\${PORT}
-rm -rf /usr/local/bin/firefox_\${PORT}
-docker rmi jlesage/firefox

One-Click Setup of Chrome Browser Container

  • Crashing self-start has been set
  • Web checksums and passwords can be set.
  • Customizable maximum container memory footprint
  • No need to consider whether to support nested virtualization and server architecture.
  • Supports sound mapping

Host requires at least 1 core, 2G RAM, and 10G hard disk, and the size of the container to be opened will take up a minimum of 1G hard disk

It is better to hang the execution in the screen during the first installation, to avoid long running SSH connection disconnection

Opening

If no custom username is set, the default username after opening is oneclick.

If no custom password is set, the default password after opening is oneclick.

The default http port is 3004, open http://IPV4:3004 after opening.

The default https port is 3005, open https://IPV4:3005 after opening.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

Delete

Change the following port number 3004 to your actual http port number, then execute the command enter twice to delete the container, configuration file, and corresponding image

shell
PORT="3004"
-docker stop chromium_\${PORT}
-docker rm -f chromium_\${PORT}
-rm -rf /usr/local/bin/config_\${PORT}
-rm -rf /usr/local/bin/password_\${PORT}
-docker rmi lscr.io/linuxserver/chromium

One-Click Setup of Desktop Container

  • Crashes automatically restart have been configured.
  • Chinese fonts are included in the setup.
  • Built-in web validation with the ability to set your own username and password.
  • Customizable maximum memory usage for the container.
  • No need to consider nested virtualization support and server architecture.
  • Sound mapping is supported, and sound can be transmitted via the web interface.

A complete Linux desktop on which you can use a browser

The host system requires at least 1 core, 2 GB of RAM, and 5 GB of hard disk space. The created container will occupy a minimum of 3.2 GB of hard disk space.

Setup Instructions:

After setup, the default username is onew and the password is oneclick. The default maximum memory usage is 2 GB.

The default web port for HTTP protocol is 3004, and for HTTPS protocol is 3005. After setup, open the corresponding protocol with localhost's IPV4:port in your web browser.

Run the following command to download and execute the setup script:

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

Deletion

Command:

shell
docker ps -a

Query for containers with a prefix of 'webtop' in their names, and record the IDs of these containers.

shell
docker rm -f container_ID

To remove the corresponding image, you can use the following command after deleting all associated containers:

shell
docker rmi lscr.io/linuxserver/webtop

One-Click Installation of Guacamole

A web-based tool for controlling servers using protocols like SSH or RDP.

Website: http://your_IPV4_address:80/guacamole

Default Username: guacadmin

Default Password: guacadmin

After installation, remember to change the password upon login.

The host machine should have at least 1 core, 2GB RAM, and 10GB of disk space; otherwise, launching might lead to host machine freezing!

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh
`,52),t=[l];function p(r,c,i,C,d,h){return o(),e("div",null,t)}const m=s(n,[["render",p]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_docker_docker_custom.md.4e05a2c3.lean.js b/assets/en_guide_docker_docker_custom.md.4e05a2c3.lean.js deleted file mode 100644 index 5a80fbb663..0000000000 --- a/assets/en_guide_docker_docker_custom.md.4e05a2c3.lean.js +++ /dev/null @@ -1,10 +0,0 @@ -import{_ as s,v as o,b as e,R as a}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Script for One-Click Installation of Certain Containers using Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_custom.md","filePath":"en/guide/docker/docker_custom.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_custom.md"},l=a(`

Script for One-Click Installation of Certain Containers using Docker

Each container has specific configuration requirements; please refer to them individually.

If the configured memory is not enough, then it's okay to make up for it with the virtual memory here.

Note that the following scripts must be pre-installed using the environment installation scripts in this set of tutorials before using them

One-Click Setup of Firefox Browser Container

  • Crash recovery on startup has been configured.
  • Chinese fonts have been integrated into the container.
  • Built-in web validation with the option to set a custom password.
  • Maximum memory usage for the container is customizable.
  • Choice to enable VNC port, disabled by default.
  • No need to consider support for nested virtualization or server architecture.
  • Audio mapping is not supported; sound transmission is unavailable on both the web and VNC.

The host machine should have at least 1 core, 1GB RAM, and 5GB disk space. The created container will occupy a minimum of 1GB disk space.

Setup:

After setup, the default password is oneclick.

The default web port is 3003. Once the setup is complete, simply open HOST_IPV4:PORT in your browser.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

Deletion

Modify the following port number 3003 to your actual port number, and then execute the command to delete the container, configuration file, and corresponding image

shell
PORT="3003"
-docker stop firefox_\${PORT}
-docker rm -f firefox_\${PORT}
-rm -rf /usr/local/bin/firefox_\${PORT}
-docker rmi jlesage/firefox

One-Click Setup of Chrome Browser Container

  • Crashing self-start has been set
  • Web checksums and passwords can be set.
  • Customizable maximum container memory footprint
  • No need to consider whether to support nested virtualization and server architecture.
  • Supports sound mapping

Host requires at least 1 core, 2G RAM, and 10G hard disk, and the size of the container to be opened will take up a minimum of 1G hard disk

It is better to hang the execution in the screen during the first installation, to avoid long running SSH connection disconnection

Opening

If no custom username is set, the default username after opening is oneclick.

If no custom password is set, the default password after opening is oneclick.

The default http port is 3004, open http://IPV4:3004 after opening.

The default https port is 3005, open https://IPV4:3005 after opening.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

Delete

Change the following port number 3004 to your actual http port number, then execute the command enter twice to delete the container, configuration file, and corresponding image

shell
PORT="3004"
-docker stop chromium_\${PORT}
-docker rm -f chromium_\${PORT}
-rm -rf /usr/local/bin/config_\${PORT}
-rm -rf /usr/local/bin/password_\${PORT}
-docker rmi lscr.io/linuxserver/chromium

One-Click Setup of Desktop Container

  • Crashes automatically restart have been configured.
  • Chinese fonts are included in the setup.
  • Built-in web validation with the ability to set your own username and password.
  • Customizable maximum memory usage for the container.
  • No need to consider nested virtualization support and server architecture.
  • Sound mapping is supported, and sound can be transmitted via the web interface.

A complete Linux desktop on which you can use a browser

The host system requires at least 1 core, 2 GB of RAM, and 5 GB of hard disk space. The created container will occupy a minimum of 3.2 GB of hard disk space.

Setup Instructions:

After setup, the default username is onew and the password is oneclick. The default maximum memory usage is 2 GB.

The default web port for HTTP protocol is 3004, and for HTTPS protocol is 3005. After setup, open the corresponding protocol with localhost's IPV4:port in your web browser.

Run the following command to download and execute the setup script:

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

Deletion

Command:

shell
docker ps -a

Query for containers with a prefix of 'webtop' in their names, and record the IDs of these containers.

shell
docker rm -f container_ID

To remove the corresponding image, you can use the following command after deleting all associated containers:

shell
docker rmi lscr.io/linuxserver/webtop

One-Click Installation of Guacamole

A web-based tool for controlling servers using protocols like SSH or RDP.

Website: http://your_IPV4_address:80/guacamole

Default Username: guacadmin

Default Password: guacadmin

After installation, remember to change the password upon login.

The host machine should have at least 1 core, 2GB RAM, and 10GB of disk space; otherwise, launching might lead to host machine freezing!

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh
`,52),t=[l];function p(r,c,i,C,d,h){return o(),e("div",null,t)}const m=s(n,[["render",p]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_docker_docker_custom.md.CoAvHe_n.js b/assets/en_guide_docker_docker_custom.md.CoAvHe_n.js new file mode 100644 index 0000000000..acc659ad50 --- /dev/null +++ b/assets/en_guide_docker_docker_custom.md.CoAvHe_n.js @@ -0,0 +1,10 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Script for One-Click Installation of Certain Containers using Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_custom.md","filePath":"en/guide/docker/docker_custom.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_custom.md"};function o(l,s,h,p,r,c){return a(),e("div",null,s[0]||(s[0]=[t(`

Script for One-Click Installation of Certain Containers using Docker

Each container has specific configuration requirements; please refer to them individually.

If the configured memory is not enough, then it's okay to make up for it with the virtual memory here.

Note that the following scripts must be pre-installed using the environment installation scripts in this set of tutorials before using them

One-Click Setup of Firefox Browser Container

  • Crash recovery on startup has been configured.
  • Chinese fonts have been integrated into the container.
  • Built-in web validation with the option to set a custom password.
  • Maximum memory usage for the container is customizable.
  • Choice to enable VNC port, disabled by default.
  • No need to consider support for nested virtualization or server architecture.
  • Audio mapping is not supported; sound transmission is unavailable on both the web and VNC.

The host machine should have at least 1 core, 1GB RAM, and 5GB disk space. The created container will occupy a minimum of 1GB disk space.

Setup:

After setup, the default password is oneclick.

The default web port is 3003. Once the setup is complete, simply open HOST_IPV4:PORT in your browser.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

Deletion

Modify the following port number 3003 to your actual port number, and then execute the command to delete the container, configuration file, and corresponding image

shell
PORT="3003"
+docker stop firefox_\${PORT}
+docker rm -f firefox_\${PORT}
+rm -rf /usr/local/bin/firefox_\${PORT}
+docker rmi jlesage/firefox

One-Click Setup of Chrome Browser Container

  • Crashing self-start has been set
  • Web checksums and passwords can be set.
  • Customizable maximum container memory footprint
  • No need to consider whether to support nested virtualization and server architecture.
  • Supports sound mapping

Host requires at least 1 core, 2G RAM, and 10G hard disk, and the size of the container to be opened will take up a minimum of 1G hard disk

It is better to hang the execution in the screen during the first installation, to avoid long running SSH connection disconnection

Opening

If no custom username is set, the default username after opening is oneclick.

If no custom password is set, the default password after opening is oneclick.

The default http port is 3004, open http://IPV4:3004 after opening.

The default https port is 3005, open https://IPV4:3005 after opening.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

Delete

Change the following port number 3004 to your actual http port number, then execute the command enter twice to delete the container, configuration file, and corresponding image

shell
PORT="3004"
+docker stop chromium_\${PORT}
+docker rm -f chromium_\${PORT}
+rm -rf /usr/local/bin/config_\${PORT}
+rm -rf /usr/local/bin/password_\${PORT}
+docker rmi lscr.io/linuxserver/chromium

One-Click Setup of Desktop Container

  • Crashes automatically restart have been configured.
  • Chinese fonts are included in the setup.
  • Built-in web validation with the ability to set your own username and password.
  • Customizable maximum memory usage for the container.
  • No need to consider nested virtualization support and server architecture.
  • Sound mapping is supported, and sound can be transmitted via the web interface.

A complete Linux desktop on which you can use a browser

The host system requires at least 1 core, 2 GB of RAM, and 5 GB of hard disk space. The created container will occupy a minimum of 3.2 GB of hard disk space.

Setup Instructions:

After setup, the default username is onew and the password is oneclick. The default maximum memory usage is 2 GB.

The default web port for HTTP protocol is 3004, and for HTTPS protocol is 3005. After setup, open the corresponding protocol with localhost's IPV4:port in your web browser.

Run the following command to download and execute the setup script:

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

Deletion

Command:

shell
docker ps -a

Query for containers with a prefix of 'webtop' in their names, and record the IDs of these containers.

shell
docker rm -f container_ID

To remove the corresponding image, you can use the following command after deleting all associated containers:

shell
docker rmi lscr.io/linuxserver/webtop

One-Click Installation of Guacamole

A web-based tool for controlling servers using protocols like SSH or RDP.

Website: http://your_IPV4_address:80/guacamole

Default Username: guacadmin

Default Password: guacadmin

After installation, remember to change the password upon login.

The host machine should have at least 1 core, 2GB RAM, and 10GB of disk space; otherwise, launching might lead to host machine freezing!

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh
`,52)]))}const u=i(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_custom.md.CoAvHe_n.lean.js b/assets/en_guide_docker_docker_custom.md.CoAvHe_n.lean.js new file mode 100644 index 0000000000..4318fd8ce1 --- /dev/null +++ b/assets/en_guide_docker_docker_custom.md.CoAvHe_n.lean.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Script for One-Click Installation of Certain Containers using Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_custom.md","filePath":"en/guide/docker/docker_custom.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_custom.md"};function o(l,s,h,p,r,c){return a(),e("div",null,s[0]||(s[0]=[t("",52)]))}const u=i(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_install.md.2b0bb4e4.js b/assets/en_guide_docker_docker_install.md.2b0bb4e4.js deleted file mode 100644 index 766d47f23f..0000000000 --- a/assets/en_guide_docker_docker_install.md.2b0bb4e4.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as e,R as o}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_install.md","filePath":"en/guide/docker/docker_install.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_install.md"},t=o('

Preface

Support for running Docker virtualization on various systems, including Linux, Android, and Windows.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Setting Up Virtual Memory

TIP

Allocate some swap space to prevent your machine from crashing.

Unit conversion: Inputting 1024 results in 1G of SWAP - virtual memory. Virtual memory occupies disk space and is automatically utilized when the physical memory is insufficient. However, this leads to high IO usage and CPU performance overhead.

It is recommended to allocate virtual memory twice the size of your physical memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Environment Setup

  • Detect the system environment and install the corresponding components
  • Install docker and docker-compose.
  • Download some configuration scripts required by default
  • Detect if there is an IPV6 address, check if it is greater than or equal to /112, and if so, configure the docker's ipv6 network.
  • If all the above conditions are met, create ndpresponder docker and radvd so that IPV6 allocation supports ndp broadcasting and auto-allocation.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

OR

bash dockerinstall.sh

TIP

The environment installation process may require you to reboot the server and then execute the script again, see the instructions after the script is run for more details

',16),l=[t];function p(r,c,i,d,h,u){return a(),e("div",null,l)}const y=s(n,[["render",p]]);export{C as __pageData,y as default}; diff --git a/assets/en_guide_docker_docker_install.md.2b0bb4e4.lean.js b/assets/en_guide_docker_docker_install.md.2b0bb4e4.lean.js deleted file mode 100644 index 766d47f23f..0000000000 --- a/assets/en_guide_docker_docker_install.md.2b0bb4e4.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as e,R as o}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_install.md","filePath":"en/guide/docker/docker_install.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_install.md"},t=o('

Preface

Support for running Docker virtualization on various systems, including Linux, Android, and Windows.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Setting Up Virtual Memory

TIP

Allocate some swap space to prevent your machine from crashing.

Unit conversion: Inputting 1024 results in 1G of SWAP - virtual memory. Virtual memory occupies disk space and is automatically utilized when the physical memory is insufficient. However, this leads to high IO usage and CPU performance overhead.

It is recommended to allocate virtual memory twice the size of your physical memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Environment Setup

  • Detect the system environment and install the corresponding components
  • Install docker and docker-compose.
  • Download some configuration scripts required by default
  • Detect if there is an IPV6 address, check if it is greater than or equal to /112, and if so, configure the docker's ipv6 network.
  • If all the above conditions are met, create ndpresponder docker and radvd so that IPV6 allocation supports ndp broadcasting and auto-allocation.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

OR

bash dockerinstall.sh

TIP

The environment installation process may require you to reboot the server and then execute the script again, see the instructions after the script is run for more details

',16),l=[t];function p(r,c,i,d,h,u){return a(),e("div",null,l)}const y=s(n,[["render",p]]);export{C as __pageData,y as default}; diff --git a/assets/en_guide_docker_docker_install.md.DMUsaTt3.js b/assets/en_guide_docker_docker_install.md.DMUsaTt3.js new file mode 100644 index 0000000000..d56670125b --- /dev/null +++ b/assets/en_guide_docker_docker_install.md.DMUsaTt3.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_install.md","filePath":"en/guide/docker/docker_install.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_install.md"};function o(l,s,r,p,h,d){return a(),e("div",null,s[0]||(s[0]=[t('

Preface

Support for running Docker virtualization on various systems, including Linux, Android, and Windows.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Setting Up Virtual Memory

TIP

Allocate some swap space to prevent your machine from crashing.

Unit conversion: Inputting 1024 results in 1G of SWAP - virtual memory. Virtual memory occupies disk space and is automatically utilized when the physical memory is insufficient. However, this leads to high IO usage and CPU performance overhead.

It is recommended to allocate virtual memory twice the size of your physical memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Environment Setup

  • Detect the system environment and install the corresponding components
  • Install docker and docker-compose.
  • Download some configuration scripts required by default
  • Detect if there is an IPV6 address, check if it is greater than or equal to /112, and if so, configure the docker's ipv6 network.
  • If all the above conditions are met, create ndpresponder docker and radvd so that IPV6 allocation supports ndp broadcasting and auto-allocation.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

OR

bash dockerinstall.sh

TIP

The environment installation process may require you to reboot the server and then execute the script again, see the instructions after the script is run for more details

',16)]))}const u=i(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_install.md.DMUsaTt3.lean.js b/assets/en_guide_docker_docker_install.md.DMUsaTt3.lean.js new file mode 100644 index 0000000000..ea6ed8c209 --- /dev/null +++ b/assets/en_guide_docker_docker_install.md.DMUsaTt3.lean.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_install.md","filePath":"en/guide/docker/docker_install.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_install.md"};function o(l,s,r,p,h,d){return a(),e("div",null,s[0]||(s[0]=[t("",16)]))}const u=i(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_macos.md.48b99172.js b/assets/en_guide_docker_docker_macos.md.48b99172.js deleted file mode 100644 index f4e5a41603..0000000000 --- a/assets/en_guide_docker_docker_macos.md.48b99172.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as r,R as o}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"Running macOS Virtual Machines in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_macos.md","filePath":"en/guide/docker/docker_macos.md","lastUpdated":1747972048000}'),c={name:"en/guide/docker/docker_macos.md"},n=o('

Running macOS Virtual Machines in Docker

Using Dockur

Original Project:

https://github.com/dockur/macos

Using Docker-OSX

Original Project:

https://github.com/sickcodes/Docker-OSX

',7),i=[n];function t(s,d,u,h,k,l){return a(),r("div",null,i)}const p=e(c,[["render",t]]);export{g as __pageData,p as default}; diff --git a/assets/en_guide_docker_docker_macos.md.48b99172.lean.js b/assets/en_guide_docker_docker_macos.md.48b99172.lean.js deleted file mode 100644 index f4e5a41603..0000000000 --- a/assets/en_guide_docker_docker_macos.md.48b99172.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as r,R as o}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"Running macOS Virtual Machines in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_macos.md","filePath":"en/guide/docker/docker_macos.md","lastUpdated":1747972048000}'),c={name:"en/guide/docker/docker_macos.md"},n=o('

Running macOS Virtual Machines in Docker

Using Dockur

Original Project:

https://github.com/dockur/macos

Using Docker-OSX

Original Project:

https://github.com/sickcodes/Docker-OSX

',7),i=[n];function t(s,d,u,h,k,l){return a(),r("div",null,i)}const p=e(c,[["render",t]]);export{g as __pageData,p as default}; diff --git a/assets/en_guide_docker_docker_macos.md.DItPel8U.js b/assets/en_guide_docker_docker_macos.md.DItPel8U.js new file mode 100644 index 0000000000..58f5b8de58 --- /dev/null +++ b/assets/en_guide_docker_docker_macos.md.DItPel8U.js @@ -0,0 +1 @@ +import{_ as a,c as r,o,ag as c}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"Running macOS Virtual Machines in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_macos.md","filePath":"en/guide/docker/docker_macos.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_macos.md"};function t(i,e,s,d,u,l){return o(),r("div",null,e[0]||(e[0]=[c('

Running macOS Virtual Machines in Docker

Using Dockur

Original Project:

https://github.com/dockur/macos

Using Docker-OSX

Original Project:

https://github.com/sickcodes/Docker-OSX

',7)]))}const m=a(n,[["render",t]]);export{h as __pageData,m as default}; diff --git a/assets/en_guide_docker_docker_macos.md.DItPel8U.lean.js b/assets/en_guide_docker_docker_macos.md.DItPel8U.lean.js new file mode 100644 index 0000000000..7ef5432185 --- /dev/null +++ b/assets/en_guide_docker_docker_macos.md.DItPel8U.lean.js @@ -0,0 +1 @@ +import{_ as a,c as r,o,ag as c}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"Running macOS Virtual Machines in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_macos.md","filePath":"en/guide/docker/docker_macos.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_macos.md"};function t(i,e,s,d,u,l){return o(),r("div",null,e[0]||(e[0]=[c("",7)]))}const m=a(n,[["render",t]]);export{h as __pageData,m as default}; diff --git a/assets/en_guide_docker_docker_precheck.md.BrsWou7M.js b/assets/en_guide_docker_docker_precheck.md.BrsWou7M.js new file mode 100644 index 0000000000..a5275dc725 --- /dev/null +++ b/assets/en_guide_docker_docker_precheck.md.BrsWou7M.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const p=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_precheck.md","filePath":"en/guide/docker/docker_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/docker/docker_precheck.md"};function s(i,e,c,d,h,u){return a(),o("div",null,e[0]||(e[0]=[n('

Introduction

The following is an introduction to the non-customized sections. Please ensure that you don't confuse them with the customized parts.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

WARNING

If the host has an IPV6 network, the installation will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/docker

Project Features

Bulk or individual NAT server provisioning via docker

Default use of debian system optional alpine system, each container comes with 1 external ssh port, 25 internal and external network ports, you can choose whether to bind IPV6 address

The default creation of unprivileged containers, and does not mount and host docker daemon communication, so ** host created docker virtualization NAT servers can not be nested within the virtualization docker **

By default, lxcfs is installed and enabled, so that when querying resources within a container, CPU and memory use the configured view instead of the host's view.

Since most cloud servers have ext4 filesystems, even xfs filesystems do not enable the pquota option, so sharing the host's hard disk by default does not limit the disk size of each container.

Configuration requirements

The system can be installed docker can be used, the network can connect to the Github raw interface can be used, hardware configuration as long as not pull across the line, free hard disk has 3G on it!

(If you need to bind an IPV6 address, then please make sure to use the installation script of this set of scripts for docker installation, you need it to automatically preset some of the settings)

If the hardware resources are just a little bit better, need to limit more things and need to limit the size of the hard disk, you can use the incus partition of the script batch open LXC virtualization containers

If the hardware is very good and you have a lot of resources, you can use the PVE partition script to batch open KVM virtualized VMs.

',16)]))}const f=t(r,[["render",s]]);export{p as __pageData,f as default}; diff --git a/assets/en_guide_docker_docker_precheck.md.BrsWou7M.lean.js b/assets/en_guide_docker_docker_precheck.md.BrsWou7M.lean.js new file mode 100644 index 0000000000..3205407f29 --- /dev/null +++ b/assets/en_guide_docker_docker_precheck.md.BrsWou7M.lean.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const p=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_precheck.md","filePath":"en/guide/docker/docker_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/docker/docker_precheck.md"};function s(i,e,c,d,h,u){return a(),o("div",null,e[0]||(e[0]=[n("",16)]))}const f=t(r,[["render",s]]);export{p as __pageData,f as default}; diff --git a/assets/en_guide_docker_docker_precheck.md.a9b1c276.js b/assets/en_guide_docker_docker_precheck.md.a9b1c276.js deleted file mode 100644 index aac15598fa..0000000000 --- a/assets/en_guide_docker_docker_precheck.md.a9b1c276.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_precheck.md","filePath":"en/guide/docker/docker_precheck.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_precheck.md"},s=a('

Introduction

The following is an introduction to the non-customized sections. Please ensure that you don't confuse them with the customized parts.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

WARNING

If the host has an IPV6 network, the installation will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/docker

Project Features

Bulk or individual NAT server provisioning via docker

Default use of debian system optional alpine system, each container comes with 1 external ssh port, 25 internal and external network ports, you can choose whether to bind IPV6 address

The default creation of unprivileged containers, and does not mount and host docker daemon communication, so ** host created docker virtualization NAT servers can not be nested within the virtualization docker **

By default, lxcfs is installed and enabled, so that when querying resources within a container, CPU and memory use the configured view instead of the host's view.

Since most cloud servers have ext4 filesystems, even xfs filesystems do not enable the pquota option, so sharing the host's hard disk by default does not limit the disk size of each container.

Configuration requirements

The system can be installed docker can be used, the network can connect to the Github raw interface can be used, hardware configuration as long as not pull across the line, free hard disk has 3G on it!

(If you need to bind an IPV6 address, then please make sure to use the installation script of this set of scripts for docker installation, you need it to automatically preset some of the settings)

If the hardware resources are just a little bit better, need to limit more things and need to limit the size of the hard disk, you can use the incus partition of the script batch open LXC virtualization containers

If the hardware is very good and you have a lot of resources, you can use the PVE partition script to batch open KVM virtualized VMs.

',16),r=[s];function i(c,d,h,u,l,p){return t(),o("div",null,r)}const k=e(n,[["render",i]]);export{m as __pageData,k as default}; diff --git a/assets/en_guide_docker_docker_precheck.md.a9b1c276.lean.js b/assets/en_guide_docker_docker_precheck.md.a9b1c276.lean.js deleted file mode 100644 index aac15598fa..0000000000 --- a/assets/en_guide_docker_docker_precheck.md.a9b1c276.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_precheck.md","filePath":"en/guide/docker/docker_precheck.md","lastUpdated":1747972048000}'),n={name:"en/guide/docker/docker_precheck.md"},s=a('

Introduction

The following is an introduction to the non-customized sections. Please ensure that you don't confuse them with the customized parts.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

WARNING

If the host has an IPV6 network, the installation will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/docker

Project Features

Bulk or individual NAT server provisioning via docker

Default use of debian system optional alpine system, each container comes with 1 external ssh port, 25 internal and external network ports, you can choose whether to bind IPV6 address

The default creation of unprivileged containers, and does not mount and host docker daemon communication, so ** host created docker virtualization NAT servers can not be nested within the virtualization docker **

By default, lxcfs is installed and enabled, so that when querying resources within a container, CPU and memory use the configured view instead of the host's view.

Since most cloud servers have ext4 filesystems, even xfs filesystems do not enable the pquota option, so sharing the host's hard disk by default does not limit the disk size of each container.

Configuration requirements

The system can be installed docker can be used, the network can connect to the Github raw interface can be used, hardware configuration as long as not pull across the line, free hard disk has 3G on it!

(If you need to bind an IPV6 address, then please make sure to use the installation script of this set of scripts for docker installation, you need it to automatically preset some of the settings)

If the hardware resources are just a little bit better, need to limit more things and need to limit the size of the hard disk, you can use the incus partition of the script batch open LXC virtualization containers

If the hardware is very good and you have a lot of resources, you can use the PVE partition script to batch open KVM virtualized VMs.

',16),r=[s];function i(c,d,h,u,l,p){return t(),o("div",null,r)}const k=e(n,[["render",i]]);export{m as __pageData,k as default}; diff --git a/assets/en_guide_docker_docker_qa.md.fed2a991.js b/assets/en_guide_docker_docker_qa.md.fed2a991.js deleted file mode 100644 index 0b73957db1..0000000000 --- a/assets/en_guide_docker_docker_qa.md.fed2a991.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as s,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_qa.md","filePath":"en/guide/docker/docker_qa.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_qa.md"},l=n('

Solve the puzzle

Common Docker Commands

Check real-time resource usage of a specific container

docker stats <container_name>

Enter a specific container

docker exec -it <container_name> /bin/bash

Clean Docker cache, remove unused resources including images, containers, networks, etc.

docker system prune -a

Uninstall all Docker images and containers

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

View logs of a specific container

docker logs <container_name_or_ID>

View overall disk usage of Docker

docker system df

List all containers

docker ps -a

List all images

docker images

Remove a specific container

docker rm -f <container_name_or_ID>

Remove a specific image

docker rmi <image_name_or_ID>
',22),t=[l];function c(p,i,r,d,m,g){return a(),s("div",null,t)}const C=e(o,[["render",c]]);export{h as __pageData,C as default}; diff --git a/assets/en_guide_docker_docker_qa.md.fed2a991.lean.js b/assets/en_guide_docker_docker_qa.md.fed2a991.lean.js deleted file mode 100644 index 0b73957db1..0000000000 --- a/assets/en_guide_docker_docker_qa.md.fed2a991.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as s,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_qa.md","filePath":"en/guide/docker/docker_qa.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_qa.md"},l=n('

Solve the puzzle

Common Docker Commands

Check real-time resource usage of a specific container

docker stats <container_name>

Enter a specific container

docker exec -it <container_name> /bin/bash

Clean Docker cache, remove unused resources including images, containers, networks, etc.

docker system prune -a

Uninstall all Docker images and containers

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

View logs of a specific container

docker logs <container_name_or_ID>

View overall disk usage of Docker

docker system df

List all containers

docker ps -a

List all images

docker images

Remove a specific container

docker rm -f <container_name_or_ID>

Remove a specific image

docker rmi <image_name_or_ID>
',22),t=[l];function c(p,i,r,d,m,g){return a(),s("div",null,t)}const C=e(o,[["render",c]]);export{h as __pageData,C as default}; diff --git a/assets/en_guide_docker_docker_qa.md.q3nJoH_p.js b/assets/en_guide_docker_docker_qa.md.q3nJoH_p.js new file mode 100644 index 0000000000..ecdba08f95 --- /dev/null +++ b/assets/en_guide_docker_docker_qa.md.q3nJoH_p.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_qa.md","filePath":"en/guide/docker/docker_qa.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_qa.md"};function o(p,e,c,l,d,r){return t(),s("div",null,e[0]||(e[0]=[i('

Solve the puzzle

Common Docker Commands

Check real-time resource usage of a specific container

docker stats <container_name>

Enter a specific container

docker exec -it <container_name> /bin/bash

Clean Docker cache, remove unused resources including images, containers, networks, etc.

docker system prune -a

Uninstall all Docker images and containers

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

View logs of a specific container

docker logs <container_name_or_ID>

View overall disk usage of Docker

docker system df

List all containers

docker ps -a

List all images

docker images

Remove a specific container

docker rm -f <container_name_or_ID>

Remove a specific image

docker rmi <image_name_or_ID>
',22)]))}const u=a(n,[["render",o]]);export{g as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_qa.md.q3nJoH_p.lean.js b/assets/en_guide_docker_docker_qa.md.q3nJoH_p.lean.js new file mode 100644 index 0000000000..1396e0675c --- /dev/null +++ b/assets/en_guide_docker_docker_qa.md.q3nJoH_p.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_qa.md","filePath":"en/guide/docker/docker_qa.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_qa.md"};function o(p,e,c,l,d,r){return t(),s("div",null,e[0]||(e[0]=[i("",22)]))}const u=a(n,[["render",o]]);export{g as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.js b/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.js new file mode 100644 index 0000000000..1c6677c3de --- /dev/null +++ b/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_thanks.md","filePath":"en/guide/docker/docker_thanks.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_thanks.md"};function c(p,r,h,i,s,l){return a(),t("div",null,r[0]||(r[0]=[o('

Acknowledgements

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda and @CoiaPrant for providing docker guidance.

',20)]))}const u=e(n,[["render",c]]);export{d as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.lean.js b/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.lean.js new file mode 100644 index 0000000000..0bfa6d2fcd --- /dev/null +++ b/assets/en_guide_docker_docker_thanks.md.CLSD9Nhw.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_thanks.md","filePath":"en/guide/docker/docker_thanks.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_thanks.md"};function c(p,r,h,i,s,l){return a(),t("div",null,r[0]||(r[0]=[o("",20)]))}const u=e(n,[["render",c]]);export{d as __pageData,u as default}; diff --git a/assets/en_guide_docker_docker_thanks.md.d7efa635.js b/assets/en_guide_docker_docker_thanks.md.d7efa635.js deleted file mode 100644 index 3000e15861..0000000000 --- a/assets/en_guide_docker_docker_thanks.md.d7efa635.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_thanks.md","filePath":"en/guide/docker/docker_thanks.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_thanks.md"},n=a('

Acknowledgements

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda and @CoiaPrant for providing docker guidance.

',20),c=[n];function h(p,i,s,l,d,g){return e(),t("div",null,c)}const b=r(o,[["render",h]]);export{m as __pageData,b as default}; diff --git a/assets/en_guide_docker_docker_thanks.md.d7efa635.lean.js b/assets/en_guide_docker_docker_thanks.md.d7efa635.lean.js deleted file mode 100644 index 3000e15861..0000000000 --- a/assets/en_guide_docker_docker_thanks.md.d7efa635.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/docker/docker_thanks.md","filePath":"en/guide/docker/docker_thanks.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_thanks.md"},n=a('

Acknowledgements

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda and @CoiaPrant for providing docker guidance.

',20),c=[n];function h(p,i,s,l,d,g){return e(),t("div",null,c)}const b=r(o,[["render",h]]);export{m as __pageData,b as default}; diff --git a/assets/en_guide_docker_docker_windows.md.CDb3Bppx.js b/assets/en_guide_docker_docker_windows.md.CDb3Bppx.js new file mode 100644 index 0000000000..6c78097874 --- /dev/null +++ b/assets/en_guide_docker_docker_windows.md.CDb3Bppx.js @@ -0,0 +1,26 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Running Windows Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_windows.md","filePath":"en/guide/docker/docker_windows.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_windows.md"};function o(r,s,l,h,p,d){return a(),e("div",null,s[0]||(s[0]=[t(`

Running Windows Virtual Machine in Docker

One-Click Deployment (Using Vagrant)

  • Shares all resources of the host machine; based on Docker, so it only occupies the size of the system, suitable for multiple instances.
  • Shares IP; Docker's NAT mapping is employed. You can choose whether to map to the external network or just the internal network.
  • The configured Windows system is set to use a maximum of 1 core, 2GB RAM, and 50GB hard disk by default. Actual usage may vary based on usage patterns.
  • No need for iptables for NAT mapping; port mappings are automatically deleted when containers are removed, making maintenance easier.
  • Ensure that the host machine supports nested virtualization, and currently, only X86_64 architecture systems are supported. I haven't compiled corresponding images for ARM devices at the moment.

The host machine needs to support nested virtualization and currently only supports systems based on the X86_64 architecture; I don't have an ARM machine on hand to compile the corresponding image at the moment.

Command:

shell
egrep -c '(vmx|svm)' /proc/cpuinfo

The result should be greater than or equal to 1 and cannot be 0.

Next, you need to configure Docker to start using the v1 version of cgroup.

shell
sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
+update-grub
+ls

If there are no errors during execution, run the reboot command to restart the system and apply the settings.

Supported Images

We are using custom-built images: https://hub.docker.com/r/spiritlhl/wds

Image NameImage Size
1020GB
202217.5GB
201917GB

The size of the created container will be slightly larger than the image size, but not by much.

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

Usage Instructions

Make sure to execute the following commands in a 'screen' session before proceeding, to avoid potential disconnection or freezing of the SSH connection.

./onewindows.sh <container_name> <system_version> <RDP_port> <external_mapping>
  • Replace <container_name> with the name.
  • Replace <system_version> with the desired Windows system version.
  • Replace <RDP_port> with the port number for RDP access.
  • If you want to enable external mapping, replace <external_mapping> with 'Y'. If not, leave it blank or use 'N'.

Before initiating the setup, ensure that the host machine has a disk size at least twice the size of the image, plus an additional 10GB, as Docker needs to pull the image locally before creating the container.

During the creation process, the peak disk usage will be host_system_size + image_size + container_size.

For example, to set up a container with the name test, the container with the lowest occupancy Windows 2019 system, map the extranet RDP port 13389 and set it to extranet mapping (mapping to your server's extranet IPV4 address)

shell
./onewindows.sh test 2019 13389 Y

After it, the default usernames are Administrator and vagrant, with the default password being vagrant.

If you choose to open a mapped extranet port, be sure to log in and change the password of the corresponding account (both accounts may have, try it yourself), otherwise it may be abused by someone blasting

Deletion

To delete the corresponding image and container, first use the command docker ps -a and docker images to find the ID of the image named spiritlhl/wds. Then, use the following commands accordingly:

docker rm -f container_ID
+docker rmi image_ID

After deletion, you can create containers of different versions of Windows.

Other similar projects

https://github.com/dockur/windows - Similar project that support more systems, but have more resource requirements

https://github.com/dockur/windows-arm/ - It's great that he has ARM servers for mirror compilation, my project doesn't have

Note that both of the above projects require a host with at least 4 cores of CPU, at least 4G of RAM, and at least 64G of hard disk, which is greater than the mirroring requirements of my project. (The advantage of his project is that you can customize many configuration items, see his corresponding project description for details.)

Manual Provisioning (via the Dockur Project)

This project supports VM creation using QEMU even on host systems that do not support nested virtualization.

Original Project Repositories

⚠️ Notes:

  • The original project provides only the launcher, not a Windows image.

  • The first container startup may take up to 4 hours on domestic (China) networks, due to image download and installation.

  • The host system should meet the following minimum hardware requirements (can be adjusted via script modifications):

    • CPU: At least 4 cores
    • RAM: At least 4 GB
    • Disk: At least 64 GB

For customization such as reducing resource usage or changing launch parameters, refer to:

For x86_64 Architecture Users

A pre-modified single-file launcher is available to simplify building a Windows image. This version writes system files and images directly into Docker’s writable layer—no external image mounting required.

Download link: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

Import Docker image:

bash
docker load -i builder.tar

Launching the Container with a Custom Windows ISO

Download a Windows ISO image from: https://down.idc.wiki/ISOS/Windows/

Sample command to start the container:

bash
docker run -it -d \\
+  -e RAM_SIZE="8G" \\
+  -e CPU_CORES="4" \\
+  --name win2022 \\
+  -p 8006:8006 \\
+  --device=/dev/kvm \\
+  --device=/dev/net/tun \\
+  --cap-add NET_ADMIN \\
+  -v "$(pwd)/WindowsImage.iso:/boot.iso" \\
+  --stop-timeout 120 \\
+  windows:builder

We also offer a ready-to-use image with the system and configuration already integrated. Features:

  • Image size: ~26 GB (includes system image and default config)
  • Supports auto disk expansion and startup tasks
  • Just download, import, and run
  • ⚠️ Note: Combined download will require ~60 GB of free space

Download and Merge Split Files

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
+chmod +x mergew.sh
+bash mergew.sh

Start the Container

bash
docker load -i win2022.tar
+docker run -it -d \\
+  -e RAM_SIZE="4G" \\
+  -e CPU_CORES="2" \\
+  --name win2022 \\
+  -p 8006:8006 \\
+  --device=/dev/kvm \\
+  --device=/dev/net/tun \\
+  --cap-add NET_ADMIN \\
+  --stop-timeout 120 \\
+  windows:2022

Important Notes

It is not recommended to use docker commit to save changes to this image, as repeated layer stacking may cause the image size to exceed 40 GB.

For personalized configuration or additional software integration, always start from the builder image to ensure a clean and maintainable result.

`,61)]))}const g=i(n,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_docker_docker_windows.md.CDb3Bppx.lean.js b/assets/en_guide_docker_docker_windows.md.CDb3Bppx.lean.js new file mode 100644 index 0000000000..bef8632051 --- /dev/null +++ b/assets/en_guide_docker_docker_windows.md.CDb3Bppx.lean.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as a,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Running Windows Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_windows.md","filePath":"en/guide/docker/docker_windows.md","lastUpdated":1747984962000}'),n={name:"en/guide/docker/docker_windows.md"};function o(r,s,l,h,p,d){return a(),e("div",null,s[0]||(s[0]=[t("",61)]))}const g=i(n,[["render",o]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_docker_docker_windows.md.aeb5b431.js b/assets/en_guide_docker_docker_windows.md.aeb5b431.js deleted file mode 100644 index 8ba3b7ce48..0000000000 --- a/assets/en_guide_docker_docker_windows.md.aeb5b431.js +++ /dev/null @@ -1,26 +0,0 @@ -import{_ as s,v as e,b as a,R as n}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Running Windows Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_windows.md","filePath":"en/guide/docker/docker_windows.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_windows.md"},t=n(`

Running Windows Virtual Machine in Docker

One-Click Deployment (Using Vagrant)

  • Shares all resources of the host machine; based on Docker, so it only occupies the size of the system, suitable for multiple instances.
  • Shares IP; Docker's NAT mapping is employed. You can choose whether to map to the external network or just the internal network.
  • The configured Windows system is set to use a maximum of 1 core, 2GB RAM, and 50GB hard disk by default. Actual usage may vary based on usage patterns.
  • No need for iptables for NAT mapping; port mappings are automatically deleted when containers are removed, making maintenance easier.
  • Ensure that the host machine supports nested virtualization, and currently, only X86_64 architecture systems are supported. I haven't compiled corresponding images for ARM devices at the moment.

The host machine needs to support nested virtualization and currently only supports systems based on the X86_64 architecture; I don't have an ARM machine on hand to compile the corresponding image at the moment.

Command:

shell
egrep -c '(vmx|svm)' /proc/cpuinfo

The result should be greater than or equal to 1 and cannot be 0.

Next, you need to configure Docker to start using the v1 version of cgroup.

shell
sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

If there are no errors during execution, run the reboot command to restart the system and apply the settings.

Supported Images

We are using custom-built images: https://hub.docker.com/r/spiritlhl/wds

Image NameImage Size
1020GB
202217.5GB
201917GB

The size of the created container will be slightly larger than the image size, but not by much.

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

Usage Instructions

Make sure to execute the following commands in a 'screen' session before proceeding, to avoid potential disconnection or freezing of the SSH connection.

./onewindows.sh <container_name> <system_version> <RDP_port> <external_mapping>
  • Replace <container_name> with the name.
  • Replace <system_version> with the desired Windows system version.
  • Replace <RDP_port> with the port number for RDP access.
  • If you want to enable external mapping, replace <external_mapping> with 'Y'. If not, leave it blank or use 'N'.

Before initiating the setup, ensure that the host machine has a disk size at least twice the size of the image, plus an additional 10GB, as Docker needs to pull the image locally before creating the container.

During the creation process, the peak disk usage will be host_system_size + image_size + container_size.

For example, to set up a container with the name test, the container with the lowest occupancy Windows 2019 system, map the extranet RDP port 13389 and set it to extranet mapping (mapping to your server's extranet IPV4 address)

shell
./onewindows.sh test 2019 13389 Y

After it, the default usernames are Administrator and vagrant, with the default password being vagrant.

If you choose to open a mapped extranet port, be sure to log in and change the password of the corresponding account (both accounts may have, try it yourself), otherwise it may be abused by someone blasting

Deletion

To delete the corresponding image and container, first use the command docker ps -a and docker images to find the ID of the image named spiritlhl/wds. Then, use the following commands accordingly:

docker rm -f container_ID
-docker rmi image_ID

After deletion, you can create containers of different versions of Windows.

Other similar projects

https://github.com/dockur/windows - Similar project that support more systems, but have more resource requirements

https://github.com/dockur/windows-arm/ - It's great that he has ARM servers for mirror compilation, my project doesn't have

Note that both of the above projects require a host with at least 4 cores of CPU, at least 4G of RAM, and at least 64G of hard disk, which is greater than the mirroring requirements of my project. (The advantage of his project is that you can customize many configuration items, see his corresponding project description for details.)

Manual Provisioning (via the Dockur Project)

This project supports VM creation using QEMU even on host systems that do not support nested virtualization.

Original Project Repositories

⚠️ Notes:

  • The original project provides only the launcher, not a Windows image.

  • The first container startup may take up to 4 hours on domestic (China) networks, due to image download and installation.

  • The host system should meet the following minimum hardware requirements (can be adjusted via script modifications):

    • CPU: At least 4 cores
    • RAM: At least 4 GB
    • Disk: At least 64 GB

For customization such as reducing resource usage or changing launch parameters, refer to:

For x86_64 Architecture Users

A pre-modified single-file launcher is available to simplify building a Windows image. This version writes system files and images directly into Docker’s writable layer—no external image mounting required.

Download link: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

Import Docker image:

bash
docker load -i builder.tar

Launching the Container with a Custom Windows ISO

Download a Windows ISO image from: https://down.idc.wiki/ISOS/Windows/

Sample command to start the container:

bash
docker run -it -d \\
-  -e RAM_SIZE="8G" \\
-  -e CPU_CORES="4" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  -v "$(pwd)/WindowsImage.iso:/boot.iso" \\
-  --stop-timeout 120 \\
-  windows:builder

We also offer a ready-to-use image with the system and configuration already integrated. Features:

  • Image size: ~26 GB (includes system image and default config)
  • Supports auto disk expansion and startup tasks
  • Just download, import, and run
  • ⚠️ Note: Combined download will require ~60 GB of free space

Download and Merge Split Files

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

Start the Container

bash
docker load -i win2022.tar
-docker run -it -d \\
-  -e RAM_SIZE="4G" \\
-  -e CPU_CORES="2" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  --stop-timeout 120 \\
-  windows:2022

Important Notes

It is not recommended to use docker commit to save changes to this image, as repeated layer stacking may cause the image size to exceed 40 GB.

For personalized configuration or additional software integration, always start from the builder image to ensure a clean and maintainable result.

`,61),l=[t];function r(p,i,c,d,h,u){return e(),a("div",null,l)}const m=s(o,[["render",r]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_docker_docker_windows.md.aeb5b431.lean.js b/assets/en_guide_docker_docker_windows.md.aeb5b431.lean.js deleted file mode 100644 index 8ba3b7ce48..0000000000 --- a/assets/en_guide_docker_docker_windows.md.aeb5b431.lean.js +++ /dev/null @@ -1,26 +0,0 @@ -import{_ as s,v as e,b as a,R as n}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Running Windows Virtual Machine in Docker","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/docker/docker_windows.md","filePath":"en/guide/docker/docker_windows.md","lastUpdated":1747972048000}'),o={name:"en/guide/docker/docker_windows.md"},t=n(`

Running Windows Virtual Machine in Docker

One-Click Deployment (Using Vagrant)

  • Shares all resources of the host machine; based on Docker, so it only occupies the size of the system, suitable for multiple instances.
  • Shares IP; Docker's NAT mapping is employed. You can choose whether to map to the external network or just the internal network.
  • The configured Windows system is set to use a maximum of 1 core, 2GB RAM, and 50GB hard disk by default. Actual usage may vary based on usage patterns.
  • No need for iptables for NAT mapping; port mappings are automatically deleted when containers are removed, making maintenance easier.
  • Ensure that the host machine supports nested virtualization, and currently, only X86_64 architecture systems are supported. I haven't compiled corresponding images for ARM devices at the moment.

The host machine needs to support nested virtualization and currently only supports systems based on the X86_64 architecture; I don't have an ARM machine on hand to compile the corresponding image at the moment.

Command:

shell
egrep -c '(vmx|svm)' /proc/cpuinfo

The result should be greater than or equal to 1 and cannot be 0.

Next, you need to configure Docker to start using the v1 version of cgroup.

shell
sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

If there are no errors during execution, run the reboot command to restart the system and apply the settings.

Supported Images

We are using custom-built images: https://hub.docker.com/r/spiritlhl/wds

Image NameImage Size
1020GB
202217.5GB
201917GB

The size of the created container will be slightly larger than the image size, but not by much.

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

Usage Instructions

Make sure to execute the following commands in a 'screen' session before proceeding, to avoid potential disconnection or freezing of the SSH connection.

./onewindows.sh <container_name> <system_version> <RDP_port> <external_mapping>
  • Replace <container_name> with the name.
  • Replace <system_version> with the desired Windows system version.
  • Replace <RDP_port> with the port number for RDP access.
  • If you want to enable external mapping, replace <external_mapping> with 'Y'. If not, leave it blank or use 'N'.

Before initiating the setup, ensure that the host machine has a disk size at least twice the size of the image, plus an additional 10GB, as Docker needs to pull the image locally before creating the container.

During the creation process, the peak disk usage will be host_system_size + image_size + container_size.

For example, to set up a container with the name test, the container with the lowest occupancy Windows 2019 system, map the extranet RDP port 13389 and set it to extranet mapping (mapping to your server's extranet IPV4 address)

shell
./onewindows.sh test 2019 13389 Y

After it, the default usernames are Administrator and vagrant, with the default password being vagrant.

If you choose to open a mapped extranet port, be sure to log in and change the password of the corresponding account (both accounts may have, try it yourself), otherwise it may be abused by someone blasting

Deletion

To delete the corresponding image and container, first use the command docker ps -a and docker images to find the ID of the image named spiritlhl/wds. Then, use the following commands accordingly:

docker rm -f container_ID
-docker rmi image_ID

After deletion, you can create containers of different versions of Windows.

Other similar projects

https://github.com/dockur/windows - Similar project that support more systems, but have more resource requirements

https://github.com/dockur/windows-arm/ - It's great that he has ARM servers for mirror compilation, my project doesn't have

Note that both of the above projects require a host with at least 4 cores of CPU, at least 4G of RAM, and at least 64G of hard disk, which is greater than the mirroring requirements of my project. (The advantage of his project is that you can customize many configuration items, see his corresponding project description for details.)

Manual Provisioning (via the Dockur Project)

This project supports VM creation using QEMU even on host systems that do not support nested virtualization.

Original Project Repositories

⚠️ Notes:

  • The original project provides only the launcher, not a Windows image.

  • The first container startup may take up to 4 hours on domestic (China) networks, due to image download and installation.

  • The host system should meet the following minimum hardware requirements (can be adjusted via script modifications):

    • CPU: At least 4 cores
    • RAM: At least 4 GB
    • Disk: At least 64 GB

For customization such as reducing resource usage or changing launch parameters, refer to:

For x86_64 Architecture Users

A pre-modified single-file launcher is available to simplify building a Windows image. This version writes system files and images directly into Docker’s writable layer—no external image mounting required.

Download link: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

Import Docker image:

bash
docker load -i builder.tar

Launching the Container with a Custom Windows ISO

Download a Windows ISO image from: https://down.idc.wiki/ISOS/Windows/

Sample command to start the container:

bash
docker run -it -d \\
-  -e RAM_SIZE="8G" \\
-  -e CPU_CORES="4" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  -v "$(pwd)/WindowsImage.iso:/boot.iso" \\
-  --stop-timeout 120 \\
-  windows:builder

We also offer a ready-to-use image with the system and configuration already integrated. Features:

  • Image size: ~26 GB (includes system image and default config)
  • Supports auto disk expansion and startup tasks
  • Just download, import, and run
  • ⚠️ Note: Combined download will require ~60 GB of free space

Download and Merge Split Files

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

Start the Container

bash
docker load -i win2022.tar
-docker run -it -d \\
-  -e RAM_SIZE="4G" \\
-  -e CPU_CORES="2" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  --stop-timeout 120 \\
-  windows:2022

Important Notes

It is not recommended to use docker commit to save changes to this image, as repeated layer stacking may cause the image size to exceed 40 GB.

For personalized configuration or additional software integration, always start from the builder image to ensure a clean and maintainable result.

`,61),l=[t];function r(p,i,c,d,h,u){return e(),a("div",null,l)}const m=s(o,[["render",r]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_incus_incus_custom.md.DUBzNIug.js b/assets/en_guide_incus_incus_custom.md.DUBzNIug.js new file mode 100644 index 0000000000..fa80949951 --- /dev/null +++ b/assets/en_guide_incus_incus_custom.md.DUBzNIug.js @@ -0,0 +1,80 @@ +import{_ as t,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const i="/assets/lxd1.CbGLa5s4.png",o="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",p="/assets/lxd4.CSfRHLxz.png",r="/assets/lxd5.WUJi0qzd.png",h="/assets/lxd6.Cnds779U.png",d="/assets/lxd7.EJ0s1ls2.png",c="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",k="/assets/lxd11.D6E5sVW2.png",m="/assets/lxd12.B9udKIzn.png",b="/assets/lxd13.Dwv7xBpz.png",f="/assets/lxd14.Whdz6cP-.png",y="/assets/lxd15.BjW7LbDr.png",v="/assets/lxd16.CgeIdYJ2.png",F="/assets/lxd17.CWPY1pea.png",w="/assets/lxd18.DqnpcYcL.png",C="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",P="/assets/lxd21.w-R0l00Y.png",_="/assets/lxd22.45M-VX6J.png",E="/assets/lxd23.CLaVW0qk.png",S=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_custom.md","filePath":"en/guide/incus/incus_custom.md","lastUpdated":1747984962000}'),I={name:"en/guide/incus/incus_custom.md"};function B(q,e,T,V,A,O){return a(),s("div",null,e[0]||(e[0]=[n(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
+systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of incus is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
+EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
+ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
+Client IPv4
+Server IPv6
+Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify here
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
+ip tunnel del server-ipv6

client

ip link set user-ipv6 down
+ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
+apt update -y
+
+# Install WireGuard runtime dependencies
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# Install WireGuard protocol-compatible toolset
+apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
+yum update -y
+
+# Install additional package components
+yum install -y epel-release 
+
+# Install WireGuard runtime dependencies
+yum install -y net-tools
+
+# Install WireGuard protocol-compatible toolset
+yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6 >/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
+sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
+wg-quick up warp
+
+# Check IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# Check IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# Disconnect from Warp after successful test.
+wg-quick down warp
+
+# Reconnect and set process daemon to take effect automatically after reboot.
+systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194)]))}const W=t(I,[["render",B]]);export{S as __pageData,W as default}; diff --git a/assets/en_guide_incus_incus_custom.md.DUBzNIug.lean.js b/assets/en_guide_incus_incus_custom.md.DUBzNIug.lean.js new file mode 100644 index 0000000000..71c58a099e --- /dev/null +++ b/assets/en_guide_incus_incus_custom.md.DUBzNIug.lean.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const i="/assets/lxd1.CbGLa5s4.png",o="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",p="/assets/lxd4.CSfRHLxz.png",r="/assets/lxd5.WUJi0qzd.png",h="/assets/lxd6.Cnds779U.png",d="/assets/lxd7.EJ0s1ls2.png",c="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",k="/assets/lxd11.D6E5sVW2.png",m="/assets/lxd12.B9udKIzn.png",b="/assets/lxd13.Dwv7xBpz.png",f="/assets/lxd14.Whdz6cP-.png",y="/assets/lxd15.BjW7LbDr.png",v="/assets/lxd16.CgeIdYJ2.png",F="/assets/lxd17.CWPY1pea.png",w="/assets/lxd18.DqnpcYcL.png",C="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",P="/assets/lxd21.w-R0l00Y.png",_="/assets/lxd22.45M-VX6J.png",E="/assets/lxd23.CLaVW0qk.png",S=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_custom.md","filePath":"en/guide/incus/incus_custom.md","lastUpdated":1747984962000}'),I={name:"en/guide/incus/incus_custom.md"};function B(q,e,T,V,A,O){return a(),s("div",null,e[0]||(e[0]=[n("",194)]))}const W=t(I,[["render",B]]);export{S as __pageData,W as default}; diff --git a/assets/en_guide_incus_incus_custom.md.f6f0e581.js b/assets/en_guide_incus_incus_custom.md.f6f0e581.js deleted file mode 100644 index 30540e8461..0000000000 --- a/assets/en_guide_incus_incus_custom.md.f6f0e581.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as e,v as s,b as t,R as a}from"./chunks/framework.70afa331.js";const n="/assets/lxd1.78537e30.png",o="/assets/lxd2.da10b5ec.png",l="/assets/lxd3.917f56de.png",p="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",r="/assets/lxd6.572825bf.png",c="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",y="/assets/lxd11.b83f953c.png",m="/assets/lxd12.0da335dd.png",C="/assets/lxd13.308fe0de.png",g="/assets/lxd14.8dbfdcd6.png",f="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",A="/assets/lxd17.d7ea65d8.png",v="/assets/lxd18.d6225daa.png",D="/assets/lxd19.69674669.png",k="/assets/lxd20.179fc6e1.png",w="/assets/lxd21.48123d6a.png",F="/assets/lxd22.4386597e.png",P="/assets/lxd23.c26427e3.png",W=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_custom.md","filePath":"en/guide/incus/incus_custom.md","lastUpdated":1747972048000}'),_={name:"en/guide/incus/incus_custom.md"},I=a(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of incus is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194),x=[I];function E(q,T,V,B,O,S){return s(),t("div",null,x)}const M=e(_,[["render",E]]);export{W as __pageData,M as default}; diff --git a/assets/en_guide_incus_incus_custom.md.f6f0e581.lean.js b/assets/en_guide_incus_incus_custom.md.f6f0e581.lean.js deleted file mode 100644 index 30540e8461..0000000000 --- a/assets/en_guide_incus_incus_custom.md.f6f0e581.lean.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as e,v as s,b as t,R as a}from"./chunks/framework.70afa331.js";const n="/assets/lxd1.78537e30.png",o="/assets/lxd2.da10b5ec.png",l="/assets/lxd3.917f56de.png",p="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",r="/assets/lxd6.572825bf.png",c="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",y="/assets/lxd11.b83f953c.png",m="/assets/lxd12.0da335dd.png",C="/assets/lxd13.308fe0de.png",g="/assets/lxd14.8dbfdcd6.png",f="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",A="/assets/lxd17.d7ea65d8.png",v="/assets/lxd18.d6225daa.png",D="/assets/lxd19.69674669.png",k="/assets/lxd20.179fc6e1.png",w="/assets/lxd21.48123d6a.png",F="/assets/lxd22.4386597e.png",P="/assets/lxd23.c26427e3.png",W=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_custom.md","filePath":"en/guide/incus/incus_custom.md","lastUpdated":1747972048000}'),_={name:"en/guide/incus/incus_custom.md"},I=a(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of incus is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194),x=[I];function E(q,T,V,B,O,S){return s(),t("div",null,x)}const M=e(_,[["render",E]]);export{W as __pageData,M as default}; diff --git a/assets/en_guide_incus_incus_extra_config.md.06d84d9b.js b/assets/en_guide_incus_incus_extra_config.md.06d84d9b.js deleted file mode 100644 index c3209ccb2a..0000000000 --- a/assets/en_guide_incus_incus_extra_config.md.06d84d9b.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_extra_config.md","filePath":"en/guide/incus/incus_extra_config.md","lastUpdated":1747972048000}'),e={name:"en/guide/incus/incus_extra_config.md"},l=o(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for incus containers created with incus.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for incus Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

One-Click Installation of the official incus Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

`,29),t=[l];function p(i,c,r,C,d,y){return a(),n("div",null,t)}const D=s(e,[["render",p]]);export{h as __pageData,D as default}; diff --git a/assets/en_guide_incus_incus_extra_config.md.06d84d9b.lean.js b/assets/en_guide_incus_incus_extra_config.md.06d84d9b.lean.js deleted file mode 100644 index c3209ccb2a..0000000000 --- a/assets/en_guide_incus_incus_extra_config.md.06d84d9b.lean.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_extra_config.md","filePath":"en/guide/incus/incus_extra_config.md","lastUpdated":1747972048000}'),e={name:"en/guide/incus/incus_extra_config.md"},l=o(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for incus containers created with incus.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for incus Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

One-Click Installation of the official incus Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

`,29),t=[l];function p(i,c,r,C,d,y){return a(),n("div",null,t)}const D=s(e,[["render",p]]);export{h as __pageData,D as default}; diff --git a/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.js b/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.js new file mode 100644 index 0000000000..d4eae9cd41 --- /dev/null +++ b/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.js @@ -0,0 +1,11 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_extra_config.md","filePath":"en/guide/incus/incus_extra_config.md","lastUpdated":1747984962000}'),e={name:"en/guide/incus/incus_extra_config.md"};function l(h,s,p,o,r,d){return t(),a("div",null,s[0]||(s[0]=[n(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for incus containers created with incus.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for incus Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

One-Click Installation of the official incus Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
apt-get install -y incus-ui-canonical
+incus config set core.https_address [::]

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

`,29)]))}const g=i(e,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.lean.js b/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.lean.js new file mode 100644 index 0000000000..660c767db9 --- /dev/null +++ b/assets/en_guide_incus_incus_extra_config.md.BkutcTAl.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_extra_config.md","filePath":"en/guide/incus/incus_extra_config.md","lastUpdated":1747984962000}'),e={name:"en/guide/incus/incus_extra_config.md"};function l(h,s,p,o,r,d){return t(),a("div",null,s[0]||(s[0]=[n("",29)]))}const g=i(e,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_install.md.BgEyJdKz.js b/assets/en_guide_incus_incus_install.md.BgEyJdKz.js new file mode 100644 index 0000000000..657b163e4d --- /dev/null +++ b/assets/en_guide_incus_incus_install.md.BgEyJdKz.js @@ -0,0 +1,17 @@ +import{_ as a,c as i,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"incus Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_install.md","filePath":"en/guide/incus/incus_install.md","lastUpdated":1747984962000}'),t={name:"en/guide/incus/incus_install.md"};function l(o,s,p,h,c,r){return e(),i("div",null,s[0]||(s[0]=[n(`

incus Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both update and curl are working properly before executing this script.

  • Prerequisites: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

OR

shell
bash incus_install.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

TIP

The execution process may require a manual reboot to load the storage type into the kernel, the installation is completed at the end of the execution will automatically reboot the server, the first time after the complete installation of the reboot will take about 400 ~ 500 seconds, please be patient

WARNING

If you need to open more than 200 Incus containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Manual Installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing incus

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

sudo -i
+mkdir -p /etc/apt/keyrings/
+curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
+sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
+Enabled: yes
+Types: deb
+URIs: https://pkgs.zabbly.com/incus/stable
+Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
+Components: main
+Architectures: $(dpkg --print-architecture)
+Signed-By: /etc/apt/keyrings/zabbly.gpg
+EOF'
+apt-get update
+apt-get install incus -y
+incus -h

If there are no exceptions, continue execution

incus admin init

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

`,30)]))}const k=a(t,[["render",l]]);export{u as __pageData,k as default}; diff --git a/assets/en_guide_incus_incus_install.md.BgEyJdKz.lean.js b/assets/en_guide_incus_incus_install.md.BgEyJdKz.lean.js new file mode 100644 index 0000000000..5066c43e9c --- /dev/null +++ b/assets/en_guide_incus_incus_install.md.BgEyJdKz.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"incus Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_install.md","filePath":"en/guide/incus/incus_install.md","lastUpdated":1747984962000}'),t={name:"en/guide/incus/incus_install.md"};function l(o,s,p,h,c,r){return e(),i("div",null,s[0]||(s[0]=[n("",30)]))}const k=a(t,[["render",l]]);export{u as __pageData,k as default}; diff --git a/assets/en_guide_incus_incus_install.md.ce7c0d18.js b/assets/en_guide_incus_incus_install.md.ce7c0d18.js deleted file mode 100644 index a6df585c6b..0000000000 --- a/assets/en_guide_incus_incus_install.md.ce7c0d18.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"incus Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_install.md","filePath":"en/guide/incus/incus_install.md","lastUpdated":1747972048000}'),l={name:"en/guide/incus/incus_install.md"},t=e(`

incus Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both update and curl are working properly before executing this script.

  • Prerequisites: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

OR

shell
bash incus_install.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

TIP

The execution process may require a manual reboot to load the storage type into the kernel, the installation is completed at the end of the execution will automatically reboot the server, the first time after the complete installation of the reboot will take about 400 ~ 500 seconds, please be patient

WARNING

If you need to open more than 200 Incus containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Manual Installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing incus

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

If there are no exceptions, continue execution

incus admin init

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

`,30),o=[t];function p(i,c,r,u,d,h){return a(),n("div",null,o)}const m=s(l,[["render",p]]);export{C as __pageData,m as default}; diff --git a/assets/en_guide_incus_incus_install.md.ce7c0d18.lean.js b/assets/en_guide_incus_incus_install.md.ce7c0d18.lean.js deleted file mode 100644 index a6df585c6b..0000000000 --- a/assets/en_guide_incus_incus_install.md.ce7c0d18.lean.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const C=JSON.parse('{"title":"incus Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_install.md","filePath":"en/guide/incus/incus_install.md","lastUpdated":1747972048000}'),l={name:"en/guide/incus/incus_install.md"},t=e(`

incus Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both update and curl are working properly before executing this script.

  • Prerequisites: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

OR

shell
bash incus_install.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

TIP

The execution process may require a manual reboot to load the storage type into the kernel, the installation is completed at the end of the execution will automatically reboot the server, the first time after the complete installation of the reboot will take about 400 ~ 500 seconds, please be patient

WARNING

If you need to open more than 200 Incus containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Manual Installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing incus

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

If there are no exceptions, continue execution

incus admin init

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

`,30),o=[t];function p(i,c,r,u,d,h){return a(),n("div",null,o)}const m=s(l,[["render",p]]);export{C as __pageData,m as default}; diff --git a/assets/en_guide_incus_incus_lxc.md.BxXye95l.js b/assets/en_guide_incus_incus_lxc.md.BxXye95l.js new file mode 100644 index 0000000000..e89fa90066 --- /dev/null +++ b/assets/en_guide_incus_incus_lxc.md.BxXye95l.js @@ -0,0 +1,25 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Running LXC Container in Incus","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_lxc.md","filePath":"en/guide/incus/incus_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/incus/incus_lxc.md"};function h(l,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[e(`

Running LXC Container in Incus

Images available for creating LXC Containers

A portion of the available system parameters are shown here for your reference:

  • debian10, debian11, debian12
  • ubuntu18, ubuntu20, ubuntu22
  • centos8, centos9 (actually opened out of the Stream version)
  • alpine3.15, alpine3.16, alpine3.17, alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (CGroupV1 needs to be enabled in GRUB or it won't start.)
  • kali,archlinux
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

TIP

The version number has ended the long-term maintenance of the general no longer have an official mirror, temporarily did not find the archive address of the historical mirror, if you find welcome to leave a message I will add support!

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Download script

Downloading the boot script is NOT REQUIRED, if you have used the command to install incus with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian11)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support custom server system, do not fill in the leave blank default use debian11, pay attention to the incoming parameters for the system name + version number

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
incus stop test
+incus delete test
+rm -rf test
+rm -rf test_v6
+ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

incus if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

incus if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
+Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, incus virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common incus commands

View all containers:

bash
incus list

View details of a specific container:

bash
incus info container_name

Start a specific container:

bash
incus start container_name

Stop a specific container:

bash
incus stop container_name

Delete a specific container:

bash
incus delete -f container_name

Enter the container's shell:

bash
incus exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all incus containers

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,85)]))}const g=i(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_lxc.md.BxXye95l.lean.js b/assets/en_guide_incus_incus_lxc.md.BxXye95l.lean.js new file mode 100644 index 0000000000..89722d4d0e --- /dev/null +++ b/assets/en_guide_incus_incus_lxc.md.BxXye95l.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Running LXC Container in Incus","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_lxc.md","filePath":"en/guide/incus/incus_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/incus/incus_lxc.md"};function h(l,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[e("",85)]))}const g=i(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.js b/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.js deleted file mode 100644 index a200bd9d57..0000000000 --- a/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Running LXC Container in Incus","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_lxc.md","filePath":"en/guide/incus/incus_lxc.md","lastUpdated":1747972048000}'),o={name:"en/guide/incus/incus_lxc.md"},l=e(`

Running LXC Container in Incus

Images available for creating LXC Containers

A portion of the available system parameters are shown here for your reference:

  • debian10, debian11, debian12
  • ubuntu18, ubuntu20, ubuntu22
  • centos8, centos9 (actually opened out of the Stream version)
  • alpine3.15, alpine3.16, alpine3.17, alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (CGroupV1 needs to be enabled in GRUB or it won't start.)
  • kali,archlinux
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

TIP

The version number has ended the long-term maintenance of the general no longer have an official mirror, temporarily did not find the archive address of the historical mirror, if you find welcome to leave a message I will add support!

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Download script

Downloading the boot script is NOT REQUIRED, if you have used the command to install incus with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian11)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support custom server system, do not fill in the leave blank default use debian11, pay attention to the incoming parameters for the system name + version number

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

incus if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

incus if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, incus virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common incus commands

View all containers:

bash
incus list

View details of a specific container:

bash
incus info container_name

Start a specific container:

bash
incus start container_name

Stop a specific container:

bash
incus stop container_name

Delete a specific container:

bash
incus delete -f container_name

Enter the container's shell:

bash
incus exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all incus containers

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,85),t=[l];function p(r,c,i,C,h,y){return a(),n("div",null,t)}const A=s(o,[["render",p]]);export{u as __pageData,A as default}; diff --git a/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.lean.js b/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.lean.js deleted file mode 100644 index a200bd9d57..0000000000 --- a/assets/en_guide_incus_incus_lxc.md.c5c0a6f8.lean.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"Running LXC Container in Incus","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_lxc.md","filePath":"en/guide/incus/incus_lxc.md","lastUpdated":1747972048000}'),o={name:"en/guide/incus/incus_lxc.md"},l=e(`

Running LXC Container in Incus

Images available for creating LXC Containers

A portion of the available system parameters are shown here for your reference:

  • debian10, debian11, debian12
  • ubuntu18, ubuntu20, ubuntu22
  • centos8, centos9 (actually opened out of the Stream version)
  • alpine3.15, alpine3.16, alpine3.17, alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (CGroupV1 needs to be enabled in GRUB or it won't start.)
  • kali,archlinux
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

TIP

The version number has ended the long-term maintenance of the general no longer have an official mirror, temporarily did not find the archive address of the historical mirror, if you find welcome to leave a message I will add support!

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Download script

Downloading the boot script is NOT REQUIRED, if you have used the command to install incus with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian11)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support custom server system, do not fill in the leave blank default use debian11, pay attention to the incoming parameters for the system name + version number

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

incus if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

incus if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, incus virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common incus commands

View all containers:

bash
incus list

View details of a specific container:

bash
incus info container_name

Start a specific container:

bash
incus start container_name

Stop a specific container:

bash
incus stop container_name

Delete a specific container:

bash
incus delete -f container_name

Enter the container's shell:

bash
incus exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all incus containers

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,85),t=[l];function p(r,c,i,C,h,y){return a(),n("div",null,t)}const A=s(o,[["render",p]]);export{u as __pageData,A as default}; diff --git a/assets/en_guide_incus_incus_precheck.md.44458de1.js b/assets/en_guide_incus_incus_precheck.md.44458de1.js deleted file mode 100644 index cc624ffef7..0000000000 --- a/assets/en_guide_incus_incus_precheck.md.44458de1.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as n,R as o}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_precheck.md","filePath":"en/guide/incus/incus_precheck.md","lastUpdated":1747972048000}'),a={name:"en/guide/incus/incus_precheck.md"},r=o('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/incus

Requirements

Hardware requirements.

  • System: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu24 and Debian12, other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open incus containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for incus containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',15),s=[r];function i(c,d,h,l,u,p){return t(),n("div",null,s)}const b=e(a,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_incus_incus_precheck.md.44458de1.lean.js b/assets/en_guide_incus_incus_precheck.md.44458de1.lean.js deleted file mode 100644 index cc624ffef7..0000000000 --- a/assets/en_guide_incus_incus_precheck.md.44458de1.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as n,R as o}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_precheck.md","filePath":"en/guide/incus/incus_precheck.md","lastUpdated":1747972048000}'),a={name:"en/guide/incus/incus_precheck.md"},r=o('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/incus

Requirements

Hardware requirements.

  • System: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu24 and Debian12, other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open incus containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for incus containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',15),s=[r];function i(c,d,h,l,u,p){return t(),n("div",null,s)}const b=e(a,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.js b/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.js new file mode 100644 index 0000000000..80466373ed --- /dev/null +++ b/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.js @@ -0,0 +1 @@ +import{_ as t,c as n,o,ag as a}from"./chunks/framework.CSeR4K32.js";const p=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_precheck.md","filePath":"en/guide/incus/incus_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/incus/incus_precheck.md"};function i(s,e,c,d,h,l){return o(),n("div",null,e[0]||(e[0]=[a('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/incus

Requirements

Hardware requirements.

  • System: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu24 and Debian12, other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open incus containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for incus containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',15)]))}const m=t(r,[["render",i]]);export{p as __pageData,m as default}; diff --git a/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.lean.js b/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.lean.js new file mode 100644 index 0000000000..633a05948a --- /dev/null +++ b/assets/en_guide_incus_incus_precheck.md.DeMpsPcV.lean.js @@ -0,0 +1 @@ +import{_ as t,c as n,o,ag as a}from"./chunks/framework.CSeR4K32.js";const p=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_precheck.md","filePath":"en/guide/incus/incus_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/incus/incus_precheck.md"};function i(s,e,c,d,h,l){return o(),n("div",null,e[0]||(e[0]=[a("",15)]))}const m=t(r,[["render",i]]);export{p as __pageData,m as default}; diff --git a/assets/en_guide_incus_incus_qa.md.L3eCjNtY.js b/assets/en_guide_incus_incus_qa.md.L3eCjNtY.js new file mode 100644 index 0000000000..f7abbd8667 --- /dev/null +++ b/assets/en_guide_incus_incus_qa.md.L3eCjNtY.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as s,ag as o}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_qa.md","filePath":"en/guide/incus/incus_qa.md","lastUpdated":1747984962000}'),n={name:"en/guide/incus/incus_qa.md"};function i(r,e,p,d,h,l){return s(),a("div",null,e[0]||(e[0]=[o('

Solve the puzzle

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',13)]))}const f=t(n,[["render",i]]);export{c as __pageData,f as default}; diff --git a/assets/en_guide_incus_incus_qa.md.L3eCjNtY.lean.js b/assets/en_guide_incus_incus_qa.md.L3eCjNtY.lean.js new file mode 100644 index 0000000000..d7eb972c48 --- /dev/null +++ b/assets/en_guide_incus_incus_qa.md.L3eCjNtY.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as s,ag as o}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_qa.md","filePath":"en/guide/incus/incus_qa.md","lastUpdated":1747984962000}'),n={name:"en/guide/incus/incus_qa.md"};function i(r,e,p,d,h,l){return s(),a("div",null,e[0]||(e[0]=[o("",13)]))}const f=t(n,[["render",i]]);export{c as __pageData,f as default}; diff --git a/assets/en_guide_incus_incus_qa.md.bea92aa8.js b/assets/en_guide_incus_incus_qa.md.bea92aa8.js deleted file mode 100644 index f5cc653c36..0000000000 --- a/assets/en_guide_incus_incus_qa.md.bea92aa8.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as s}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_qa.md","filePath":"en/guide/incus/incus_qa.md","lastUpdated":1747972048000}'),o={name:"en/guide/incus/incus_qa.md"},n=s('

Solve the puzzle

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',13),r=[n];function p(i,d,l,c,h,u){return t(),a("div",null,r)}const _=e(o,[["render",p]]);export{m as __pageData,_ as default}; diff --git a/assets/en_guide_incus_incus_qa.md.bea92aa8.lean.js b/assets/en_guide_incus_incus_qa.md.bea92aa8.lean.js deleted file mode 100644 index f5cc653c36..0000000000 --- a/assets/en_guide_incus_incus_qa.md.bea92aa8.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as s}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/incus/incus_qa.md","filePath":"en/guide/incus/incus_qa.md","lastUpdated":1747972048000}'),o={name:"en/guide/incus/incus_qa.md"},n=s('

Solve the puzzle

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',13),r=[n];function p(i,d,l,c,h,u){return t(),a("div",null,r)}const _=e(o,[["render",p]]);export{m as __pageData,_ as default}; diff --git a/assets/en_guide_incus_incus_thanks.md.5f3fccbe.js b/assets/en_guide_incus_incus_thanks.md.5f3fccbe.js deleted file mode 100644 index b27773f280..0000000000 --- a/assets/en_guide_incus_incus_thanks.md.5f3fccbe.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as e,b as r,R as n}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_thanks.md","filePath":"en/guide/incus/incus_thanks.md","lastUpdated":1747972048000}'),s={name:"en/guide/incus/incus_thanks.md"},a=n('

Acknowledgements

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10),o=[a];function i(c,p,h,l,u,d){return e(),r("div",null,o)}const b=t(s,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_incus_incus_thanks.md.5f3fccbe.lean.js b/assets/en_guide_incus_incus_thanks.md.5f3fccbe.lean.js deleted file mode 100644 index b27773f280..0000000000 --- a/assets/en_guide_incus_incus_thanks.md.5f3fccbe.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as e,b as r,R as n}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_thanks.md","filePath":"en/guide/incus/incus_thanks.md","lastUpdated":1747972048000}'),s={name:"en/guide/incus/incus_thanks.md"},a=n('

Acknowledgements

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10),o=[a];function i(c,p,h,l,u,d){return e(),r("div",null,o)}const b=t(s,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.js b/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.js new file mode 100644 index 0000000000..c12fb57ff7 --- /dev/null +++ b/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.js @@ -0,0 +1 @@ +import{_ as e,c as r,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_thanks.md","filePath":"en/guide/incus/incus_thanks.md","lastUpdated":1747984962000}'),a={name:"en/guide/incus/incus_thanks.md"};function o(i,t,c,p,l,u){return n(),r("div",null,t[0]||(t[0]=[s('

Acknowledgements

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10)]))}const g=e(a,[["render",o]]);export{d as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.lean.js b/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.lean.js new file mode 100644 index 0000000000..7785b514a3 --- /dev/null +++ b/assets/en_guide_incus_incus_thanks.md.CjY9f-A0.lean.js @@ -0,0 +1 @@ +import{_ as e,c as r,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_thanks.md","filePath":"en/guide/incus/incus_thanks.md","lastUpdated":1747984962000}'),a={name:"en/guide/incus/incus_thanks.md"};function o(i,t,c,p,l,u){return n(),r("div",null,t[0]||(t[0]=[s("",10)]))}const g=e(a,[["render",o]]);export{d as __pageData,g as default}; diff --git a/assets/en_guide_incus_incus_windows.md.7fb5eecc.js b/assets/en_guide_incus_incus_windows.md.7fb5eecc.js deleted file mode 100644 index 1fea6f63c1..0000000000 --- a/assets/en_guide_incus_incus_windows.md.7fb5eecc.js +++ /dev/null @@ -1,28 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const o="/assets/win1.7d3fc058.png",t="/assets/win2.72bb0e48.jpg",l="/assets/win3.442eb15f.jpg",p="/assets/wintj.56bef513.jpg",r="/assets/wincf.76927350.jpg",c="/assets/win4.75bd03c1.jpg",i="/assets/win5.58c1b996.jpg",C="/assets/win7.854d0e0a.jpg",y="/assets/win6.f4215c61.jpg",b=JSON.parse('{"title":"Running Windows Virtual Machines in Incus","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_windows.md","filePath":"en/guide/incus/incus_windows.md","lastUpdated":1747972048000}'),d={name:"en/guide/incus/incus_windows.md"},h=e(`

Running Windows Virtual Machines in Incus

Verify the Incus Driver

Ensure that incus info output contains qemu, otherwise you cannot create VMs:

shell
incus info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, incus drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

Supported Windows image versions for patching: https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.incus.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
# Initialize empty VM
-incus init winvm --empty --vm
-
-# Adjust root disk size, CPU, and memory
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
-
-# Add TPM device (for Secure Boot/BitLocker support)
-incus config device add winvm vtpm tpm path=/dev/tpm0
-
-# Mount installation ISO and set as first boot device
-incus config device add winvm install disk \\
-  source=/root/win.incus.iso \\
-  boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
incus start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the incus list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, incus will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then incus delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
incus config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',60),D=[h];function u(A,m,g,w,f,E){return a(),n("div",null,D)}const F=s(d,[["render",u]]);export{b as __pageData,F as default}; diff --git a/assets/en_guide_incus_incus_windows.md.7fb5eecc.lean.js b/assets/en_guide_incus_incus_windows.md.7fb5eecc.lean.js deleted file mode 100644 index 1fea6f63c1..0000000000 --- a/assets/en_guide_incus_incus_windows.md.7fb5eecc.lean.js +++ /dev/null @@ -1,28 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const o="/assets/win1.7d3fc058.png",t="/assets/win2.72bb0e48.jpg",l="/assets/win3.442eb15f.jpg",p="/assets/wintj.56bef513.jpg",r="/assets/wincf.76927350.jpg",c="/assets/win4.75bd03c1.jpg",i="/assets/win5.58c1b996.jpg",C="/assets/win7.854d0e0a.jpg",y="/assets/win6.f4215c61.jpg",b=JSON.parse('{"title":"Running Windows Virtual Machines in Incus","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_windows.md","filePath":"en/guide/incus/incus_windows.md","lastUpdated":1747972048000}'),d={name:"en/guide/incus/incus_windows.md"},h=e(`

Running Windows Virtual Machines in Incus

Verify the Incus Driver

Ensure that incus info output contains qemu, otherwise you cannot create VMs:

shell
incus info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, incus drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

Supported Windows image versions for patching: https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.incus.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
# Initialize empty VM
-incus init winvm --empty --vm
-
-# Adjust root disk size, CPU, and memory
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
-
-# Add TPM device (for Secure Boot/BitLocker support)
-incus config device add winvm vtpm tpm path=/dev/tpm0
-
-# Mount installation ISO and set as first boot device
-incus config device add winvm install disk \\
-  source=/root/win.incus.iso \\
-  boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
incus start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the incus list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, incus will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then incus delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
incus config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',60),D=[h];function u(A,m,g,w,f,E){return a(),n("div",null,D)}const F=s(d,[["render",u]]);export{b as __pageData,F as default}; diff --git a/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.js b/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.js new file mode 100644 index 0000000000..2a1588fbc2 --- /dev/null +++ b/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.js @@ -0,0 +1,28 @@ +import{_ as i,c as a,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.BYIcp55m.png",h="/assets/win2.BNn7RQzT.jpg",l="/assets/win3.BgsODJcQ.jpg",p="/assets/wintj.tP8uDOfH.jpg",o="/assets/wincf.B_Jc2M1G.jpg",r="/assets/win4.DwKt_Ood.jpg",d="/assets/win5.BSQ3T_9y.jpg",k="/assets/win7.xhBfJRvu.jpg",c="/assets/win6.B-575Zc1.jpg",v=JSON.parse('{"title":"Running Windows Virtual Machines in Incus","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_windows.md","filePath":"en/guide/incus/incus_windows.md","lastUpdated":1747984962000}'),F={name:"en/guide/incus/incus_windows.md"};function g(u,s,y,m,C,B){return e(),a("div",null,s[0]||(s[0]=[t(`

Running Windows Virtual Machines in Incus

Verify the Incus Driver

Ensure that incus info output contains qemu, otherwise you cannot create VMs:

shell
incus info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, incus drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install distrobuilder --classic
+# reboot to load some config
+reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

Supported Windows image versions for patching: https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+distrobuilder repack-windows \\
+  --windows-arch=amd64 \\
+  win.iso \\
+  win.incus.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
# Initialize empty VM
+incus init winvm --empty --vm
+
+# Adjust root disk size, CPU, and memory
+incus config device override winvm root size=30GiB
+incus config set winvm limits.cpu=3
+incus config set winvm limits.memory=5GiB
+
+# Add TPM device (for Secure Boot/BitLocker support)
+incus config device add winvm vtpm tpm path=/dev/tpm0
+
+# Mount installation ISO and set as first boot device
+incus config device add winvm install disk \\
+  source=/root/win.incus.iso \\
+  boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
+apt install -y spice-html5 websockify lsof

Start the VM:

shell
incus start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the incus list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
incus stop winvm
+incus config device remove winvm install
+incus start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, incus will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then incus delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
incus config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',60)]))}const f=i(F,[["render",g]]);export{v as __pageData,f as default}; diff --git a/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.lean.js b/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.lean.js new file mode 100644 index 0000000000..50af791c81 --- /dev/null +++ b/assets/en_guide_incus_incus_windows.md.CPQ_HdzK.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.BYIcp55m.png",h="/assets/win2.BNn7RQzT.jpg",l="/assets/win3.BgsODJcQ.jpg",p="/assets/wintj.tP8uDOfH.jpg",o="/assets/wincf.B_Jc2M1G.jpg",r="/assets/win4.DwKt_Ood.jpg",d="/assets/win5.BSQ3T_9y.jpg",k="/assets/win7.xhBfJRvu.jpg",c="/assets/win6.B-575Zc1.jpg",v=JSON.parse('{"title":"Running Windows Virtual Machines in Incus","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/incus/incus_windows.md","filePath":"en/guide/incus/incus_windows.md","lastUpdated":1747984962000}'),F={name:"en/guide/incus/incus_windows.md"};function g(u,s,y,m,C,B){return e(),a("div",null,s[0]||(s[0]=[t("",60)]))}const f=i(F,[["render",g]]);export{v as __pageData,f as default}; diff --git a/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.js b/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.js new file mode 100644 index 0000000000..987791aa82 --- /dev/null +++ b/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.js @@ -0,0 +1,80 @@ +import{_ as t,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const i="/assets/lxd1.CbGLa5s4.png",o="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",p="/assets/lxd4.CSfRHLxz.png",r="/assets/lxd5.WUJi0qzd.png",h="/assets/lxd6.Cnds779U.png",d="/assets/lxd7.EJ0s1ls2.png",c="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",k="/assets/lxd11.D6E5sVW2.png",m="/assets/lxd12.B9udKIzn.png",b="/assets/lxd13.Dwv7xBpz.png",f="/assets/lxd14.Whdz6cP-.png",y="/assets/lxd15.BjW7LbDr.png",v="/assets/lxd16.CgeIdYJ2.png",F="/assets/lxd17.CWPY1pea.png",w="/assets/lxd18.DqnpcYcL.png",C="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",P="/assets/lxd21.w-R0l00Y.png",_="/assets/lxd22.45M-VX6J.png",E="/assets/lxd23.CLaVW0qk.png",S=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_custom.md","filePath":"en/guide/lxd/lxd_custom.md","lastUpdated":1747984962000}'),I={name:"en/guide/lxd/lxd_custom.md"};function B(q,e,T,V,A,O){return a(),s("div",null,e[0]||(e[0]=[n(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
+systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of LXD is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
+EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
+ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
+Client IPv4
+Server IPv6
+Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify here
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
+ip tunnel del server-ipv6

client

ip link set user-ipv6 down
+ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
+apt update -y
+
+# Install WireGuard runtime dependencies
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# Install WireGuard protocol-compatible toolset
+apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
+yum update -y
+
+# Install additional package components
+yum install -y epel-release 
+
+# Install WireGuard runtime dependencies
+yum install -y net-tools
+
+# Install WireGuard protocol-compatible toolset
+yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6 >/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
+sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
+wg-quick up warp
+
+# Check IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# Check IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# Disconnect from Warp after successful test.
+wg-quick down warp
+
+# Reconnect and set process daemon to take effect automatically after reboot.
+systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194)]))}const W=t(I,[["render",B]]);export{S as __pageData,W as default}; diff --git a/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.lean.js b/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.lean.js new file mode 100644 index 0000000000..6a66cead7f --- /dev/null +++ b/assets/en_guide_lxd_lxd_custom.md.-wt5FjRv.lean.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const i="/assets/lxd1.CbGLa5s4.png",o="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",p="/assets/lxd4.CSfRHLxz.png",r="/assets/lxd5.WUJi0qzd.png",h="/assets/lxd6.Cnds779U.png",d="/assets/lxd7.EJ0s1ls2.png",c="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",k="/assets/lxd11.D6E5sVW2.png",m="/assets/lxd12.B9udKIzn.png",b="/assets/lxd13.Dwv7xBpz.png",f="/assets/lxd14.Whdz6cP-.png",y="/assets/lxd15.BjW7LbDr.png",v="/assets/lxd16.CgeIdYJ2.png",F="/assets/lxd17.CWPY1pea.png",w="/assets/lxd18.DqnpcYcL.png",C="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",P="/assets/lxd21.w-R0l00Y.png",_="/assets/lxd22.45M-VX6J.png",E="/assets/lxd23.CLaVW0qk.png",S=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_custom.md","filePath":"en/guide/lxd/lxd_custom.md","lastUpdated":1747984962000}'),I={name:"en/guide/lxd/lxd_custom.md"};function B(q,e,T,V,A,O){return a(),s("div",null,e[0]||(e[0]=[n("",194)]))}const W=t(I,[["render",B]]);export{S as __pageData,W as default}; diff --git a/assets/en_guide_lxd_lxd_custom.md.f8616b5f.js b/assets/en_guide_lxd_lxd_custom.md.f8616b5f.js deleted file mode 100644 index 8089fc3e9f..0000000000 --- a/assets/en_guide_lxd_lxd_custom.md.f8616b5f.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as e,v as s,b as t,R as a}from"./chunks/framework.70afa331.js";const n="/assets/lxd1.78537e30.png",o="/assets/lxd2.da10b5ec.png",l="/assets/lxd3.917f56de.png",p="/assets/lxd4.83a1a121.png",r="/assets/lxd5.4ebc1444.png",i="/assets/lxd6.572825bf.png",c="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",y="/assets/lxd11.b83f953c.png",m="/assets/lxd12.0da335dd.png",C="/assets/lxd13.308fe0de.png",g="/assets/lxd14.8dbfdcd6.png",f="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",A="/assets/lxd17.d7ea65d8.png",v="/assets/lxd18.d6225daa.png",D="/assets/lxd19.69674669.png",k="/assets/lxd20.179fc6e1.png",w="/assets/lxd21.48123d6a.png",F="/assets/lxd22.4386597e.png",P="/assets/lxd23.c26427e3.png",W=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_custom.md","filePath":"en/guide/lxd/lxd_custom.md","lastUpdated":1747972048000}'),_={name:"en/guide/lxd/lxd_custom.md"},x=a(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of LXD is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194),I=[x];function E(q,T,V,B,O,S){return s(),t("div",null,I)}const M=e(_,[["render",E]]);export{W as __pageData,M as default}; diff --git a/assets/en_guide_lxd_lxd_custom.md.f8616b5f.lean.js b/assets/en_guide_lxd_lxd_custom.md.f8616b5f.lean.js deleted file mode 100644 index 8089fc3e9f..0000000000 --- a/assets/en_guide_lxd_lxd_custom.md.f8616b5f.lean.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as e,v as s,b as t,R as a}from"./chunks/framework.70afa331.js";const n="/assets/lxd1.78537e30.png",o="/assets/lxd2.da10b5ec.png",l="/assets/lxd3.917f56de.png",p="/assets/lxd4.83a1a121.png",r="/assets/lxd5.4ebc1444.png",i="/assets/lxd6.572825bf.png",c="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",y="/assets/lxd11.b83f953c.png",m="/assets/lxd12.0da335dd.png",C="/assets/lxd13.308fe0de.png",g="/assets/lxd14.8dbfdcd6.png",f="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",A="/assets/lxd17.d7ea65d8.png",v="/assets/lxd18.d6225daa.png",D="/assets/lxd19.69674669.png",k="/assets/lxd20.179fc6e1.png",w="/assets/lxd21.48123d6a.png",F="/assets/lxd22.4386597e.png",P="/assets/lxd23.c26427e3.png",W=JSON.parse('{"title":"Custom","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_custom.md","filePath":"en/guide/lxd/lxd_custom.md","lastUpdated":1747972048000}'),_={name:"en/guide/lxd/lxd_custom.md"},x=a(`

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of LXD is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',194),I=[x];function E(q,T,V,B,O,S){return s(),t("div",null,I)}const M=e(_,[["render",E]]);export{W as __pageData,M as default}; diff --git a/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.js b/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.js deleted file mode 100644 index 906fe581e6..0000000000 --- a/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.js +++ /dev/null @@ -1,16 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_extra_config.md","filePath":"en/guide/lxd/lxd_extra_config.md","lastUpdated":1747972048000}'),l={name:"en/guide/lxd/lxd_extra_config.md"},e=o(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for LXC containers created with LXD.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for LXD Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

Enable the official lxd control panel with a single click

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

One-Click Installation of Hosted Third-Party Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
  • Original author's repository: Link
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

After the installation is complete, open the hen IP address, follow the prompts to set the password for admin, other all the way to the default will be able to use the panel!

`,33),t=[e];function p(r,c,i,C,d,y){return a(),n("div",null,t)}const A=s(l,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.lean.js b/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.lean.js deleted file mode 100644 index 906fe581e6..0000000000 --- a/assets/en_guide_lxd_lxd_extra_config.md.3ce9da2c.lean.js +++ /dev/null @@ -1,16 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_extra_config.md","filePath":"en/guide/lxd/lxd_extra_config.md","lastUpdated":1747972048000}'),l={name:"en/guide/lxd/lxd_extra_config.md"},e=o(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for LXC containers created with LXD.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for LXD Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

Enable the official lxd control panel with a single click

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

One-Click Installation of Hosted Third-Party Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
  • Original author's repository: Link
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

After the installation is complete, open the hen IP address, follow the prompts to set the password for admin, other all the way to the default will be able to use the panel!

`,33),t=[e];function p(r,c,i,C,d,y){return a(),n("div",null,t)}const A=s(l,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.js b/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.js new file mode 100644 index 0000000000..203af665f7 --- /dev/null +++ b/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.js @@ -0,0 +1,16 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_extra_config.md","filePath":"en/guide/lxd/lxd_extra_config.md","lastUpdated":1747984962000}'),e={name:"en/guide/lxd/lxd_extra_config.md"};function l(h,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[n(`

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for LXC containers created with LXD.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for LXD Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

Enable the official lxd control panel with a single click

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
sudo snap refresh lxd --channel=latest/stable
+snap set lxd ui.enable=true
+lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
+systemctl reload snap.lxd.daemon
+snap restart --reload lxd

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

One-Click Installation of Hosted Third-Party Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
  • Original author's repository: Link
shell
lxc config set core.https_address [::]
+lxc config set core.trust_password your_password
+snap install lxdmosaic

After the installation is complete, open the hen IP address, follow the prompts to set the password for admin, other all the way to the default will be able to use the panel!

`,33)]))}const F=i(e,[["render",l]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.lean.js b/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.lean.js new file mode 100644 index 0000000000..19d973ecea --- /dev/null +++ b/assets/en_guide_lxd_lxd_extra_config.md.BsivFFBx.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Custom Configuration","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_extra_config.md","filePath":"en/guide/lxd/lxd_extra_config.md","lastUpdated":1747984962000}'),e={name:"en/guide/lxd/lxd_extra_config.md"};function l(h,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[n("",33)]))}const F=i(e,[["render",l]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_install.md.b53a57be.js b/assets/en_guide_lxd_lxd_install.md.b53a57be.js deleted file mode 100644 index 12e80ebd38..0000000000 --- a/assets/en_guide_lxd_lxd_install.md.b53a57be.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const o="/assets/lxdd1.433ff357.png",l="/assets/lxdd2.6a93138a.png",t="/assets/lxdd3.f56cf598.png",p="/assets/lxdd4.28d80b71.png",i="/assets/lxdd0.b1d6b8bc.png",g=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_install.md","filePath":"en/guide/lxd/lxd_install.md","lastUpdated":1747972048000}'),c={name:"en/guide/lxd/lxd_install.md"},r=n('

LXD Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both apt update and apt install curl are working properly before executing this script.

TIP

It's recommended to wait for at least 5 minutes after the system boots up before executing the following commands. This is to avoid the script being executed by the default system settings, which could cause issues with apt sources.

  • Prerequisites: Ubuntu 18+ (recommended above 20.04), Debian 8+ (recommended above 11)
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

OR

shell
bash lxdinstall.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

WARNING

If you need to open more than 200 LXD containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Installation of WEB Control Panel

Customization There are tutorials on how to enable the official panel, but here do not choose to use the official panel, because the official panel in order to security, at the expense of a lot of user experience, this piece of using the

https://github.com/turtle0x1/LxdMosaic

third-party panels

shell
sudo snap install lxdmosaic

Do a straightforward one-click install, then open the current host's https://<public IP address>/ and force access to it to get to the setup page

lxd

lxd

lxd

This piece can be changed if you need to set up the site name

lxd

Better than nothing can only mean that there is no RBAC access control for sub-user segregation

Manual installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing LXD

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

If the following error occurs in the above command

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

Use the command patch before installing lxd

snap install core

If there are no exceptions, the results of the above three lines of commands are as follows

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

Test whether symbolic links are functioning in LXC.

lxc -h

If an error is reported then execute the following command to soft connect the lxc command

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

After connecting, test the lxc command again to see if there is an error about not being able to find it

`,51),d=[r];function h(u,y,C,m,A,D){return a(),e("div",null,d)}const f=s(c,[["render",h]]);export{g as __pageData,f as default}; diff --git a/assets/en_guide_lxd_lxd_install.md.b53a57be.lean.js b/assets/en_guide_lxd_lxd_install.md.b53a57be.lean.js deleted file mode 100644 index 12e80ebd38..0000000000 --- a/assets/en_guide_lxd_lxd_install.md.b53a57be.lean.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const o="/assets/lxdd1.433ff357.png",l="/assets/lxdd2.6a93138a.png",t="/assets/lxdd3.f56cf598.png",p="/assets/lxdd4.28d80b71.png",i="/assets/lxdd0.b1d6b8bc.png",g=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_install.md","filePath":"en/guide/lxd/lxd_install.md","lastUpdated":1747972048000}'),c={name:"en/guide/lxd/lxd_install.md"},r=n('

LXD Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both apt update and apt install curl are working properly before executing this script.

TIP

It's recommended to wait for at least 5 minutes after the system boots up before executing the following commands. This is to avoid the script being executed by the default system settings, which could cause issues with apt sources.

  • Prerequisites: Ubuntu 18+ (recommended above 20.04), Debian 8+ (recommended above 11)
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

OR

shell
bash lxdinstall.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

WARNING

If you need to open more than 200 LXD containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Installation of WEB Control Panel

Customization There are tutorials on how to enable the official panel, but here do not choose to use the official panel, because the official panel in order to security, at the expense of a lot of user experience, this piece of using the

https://github.com/turtle0x1/LxdMosaic

third-party panels

shell
sudo snap install lxdmosaic

Do a straightforward one-click install, then open the current host's https://<public IP address>/ and force access to it to get to the setup page

lxd

lxd

lxd

This piece can be changed if you need to set up the site name

lxd

Better than nothing can only mean that there is no RBAC access control for sub-user segregation

Manual installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing LXD

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

If the following error occurs in the above command

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

Use the command patch before installing lxd

snap install core

If there are no exceptions, the results of the above three lines of commands are as follows

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

Test whether symbolic links are functioning in LXC.

lxc -h

If an error is reported then execute the following command to soft connect the lxc command

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

After connecting, test the lxc command again to see if there is an error about not being able to find it

`,51),d=[r];function h(u,y,C,m,A,D){return a(),e("div",null,d)}const f=s(c,[["render",h]]);export{g as __pageData,f as default}; diff --git a/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.js b/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.js new file mode 100644 index 0000000000..f1152e957e --- /dev/null +++ b/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.js @@ -0,0 +1,6 @@ +import{_ as a,c as i,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/lxdd1.CVTAIewh.png",l="/assets/lxdd2.C_mYE7sL.png",o="/assets/lxdd3.DZ2Na5-t.png",h="/assets/lxdd4.CO1I1FPh.png",p="/assets/lxdd0.QoEngFSd.png",y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_install.md","filePath":"en/guide/lxd/lxd_install.md","lastUpdated":1747984962000}'),r={name:"en/guide/lxd/lxd_install.md"};function d(c,s,k,u,g,m){return e(),i("div",null,s[0]||(s[0]=[t('

LXD Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both apt update and apt install curl are working properly before executing this script.

TIP

It's recommended to wait for at least 5 minutes after the system boots up before executing the following commands. This is to avoid the script being executed by the default system settings, which could cause issues with apt sources.

  • Prerequisites: Ubuntu 18+ (recommended above 20.04), Debian 8+ (recommended above 11)
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

OR

shell
bash lxdinstall.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

WARNING

If you need to open more than 200 LXD containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Installation of WEB Control Panel

Customization There are tutorials on how to enable the official panel, but here do not choose to use the official panel, because the official panel in order to security, at the expense of a lot of user experience, this piece of using the

https://github.com/turtle0x1/LxdMosaic

third-party panels

shell
sudo snap install lxdmosaic

Do a straightforward one-click install, then open the current host's https://<public IP address>/ and force access to it to get to the setup page

lxd

lxd

lxd

This piece can be changed if you need to set up the site name

lxd

Better than nothing can only mean that there is no RBAC access control for sub-user segregation

Manual installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing LXD

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

apt install snapd -y
+snap install lxd
+/snap/bin/lxd init

If the following error occurs in the above command

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

Use the command patch before installing lxd

snap install core

If there are no exceptions, the results of the above three lines of commands are as follows

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

Test whether symbolic links are functioning in LXC.

lxc -h

If an error is reported then execute the following command to soft connect the lxc command

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

After connecting, test the lxc command again to see if there is an error about not being able to find it

`,51)]))}const F=a(r,[["render",d]]);export{y as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.lean.js b/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.lean.js new file mode 100644 index 0000000000..c019caee58 --- /dev/null +++ b/assets/en_guide_lxd_lxd_install.md.z7YfDjTq.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/lxdd1.CVTAIewh.png",l="/assets/lxdd2.C_mYE7sL.png",o="/assets/lxdd3.DZ2Na5-t.png",h="/assets/lxdd4.CO1I1FPh.png",p="/assets/lxdd0.QoEngFSd.png",y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_install.md","filePath":"en/guide/lxd/lxd_install.md","lastUpdated":1747984962000}'),r={name:"en/guide/lxd/lxd_install.md"};function d(c,s,k,u,g,m){return e(),i("div",null,s[0]||(s[0]=[t("",51)]))}const F=a(r,[["render",d]]);export{y as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.js b/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.js deleted file mode 100644 index 04e1bd5aa9..0000000000 --- a/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"LXC virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_lxc.md","filePath":"en/guide/lxd/lxd_lxc.md","lastUpdated":1747972048000}'),o={name:"en/guide/lxd/lxd_lxc.md"},l=e(`

LXC virtualization

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Downloading the boot script is NOT REQUIRED, if you have used the command to install LXD with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian12)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support for customizing the system of the server, do not fill out the default use of debian12 when left blank, note that the incoming parameters for the system name + version number, such as:

  • debian12, debian13
  • ubuntu22, ubuntu24
  • centos8,centos9
  • alpine3.16, alpine3.17, alpine3.18,alpine3.19
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, LXC virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common LXD commands

View all containers:

bash
lxc list

View details of a specific container:

bash
lxc info container_name

Start a specific container:

bash
lxc start container_name

Stop a specific container:

bash
lxc stop container_name

Delete a specific container:

bash
lxc delete -f container_name

Enter the container's shell:

bash
lxc exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all LXC containers

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,81),t=[l];function p(r,c,i,C,h,y){return a(),n("div",null,t)}const A=s(o,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.lean.js b/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.lean.js deleted file mode 100644 index 04e1bd5aa9..0000000000 --- a/assets/en_guide_lxd_lxd_lxc.md.5c2b1e85.lean.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as n,R as e}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"LXC virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_lxc.md","filePath":"en/guide/lxd/lxd_lxc.md","lastUpdated":1747972048000}'),o={name:"en/guide/lxd/lxd_lxc.md"},l=e(`

LXC virtualization

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Downloading the boot script is NOT REQUIRED, if you have used the command to install LXD with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian12)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support for customizing the system of the server, do not fill out the default use of debian12 when left blank, note that the incoming parameters for the system name + version number, such as:

  • debian12, debian13
  • ubuntu22, ubuntu24
  • centos8,centos9
  • alpine3.16, alpine3.17, alpine3.18,alpine3.19
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, LXC virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common LXD commands

View all containers:

bash
lxc list

View details of a specific container:

bash
lxc info container_name

Start a specific container:

bash
lxc start container_name

Stop a specific container:

bash
lxc stop container_name

Delete a specific container:

bash
lxc delete -f container_name

Enter the container's shell:

bash
lxc exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all LXC containers

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,81),t=[l];function p(r,c,i,C,h,y){return a(),n("div",null,t)}const A=s(o,[["render",p]]);export{D as __pageData,A as default}; diff --git a/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.js b/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.js new file mode 100644 index 0000000000..4801fd655c --- /dev/null +++ b/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.js @@ -0,0 +1,25 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"LXC virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_lxc.md","filePath":"en/guide/lxd/lxd_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/lxd/lxd_lxc.md"};function h(l,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[e(`

LXC virtualization

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Downloading the boot script is NOT REQUIRED, if you have used the command to install LXD with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian12)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port\`\` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that \`\`\`can't be null, and it needs to be set to 0 if it's not to be mapped.

Support for customizing the system of the server, do not fill out the default use of debian12 when left blank, note that the incoming parameters for the system name + version number, such as:

  • debian12, debian13
  • ubuntu22, ubuntu24
  • centos8,centos9
  • alpine3.16, alpine3.17, alpine3.18,alpine3.19
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
lxc stop test
+lxc delete test
+rm -rf test
+rm -rf test_v6
+ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put \`\`\`screen\`\` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the \`\`\`screen\`\` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
+Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, LXC virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common LXD commands

View all containers:

bash
lxc list

View details of a specific container:

bash
lxc info container_name

Start a specific container:

bash
lxc start container_name

Stop a specific container:

bash
lxc stop container_name

Delete a specific container:

bash
lxc delete -f container_name

Enter the container's shell:

bash
lxc exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type \`\`\`exit\`\` and enter.

Delete all LXC containers

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

`,81)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.lean.js b/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.lean.js new file mode 100644 index 0000000000..fef22f2707 --- /dev/null +++ b/assets/en_guide_lxd_lxd_lxc.md.xW6rYEDm.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"LXC virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_lxc.md","filePath":"en/guide/lxd/lxd_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/lxd/lxd_lxc.md"};function h(l,s,p,o,r,k){return t(),a("div",null,s[0]||(s[0]=[e("",81)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_precheck.md.995523b7.js b/assets/en_guide_lxd_lxd_precheck.md.995523b7.js deleted file mode 100644 index 5f06c447d9..0000000000 --- a/assets/en_guide_lxd_lxd_precheck.md.995523b7.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as n}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_precheck.md","filePath":"en/guide/lxd/lxd_precheck.md","lastUpdated":1747972048000}'),a={name:"en/guide/lxd/lxd_precheck.md"},r=n('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/lxd

Requirements

Hardware requirements.

  • System: Debian 8+, Ubuntu 18+ (20.04 recommended).
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu20, Ubuntu other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open LXC containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for LXC containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',15),s=[r];function i(d,c,l,h,p,u){return t(),o("div",null,s)}const b=e(a,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_lxd_lxd_precheck.md.995523b7.lean.js b/assets/en_guide_lxd_lxd_precheck.md.995523b7.lean.js deleted file mode 100644 index 5f06c447d9..0000000000 --- a/assets/en_guide_lxd_lxd_precheck.md.995523b7.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as n}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_precheck.md","filePath":"en/guide/lxd/lxd_precheck.md","lastUpdated":1747972048000}'),a={name:"en/guide/lxd/lxd_precheck.md"},r=n('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/lxd

Requirements

Hardware requirements.

  • System: Debian 8+, Ubuntu 18+ (20.04 recommended).
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu20, Ubuntu other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open LXC containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for LXC containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',15),s=[r];function i(d,c,l,h,p,u){return t(),o("div",null,s)}const b=e(a,[["render",i]]);export{f as __pageData,b as default}; diff --git a/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.js b/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.js new file mode 100644 index 0000000000..a8e0463ece --- /dev/null +++ b/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as n,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_precheck.md","filePath":"en/guide/lxd/lxd_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/lxd/lxd_precheck.md"};function i(s,e,d,c,l,h){return n(),o("div",null,e[0]||(e[0]=[a('

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/lxd

Requirements

Hardware requirements.

  • System: Debian 8+, Ubuntu 18+ (20.04 recommended).
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu20, Ubuntu other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open LXC containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for LXC containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',15)]))}const m=t(r,[["render",i]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.lean.js b/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.lean.js new file mode 100644 index 0000000000..83f4a58618 --- /dev/null +++ b/assets/en_guide_lxd_lxd_precheck.md.COYnNjKf.lean.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as n,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_precheck.md","filePath":"en/guide/lxd/lxd_precheck.md","lastUpdated":1747984962000}'),r={name:"en/guide/lxd/lxd_precheck.md"};function i(s,e,d,c,l,h){return n(),o("div",null,e[0]||(e[0]=[a("",15)]))}const m=t(r,[["render",i]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_lxd_lxd_qa.md.7268ae8d.js b/assets/en_guide_lxd_lxd_qa.md.7268ae8d.js deleted file mode 100644 index b6088b2da3..0000000000 --- a/assets/en_guide_lxd_lxd_qa.md.7268ae8d.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,R as s}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_qa.md","filePath":"en/guide/lxd/lxd_qa.md","lastUpdated":1747972048000}'),n={name:"en/guide/lxd/lxd_qa.md"},o=s('

Solve the puzzle

What if the lxc command says it can't be found after LXD is installed?

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc\nexport PATH=$PATH:/snap/bin

After executing this command try

lxc -h

to see if the lxc command is fixed.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',18),r=[o];function p(i,l,d,c,h,u){return a(),t("div",null,r)}const b=e(n,[["render",p]]);export{m as __pageData,b as default}; diff --git a/assets/en_guide_lxd_lxd_qa.md.7268ae8d.lean.js b/assets/en_guide_lxd_lxd_qa.md.7268ae8d.lean.js deleted file mode 100644 index b6088b2da3..0000000000 --- a/assets/en_guide_lxd_lxd_qa.md.7268ae8d.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,R as s}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_qa.md","filePath":"en/guide/lxd/lxd_qa.md","lastUpdated":1747972048000}'),n={name:"en/guide/lxd/lxd_qa.md"},o=s('

Solve the puzzle

What if the lxc command says it can't be found after LXD is installed?

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc\nexport PATH=$PATH:/snap/bin

After executing this command try

lxc -h

to see if the lxc command is fixed.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',18),r=[o];function p(i,l,d,c,h,u){return a(),t("div",null,r)}const b=e(n,[["render",p]]);export{m as __pageData,b as default}; diff --git a/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.js b/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.js new file mode 100644 index 0000000000..fef275e5ef --- /dev/null +++ b/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_qa.md","filePath":"en/guide/lxd/lxd_qa.md","lastUpdated":1747984962000}'),o={name:"en/guide/lxd/lxd_qa.md"};function i(p,e,d,r,l,h){return s(),t("div",null,e[0]||(e[0]=[n('

Solve the puzzle

What if the lxc command says it can't be found after LXD is installed?

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc\nexport PATH=$PATH:/snap/bin

After executing this command try

lxc -h

to see if the lxc command is fixed.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

',18)]))}const f=a(o,[["render",i]]);export{u as __pageData,f as default}; diff --git a/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.lean.js b/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.lean.js new file mode 100644 index 0000000000..5ca3ebdc7b --- /dev/null +++ b/assets/en_guide_lxd_lxd_qa.md.Bs8c7UP0.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/lxd/lxd_qa.md","filePath":"en/guide/lxd/lxd_qa.md","lastUpdated":1747984962000}'),o={name:"en/guide/lxd/lxd_qa.md"};function i(p,e,d,r,l,h){return s(),t("div",null,e[0]||(e[0]=[n("",18)]))}const f=a(o,[["render",i]]);export{u as __pageData,f as default}; diff --git a/assets/guide_incus_incus_thanks.md.4ec3421d.js b/assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.js similarity index 51% rename from assets/guide_incus_incus_thanks.md.4ec3421d.js rename to assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.js index 1a6d063033..57f8ac7f38 100644 --- a/assets/guide_incus_incus_thanks.md.4ec3421d.js +++ b/assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.js @@ -1 +1 @@ -import{_ as t,v as r,b as e,R as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/incus/incus_thanks.md","filePath":"guide/incus/incus_thanks.md","lastUpdated":1747972048000}'),n={name:"guide/incus/incus_thanks.md"},a=s('

致谢

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10),i=[a];function o(c,p,h,u,l,d){return r(),e("div",null,i)}const b=t(n,[["render",o]]);export{f as __pageData,b as default}; +import{_ as t,c as r,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_thanks.md","filePath":"en/guide/lxd/lxd_thanks.md","lastUpdated":1747984962000}'),s={name:"en/guide/lxd/lxd_thanks.md"};function o(i,e,l,p,c,d){return a(),r("div",null,e[0]||(e[0]=[n('

Acknowledgements

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

Thank @Ella-Alinda @fscarmen for providing guidance.

',12)]))}const g=t(s,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.lean.js b/assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.lean.js new file mode 100644 index 0000000000..0a9880ad1b --- /dev/null +++ b/assets/en_guide_lxd_lxd_thanks.md.CeZBLRKW.lean.js @@ -0,0 +1 @@ +import{_ as t,c as r,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_thanks.md","filePath":"en/guide/lxd/lxd_thanks.md","lastUpdated":1747984962000}'),s={name:"en/guide/lxd/lxd_thanks.md"};function o(i,e,l,p,c,d){return a(),r("div",null,e[0]||(e[0]=[n("",12)]))}const g=t(s,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.js b/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.js deleted file mode 100644 index eb6e20e8b3..0000000000 --- a/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as r,R as a}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_thanks.md","filePath":"en/guide/lxd/lxd_thanks.md","lastUpdated":1747972048000}'),n={name:"en/guide/lxd/lxd_thanks.md"},s=a('

Acknowledgements

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

Thank @Ella-Alinda @fscarmen for providing guidance.

',12),o=[s];function i(l,p,c,d,h,u){return t(),r("div",null,o)}const x=e(n,[["render",i]]);export{f as __pageData,x as default}; diff --git a/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.lean.js b/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.lean.js deleted file mode 100644 index eb6e20e8b3..0000000000 --- a/assets/en_guide_lxd_lxd_thanks.md.bbb08af5.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as r,R as a}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_thanks.md","filePath":"en/guide/lxd/lxd_thanks.md","lastUpdated":1747972048000}'),n={name:"en/guide/lxd/lxd_thanks.md"},s=a('

Acknowledgements

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

Thank @Ella-Alinda @fscarmen for providing guidance.

',12),o=[s];function i(l,p,c,d,h,u){return t(),r("div",null,o)}const x=e(n,[["render",i]]);export{f as __pageData,x as default}; diff --git a/assets/en_guide_lxd_lxd_windows.md.586d29ea.js b/assets/en_guide_lxd_lxd_windows.md.586d29ea.js deleted file mode 100644 index bc848efd91..0000000000 --- a/assets/en_guide_lxd_lxd_windows.md.586d29ea.js +++ /dev/null @@ -1,18 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const o="/assets/win1.c8d28bad.png",l="/assets/win2.72bb0e48.jpg",t="/assets/win3.442eb15f.jpg",p="/assets/wintj.56bef513.jpg",r="/assets/wincf.76927350.jpg",c="/assets/win4.75bd03c1.jpg",i="/assets/win5.cacd68cb.jpg",C="/assets/win7.8f856089.jpg",d="/assets/win6.19e58640.jpg",b=JSON.parse('{"title":"Running Windows Virtual Machines in LXD","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_windows.md","filePath":"en/guide/lxd/lxd_windows.md","lastUpdated":1747972048000}'),y={name:"en/guide/lxd/lxd_windows.md"},h=n(`

Running Windows Virtual Machines in LXD

Verify the LXD Driver

Ensure that lxc info output contains qemu, otherwise you cannot create VMs:

shell
lxc info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, lxd drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.lxc.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
lxc start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the lxc list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, lxd will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then lxc delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
lxc config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',59),D=[h];function A(m,u,g,w,f,E){return a(),e("div",null,D)}const F=s(y,[["render",A]]);export{b as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_windows.md.586d29ea.lean.js b/assets/en_guide_lxd_lxd_windows.md.586d29ea.lean.js deleted file mode 100644 index bc848efd91..0000000000 --- a/assets/en_guide_lxd_lxd_windows.md.586d29ea.lean.js +++ /dev/null @@ -1,18 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const o="/assets/win1.c8d28bad.png",l="/assets/win2.72bb0e48.jpg",t="/assets/win3.442eb15f.jpg",p="/assets/wintj.56bef513.jpg",r="/assets/wincf.76927350.jpg",c="/assets/win4.75bd03c1.jpg",i="/assets/win5.cacd68cb.jpg",C="/assets/win7.8f856089.jpg",d="/assets/win6.19e58640.jpg",b=JSON.parse('{"title":"Running Windows Virtual Machines in LXD","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_windows.md","filePath":"en/guide/lxd/lxd_windows.md","lastUpdated":1747972048000}'),y={name:"en/guide/lxd/lxd_windows.md"},h=n(`

Running Windows Virtual Machines in LXD

Verify the LXD Driver

Ensure that lxc info output contains qemu, otherwise you cannot create VMs:

shell
lxc info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, lxd drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.lxc.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
lxc start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the lxc list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, lxd will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then lxc delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
lxc config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',59),D=[h];function A(m,u,g,w,f,E){return a(),e("div",null,D)}const F=s(y,[["render",A]]);export{b as __pageData,F as default}; diff --git a/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.js b/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.js new file mode 100644 index 0000000000..31a822cda2 --- /dev/null +++ b/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.js @@ -0,0 +1,18 @@ +import{_ as i,c as a,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.CJKAoRm5.png",h="/assets/win2.BNn7RQzT.jpg",l="/assets/win3.BgsODJcQ.jpg",p="/assets/wintj.tP8uDOfH.jpg",o="/assets/wincf.B_Jc2M1G.jpg",r="/assets/win4.DwKt_Ood.jpg",d="/assets/win5.C8qmMo1u.jpg",k="/assets/win7.CI43Ul0V.jpg",c="/assets/win6.Cx0KdzQb.jpg",v=JSON.parse('{"title":"Running Windows Virtual Machines in LXD","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_windows.md","filePath":"en/guide/lxd/lxd_windows.md","lastUpdated":1747984962000}'),F={name:"en/guide/lxd/lxd_windows.md"};function g(u,s,y,m,C,w){return e(),a("div",null,s[0]||(s[0]=[t(`

Running Windows Virtual Machines in LXD

Verify the LXD Driver

Ensure that lxc info output contains qemu, otherwise you cannot create VMs:

shell
lxc info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, lxd drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install lxd-imagebuilder --classic --edge
+# reboot to load some config
+reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+lxd-imagebuilder repack-windows \\
+  --windows-arch=amd64 \\
+  win.iso \\
+  win.lxc.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
lxc init winvm --vm --empty
+lxc config device override winvm root size=30GiB
+lxc config set winvm limits.cpu=3 limits.memory=5GiB
+lxc config device add winvm vtpm tpm path=/dev/tpm0
+lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
+apt install -y spice-html5 websockify lsof

Start the VM:

shell
lxc start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the lxc list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
lxc stop winvm
+lxc config device remove winvm install
+lxc start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, lxd will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then lxc delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
lxc config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

',59)]))}const b=i(F,[["render",g]]);export{v as __pageData,b as default}; diff --git a/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.lean.js b/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.lean.js new file mode 100644 index 0000000000..9a3244c1cb --- /dev/null +++ b/assets/en_guide_lxd_lxd_windows.md.CDGEBwH6.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.CJKAoRm5.png",h="/assets/win2.BNn7RQzT.jpg",l="/assets/win3.BgsODJcQ.jpg",p="/assets/wintj.tP8uDOfH.jpg",o="/assets/wincf.B_Jc2M1G.jpg",r="/assets/win4.DwKt_Ood.jpg",d="/assets/win5.C8qmMo1u.jpg",k="/assets/win7.CI43Ul0V.jpg",c="/assets/win6.Cx0KdzQb.jpg",v=JSON.parse('{"title":"Running Windows Virtual Machines in LXD","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/lxd/lxd_windows.md","filePath":"en/guide/lxd/lxd_windows.md","lastUpdated":1747984962000}'),F={name:"en/guide/lxd/lxd_windows.md"};function g(u,s,y,m,C,w){return e(),a("div",null,s[0]||(s[0]=[t("",59)]))}const b=i(F,[["render",g]]);export{v as __pageData,b as default}; diff --git a/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.js b/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.js new file mode 100644 index 0000000000..e2c800bbe7 --- /dev/null +++ b/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,j as s}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/images/readme.md","filePath":"en/guide/pve/images/readme.md","lastUpdated":1747984962000}'),d={name:"en/guide/pve/images/readme.md"};function n(o,e,i,m,p,c){return r(),t("div",null,e[0]||(e[0]=[s("p",null,"暂存图片",-1)]))}const _=a(d,[["render",n]]);export{u as __pageData,_ as default}; diff --git a/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.lean.js b/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.lean.js new file mode 100644 index 0000000000..e2c800bbe7 --- /dev/null +++ b/assets/en_guide_pve_images_readme.md.Dq3BR6Q6.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,j as s}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/images/readme.md","filePath":"en/guide/pve/images/readme.md","lastUpdated":1747984962000}'),d={name:"en/guide/pve/images/readme.md"};function n(o,e,i,m,p,c){return r(),t("div",null,e[0]||(e[0]=[s("p",null,"暂存图片",-1)]))}const _=a(d,[["render",n]]);export{u as __pageData,_ as default}; diff --git a/assets/en_guide_pve_images_readme.md.f8849b0b.js b/assets/en_guide_pve_images_readme.md.f8849b0b.js deleted file mode 100644 index b99d4a8b05..0000000000 --- a/assets/en_guide_pve_images_readme.md.f8849b0b.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,F as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/images/readme.md","filePath":"en/guide/pve/images/readme.md","lastUpdated":1747972048000}'),d={name:"en/guide/pve/images/readme.md"},r=s("p",null,"暂存图片",-1),n=[r];function i(o,m,p,_,c,l){return a(),t("div",null,n)}const g=e(d,[["render",i]]);export{f as __pageData,g as default}; diff --git a/assets/en_guide_pve_images_readme.md.f8849b0b.lean.js b/assets/en_guide_pve_images_readme.md.f8849b0b.lean.js deleted file mode 100644 index b99d4a8b05..0000000000 --- a/assets/en_guide_pve_images_readme.md.f8849b0b.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,F as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/images/readme.md","filePath":"en/guide/pve/images/readme.md","lastUpdated":1747972048000}'),d={name:"en/guide/pve/images/readme.md"},r=s("p",null,"暂存图片",-1),n=[r];function i(o,m,p,_,c,l){return a(),t("div",null,n)}const g=e(d,[["render",i]]);export{f as __pageData,g as default}; diff --git a/assets/en_guide_pve_pve_android.md.D8JpIji1.js b/assets/en_guide_pve_pve_android.md.D8JpIji1.js new file mode 100644 index 0000000000..730b71ea67 --- /dev/null +++ b/assets/en_guide_pve_pve_android.md.D8JpIji1.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const i="/assets/a1.DvgNELwZ.png",n="/assets/a2.BQniQEw_.png",r="/assets/a3.DHUpjnAe.png",p="/assets/a4.BtVJtyBL.png",c="/assets/a5.CamDlEuL.png",d="/assets/a6.auUigeOH.png",l="/assets/a7.3_Is3HF1.png",h="/assets/a8.CkyIulFy.png",m="/assets/a9.Dg58RrTs.png",g="/assets/a10.CPK2ZJEJ.png",u="/assets/a11.Bq6vmveu.png",f="/assets/a12.bStrZLWw.png",_="/assets/a13.DRz8WTJR.png",b="/assets/a14.D56M6gMb.png",y="/assets/a15.CtjmUhal.png",k="/assets/a16.BL0_sgNg.png",w="/assets/a17.B9keXK9k.png",v="/assets/a18.Bu92JFv5.png",C="/assets/a19.DZjr60Xs.png",x="/assets/a20.CesdkIR_.png",I="/assets/a21.BO8sy8n4.png",B="/assets/a22.COjD9r-B.png",S="/assets/a23.BxEEAckp.png",A="/assets/a24.BrCKYLHX.png",T="/assets/a25.CUB6zoiS.png",P="/assets/a26.zvaFRs59.png",F="/assets/ar.Dy_5EjFU.png",q="/assets/a27.QkS9Cjl7.png",O="/assets/a31.BiCzGFMR.png",D="/assets/a32.54sdf1AZ.png",z="/assets/a33.QYBAXO71.png",E="/assets/a34.BBqAz_kr.png",V="/assets/a35.B8NF_iJX.png",U="/assets/a36.CPvsggxV.png",M="/assets/a37.DJRI7pv9.png",R="/assets/a38.BhfuTk-3.png",K="/assets/a39.BNtfZ4xd.png",N="/assets/a40.DTfyEQe2.png",G="/assets/a41.Cb6MjiUm.png",j="/assets/a42.Du63tHI8.png",H="/assets/a43.Cxy9Fqxr.png",L="/assets/a44.Dhcgau_f.png",J="/assets/a45.DQgcLv5f.png",W="/assets/b1.CSqggjTM.png",Y="/assets/b2.BnvPQMj3.png",Q="/assets/b3.DPn2dzFl.png",X="/assets/b4.JBQupWN9.png",Z="/assets/b5.DeuT9J-4.png",$="/assets/b6.cZYHMwJ8.png",ee="/assets/b7.5Fkbt05C.png",te="/assets/b8.BXlK1Dnb.png",oe="/assets/b9.CaK5eLKm.png",se="/assets/b10.DGHfd73s.png",ae="/assets/b11.DKZjwgY8.png",ie="/assets/b12.BISDj2Ri.png",ne="/assets/b13.WGr5jMeK.png",re="/assets/b14.BqBpvoFk.png",pe="/assets/b15.Cd3Rj7ju.png",ce="/assets/b16.BR7AHi1X.png",de="/assets/b17.Cn1C4e1e.png",le="/assets/b18.ElAa2UCQ.png",he="/assets/b19.BwC-oHOW.png",me="/assets/b20.Dj-0rOwy.png",ge="/assets/b21.CYRPkSXE.png",ue="/assets/b22.BH7kRZ3Z.png",fe="/assets/b23.JVX-KOL7.png",_e="/assets/b24.a2fv8lkf.png",be="/assets/b25.BJrNgkiA.png",ye="/assets/b26.5bTO5HK5.png",ke="/assets/b27.BSRz6moE.png",we="/assets/b28.WNjJaEPB.png",ve="/assets/b29.Bs69Ykqp.png",Ce="/assets/b30.B96bh_Ou.png",xe="/assets/b31.BBIAIScF.png",Ie="/assets/b32.8G5Xy9mr.png",Be="/assets/b33.RYxcR7vu.png",Se="/assets/b34.Dw6MyLex.png",Ae="/assets/b35.DUCPsVIG.png",Te="/assets/b36.7aKaNaLh.png",Pe="/assets/b37.B5CHAJzN.png",Fe="/assets/br.CyzpZwsx.png",qe="/assets/b38.Pnnij22W.png",Oe="/assets/b39.ajiHDdbx.png",De="/assets/b40.B6FTkFUT.png",ze="/assets/b41.DcCdod5l.png",Ee="/assets/b42.CT1JvTLX.png",Ve="/assets/b43.HthhPs5o.png",Ue="/assets/b44.C9NeP-UC.png",Me="/assets/b45.BWxBBH-l.png",Re="/assets/b46.B6Ds58im.png",Ye=JSON.parse('{"title":"Android Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_android.md","filePath":"en/guide/pve/pve_android.md","lastUpdated":1747984962000}'),Ke={name:"en/guide/pve/pve_android.md"};function Ne(Ge,e,je,He,Le,Je){return s(),o("div",null,e[0]||(e[0]=[a('

Android Virtual Machine

Android System Image Download

Download links for Android system version 9 and earlier:

International

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

Domestic (China)

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Download links for Android system version 10 and later:

https://blissos.org/index.html#download

Virtual Machine Setup

Setting up an Android Virtual Machine with version 9 and earlier images

This guide demonstrates using:

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

as an example

1

Template Configuration

Create a virtual machine with VMID 100 and select the corresponding storage disk

2

Select the Android image, then choose Linux for Type and choose an option with version 2.6 for Version

3

Select Vmware compatible for Graphic card, other options are default as shown

4

Choose SATA for disk format, allocate at least 30GB of disk space (size can be chosen based on your needs)

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface

9

System Installation

After entering the boot menu, select the option starting with Installation

10

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it

11

Choose not to use GPT format

12

When the empty disk is displayed, select New

13

Select partition type Primary

14

Then you'll be prompted to specify the size of the space. Just press Enter to use all available space

15

Then select Flags, move to Bootable, press Enter until Boot appears under Flags

16

Then move to Write and press Enter to write changes

17

You'll be asked to confirm whether to continue. Type yes and press Enter to continue

18

After a progress bar completes, you'll return to the initial menu. Select Quit to exit the menu, everything is now ready

19

Then you'll return to the UI interface. Use the previously initialized disk and select the OK button

20

Use the arrow keys to select ext4 file system type, then select the OK button

21

Confirm formatting by selecting the Yes button

22

Confirm GRUB boot installation by selecting the OK button

23

Confirm the file system is readable and writable by selecting the OK button

24

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button

25

After a while, you'll enter the Android logo screen

26

Removing the Image

Then there will be a black screen. If it's still black after 3-5 minutes, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

ar

Then execute qm start 100 on the host machine again, and you should enter the Android system initialization interface

System Initialization

In the initialization interface, select the language and click the confirm button

27

It will try to connect to WiFi. Since our PVE installation uses a completely static network configuration, just skip this and set it up later

31

Click the next button to confirm the time settings

32

Click to cancel screen protection, confirm to skip again

33

After a period of black screen, the main screen application selection will appear. If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine as before, and it should display after entering VNC

Select Quickstep

34

Network Settings

After entering the desktop, you need to set up the network. Click the settings icon in the upper left corner

35

A dropdown appears, click and hold to pull down

36

Click the gear button

37

Enter Network & Internet settings

38

Double-click WIFI with the left mouse button

39

Modify the detected VirtWIFI. Right-click to bring up the selection box, then click Modify network

40

Advanced options appear, click to open hidden options

41

Configure the network settings as shown

IP address 172.16.1.xxx (replace xxx with your desired IP, I used 100 because my vmid is 100 for convenience)

Subnet mask 24

Default gateway 172.16.1.1

DNS 8.8.8.8 or 144.144.144.144

Then click the save button

42

At this point, the settings may still not be applied. Turn off WiFi and then turn it back on, it should then show as connected

43

Then exit to the main interface, click on Google Chrome, and try to open a webpage

44

You can see that opening this guide's URL works without problems, proving that the network is connected

45

Setting up an Android Virtual Machine with version 10 and later images

This guide demonstrates using:

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

as an example

1

Template Configuration

The host machine needs to execute the following command to install graphics environment dependencies

shell
apt install libgl1 libegl1 -y

Then start creating the virtual machine by clicking the Create VM button in the upper right corner. Fill in VMID, Name, Resource Pool

2

Select the Android image, then choose Linux for Type and an option with version 2.6 for Version

3

If the host machine has a GPU, select VirGL GPU for Graphic card.

If the host machine doesn't have a GPU, select VirtIO or Vmware compatible for Graphic card.

Select q35 for Machine, select OVMF (UEFI) for BIOS, and select local for EFI Storage.

4

Choose SATA for disk format. How much disk space to allocate is up to you, but at least 30GB is recommended

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface.

System Installation

After entering the boot menu, select the option ending with Installation

9

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it.

10

Choose not to use GPT format, continue using cfdisk format.

11

When the format selection box appears, select gpt.

12

When the empty disk is displayed, select New.

13

Because you need to create an EFI partition, you need to change the size rather than using the default. Change the number to 1 to allocate 1GB of disk space, then press Enter.

14

Then you'll return to the menu bar. Use the arrow keys to select Type, then press Enter to choose the format type for the partition

15

Use the arrow keys to select the first option EFI System, then press Enter

16

Now you're back at the menu bar. In the upper half of the page, you can see the specific partition size and format

17

Then press the down arrow key to select the next empty partition line

18

Select New from the menu bar, then press Enter

19

Here you need to fill in the partition size. Match it with the empty partition size shown in the upper right corner, then press Enter.

20

Return to the menu bar, select Write, press Enter to write the partition.

21

You'll be prompted to enter yes to confirm. Enter it and press Enter.

22

After a progress bar runs, you should return to the menu bar. Select Quit to exit the menu, everything is now ready

23

Then you'll return to the UI interface. Use the previously initialized 1GB disk and select the OK button

24

Use the arrow keys to select fat32 file system type, then select the OK button

25

Confirm not to modify the name by selecting the OK button

26

Confirm formatting by selecting the Yes button

27

Then you'll return to the initial UI bar. Select the second partition that is not 1GB in size and select the OK button

28

Use the arrow keys to select ext4 file system type, then select the OK button

29

Confirm not to modify the name by selecting the OK button

30

Confirm formatting by selecting the Yes button

31

Choose not to use extra space for updates by selecting the No button

32

Confirm GRUB2 EFI BootLoader by selecting the OK button

33

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button.

34

System Initialization

After a while, you'll enter the logo screen.

35

After some more time, you should enter the initial Android interface. You'll see a popup and the time. Hold the left mouse button and swipe up

36

The main screen application selection will appear. Select Quickstep

If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine, and it should display after entering VNC

37

Removing the Image

After the Android interface appears, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

br

Then execute qm start 100 on the host machine again, and you should enter the system's initial interface.

Network Settings

After entering the desktop, you need to set up the network. Hold the left mouse button in the indicated position and swipe up

38

A bunch of applications will pop up. Find the one called Bliss Ethernet Manager and click to open it

39

Click to open IP Assignment, select Static type, click the OK button to confirm

40

Click to open IP Address, enter 172.16.1.xxx/24 (I used 100 for xxx because my virtual machine VMID is 100 for easy identification), click the OK button to confirm

41

Click to open Gateway Address, enter 172.16.1.1, click the OK button to confirm

42

Click to open DNS Address, enter 8.8.8.8, click the OK button to confirm

43

Then in the application interface, click Interface Up and Refresh, then press the exit key on the keyboard to exit the program

44

Open the browser in the main interface to verify that the network is working properly

45

You can see that opening this guide works without problems, the network is functioning

46

',227)]))}const Qe=t(Ke,[["render",Ne]]);export{Ye as __pageData,Qe as default}; diff --git a/assets/en_guide_pve_pve_android.md.D8JpIji1.lean.js b/assets/en_guide_pve_pve_android.md.D8JpIji1.lean.js new file mode 100644 index 0000000000..d81d6286bd --- /dev/null +++ b/assets/en_guide_pve_pve_android.md.D8JpIji1.lean.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const i="/assets/a1.DvgNELwZ.png",n="/assets/a2.BQniQEw_.png",r="/assets/a3.DHUpjnAe.png",p="/assets/a4.BtVJtyBL.png",c="/assets/a5.CamDlEuL.png",d="/assets/a6.auUigeOH.png",l="/assets/a7.3_Is3HF1.png",h="/assets/a8.CkyIulFy.png",m="/assets/a9.Dg58RrTs.png",g="/assets/a10.CPK2ZJEJ.png",u="/assets/a11.Bq6vmveu.png",f="/assets/a12.bStrZLWw.png",_="/assets/a13.DRz8WTJR.png",b="/assets/a14.D56M6gMb.png",y="/assets/a15.CtjmUhal.png",k="/assets/a16.BL0_sgNg.png",w="/assets/a17.B9keXK9k.png",v="/assets/a18.Bu92JFv5.png",C="/assets/a19.DZjr60Xs.png",x="/assets/a20.CesdkIR_.png",I="/assets/a21.BO8sy8n4.png",B="/assets/a22.COjD9r-B.png",S="/assets/a23.BxEEAckp.png",A="/assets/a24.BrCKYLHX.png",T="/assets/a25.CUB6zoiS.png",P="/assets/a26.zvaFRs59.png",F="/assets/ar.Dy_5EjFU.png",q="/assets/a27.QkS9Cjl7.png",O="/assets/a31.BiCzGFMR.png",D="/assets/a32.54sdf1AZ.png",z="/assets/a33.QYBAXO71.png",E="/assets/a34.BBqAz_kr.png",V="/assets/a35.B8NF_iJX.png",U="/assets/a36.CPvsggxV.png",M="/assets/a37.DJRI7pv9.png",R="/assets/a38.BhfuTk-3.png",K="/assets/a39.BNtfZ4xd.png",N="/assets/a40.DTfyEQe2.png",G="/assets/a41.Cb6MjiUm.png",j="/assets/a42.Du63tHI8.png",H="/assets/a43.Cxy9Fqxr.png",L="/assets/a44.Dhcgau_f.png",J="/assets/a45.DQgcLv5f.png",W="/assets/b1.CSqggjTM.png",Y="/assets/b2.BnvPQMj3.png",Q="/assets/b3.DPn2dzFl.png",X="/assets/b4.JBQupWN9.png",Z="/assets/b5.DeuT9J-4.png",$="/assets/b6.cZYHMwJ8.png",ee="/assets/b7.5Fkbt05C.png",te="/assets/b8.BXlK1Dnb.png",oe="/assets/b9.CaK5eLKm.png",se="/assets/b10.DGHfd73s.png",ae="/assets/b11.DKZjwgY8.png",ie="/assets/b12.BISDj2Ri.png",ne="/assets/b13.WGr5jMeK.png",re="/assets/b14.BqBpvoFk.png",pe="/assets/b15.Cd3Rj7ju.png",ce="/assets/b16.BR7AHi1X.png",de="/assets/b17.Cn1C4e1e.png",le="/assets/b18.ElAa2UCQ.png",he="/assets/b19.BwC-oHOW.png",me="/assets/b20.Dj-0rOwy.png",ge="/assets/b21.CYRPkSXE.png",ue="/assets/b22.BH7kRZ3Z.png",fe="/assets/b23.JVX-KOL7.png",_e="/assets/b24.a2fv8lkf.png",be="/assets/b25.BJrNgkiA.png",ye="/assets/b26.5bTO5HK5.png",ke="/assets/b27.BSRz6moE.png",we="/assets/b28.WNjJaEPB.png",ve="/assets/b29.Bs69Ykqp.png",Ce="/assets/b30.B96bh_Ou.png",xe="/assets/b31.BBIAIScF.png",Ie="/assets/b32.8G5Xy9mr.png",Be="/assets/b33.RYxcR7vu.png",Se="/assets/b34.Dw6MyLex.png",Ae="/assets/b35.DUCPsVIG.png",Te="/assets/b36.7aKaNaLh.png",Pe="/assets/b37.B5CHAJzN.png",Fe="/assets/br.CyzpZwsx.png",qe="/assets/b38.Pnnij22W.png",Oe="/assets/b39.ajiHDdbx.png",De="/assets/b40.B6FTkFUT.png",ze="/assets/b41.DcCdod5l.png",Ee="/assets/b42.CT1JvTLX.png",Ve="/assets/b43.HthhPs5o.png",Ue="/assets/b44.C9NeP-UC.png",Me="/assets/b45.BWxBBH-l.png",Re="/assets/b46.B6Ds58im.png",Ye=JSON.parse('{"title":"Android Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_android.md","filePath":"en/guide/pve/pve_android.md","lastUpdated":1747984962000}'),Ke={name:"en/guide/pve/pve_android.md"};function Ne(Ge,e,je,He,Le,Je){return s(),o("div",null,e[0]||(e[0]=[a("",227)]))}const Qe=t(Ke,[["render",Ne]]);export{Ye as __pageData,Qe as default}; diff --git a/assets/en_guide_pve_pve_android.md.bc9044ee.js b/assets/en_guide_pve_pve_android.md.bc9044ee.js deleted file mode 100644 index 1de428c992..0000000000 --- a/assets/en_guide_pve_pve_android.md.bc9044ee.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as s}from"./chunks/framework.70afa331.js";const a="/assets/a1.662d9415.png",n="/assets/a2.1d7d86db.png",i="/assets/a3.178777a1.png",r="/assets/a4.65c15963.png",p="/assets/a5.01b8514f.png",c="/assets/a6.67efded0.png",d="/assets/a7.b8de9a6c.png",l="/assets/a8.69056d9a.png",h="/assets/a9.d4cc5fc0.png",m="/assets/a10.36860678.png",g="/assets/a11.bbc20080.png",u="/assets/a12.da46fe54.png",f="/assets/a13.b49276aa.png",b="/assets/a14.908480a6.png",_="/assets/a15.9533f30d.png",y="/assets/a16.2257f2d8.png",k="/assets/a17.b57c7755.png",w="/assets/a18.c3a22602.png",v="/assets/a19.1eefd81d.png",x="/assets/a20.24042237.png",I="/assets/a21.2bb37c9a.png",C="/assets/a22.44ab6d75.png",A="/assets/a23.191de0ca.png",S="/assets/a24.d2a9c729.png",q="/assets/a25.3e24d99b.png",P="/assets/a26.2fce6332.png",O="/assets/ar.0d8bb8f3.png",T="/assets/a27.dd61884c.png",V="/assets/a31.6d3a9d85.png",z="/assets/a32.d9973307.png",E="/assets/a33.8b54ce3f.png",M="/assets/a34.07f5cc75.png",U="/assets/a35.78be61d4.png",G="/assets/a36.a36765c2.png",D="/assets/a37.e6740eaa.png",F="/assets/a38.999b4ffb.png",B="/assets/a39.9dac95e1.png",K="/assets/a40.7f5ad4ea.png",R="/assets/a41.bbc5e317.png",N="/assets/a42.de7d1da7.png",Y="/assets/a43.e713599d.png",W="/assets/a44.5c4e5e0a.png",L="/assets/a45.2c32612e.png",H="/assets/b1.c1fdb506.png",j="/assets/b2.519a9bf0.png",Q="/assets/b3.42fd37a2.png",$="/assets/b4.b6d283a7.png",J="/assets/b5.4cd5361f.png",X="/assets/b6.36f0470d.png",Z="/assets/b7.9714bb16.png",ee="/assets/b8.2eb373bf.png",te="/assets/b9.3f01ffdc.png",oe="/assets/b10.52a93636.png",se="/assets/b11.2e525d8d.png",ae="/assets/b12.54c3189d.png",ne="/assets/b13.3b3ae784.png",ie="/assets/b14.662b1a1b.png",re="/assets/b15.0c5536d8.png",pe="/assets/b16.0fbcfcb1.png",ce="/assets/b17.4e7429fe.png",de="/assets/b18.8211f293.png",le="/assets/b19.2128d0fa.png",he="/assets/b20.8a62698b.png",me="/assets/b21.dfe1e8f0.png",ge="/assets/b22.13e3438c.png",ue="/assets/b23.e293a560.png",fe="/assets/b24.23cbc29a.png",be="/assets/b25.f2c2ebd7.png",_e="/assets/b26.b7136167.png",ye="/assets/b27.cc8f8644.png",ke="/assets/b28.2bf4d8b9.png",we="/assets/b29.8d301c10.png",ve="/assets/b30.a50bc8f3.png",xe="/assets/b31.4881ca1d.png",Ie="/assets/b32.b857654b.png",Ce="/assets/b33.1125a81c.png",Ae="/assets/b34.2101ce9a.png",Se="/assets/b35.83c5a766.png",qe="/assets/b36.ea1f048c.png",Pe="/assets/b37.b60405a9.png",Oe="/assets/br.bb3418b4.png",Te="/assets/b38.4d73fbe3.png",Ve="/assets/b39.c59ccabe.png",ze="/assets/b40.c1d0ee00.png",Ee="/assets/b41.0c6d7432.png",Me="/assets/b42.66cc353b.png",Ue="/assets/b43.a775b641.png",Ge="/assets/b44.2d540844.png",De="/assets/b45.fe0240c6.png",Fe="/assets/b46.f6b9da14.png",Je=JSON.parse('{"title":"Android Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_android.md","filePath":"en/guide/pve/pve_android.md","lastUpdated":1747972048000}'),Be={name:"en/guide/pve/pve_android.md"},Ke=s('

Android Virtual Machine

Android System Image Download

Download links for Android system version 9 and earlier:

International

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

Domestic (China)

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Download links for Android system version 10 and later:

https://blissos.org/index.html#download

Virtual Machine Setup

Setting up an Android Virtual Machine with version 9 and earlier images

This guide demonstrates using:

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

as an example

1

Template Configuration

Create a virtual machine with VMID 100 and select the corresponding storage disk

2

Select the Android image, then choose Linux for Type and choose an option with version 2.6 for Version

3

Select Vmware compatible for Graphic card, other options are default as shown

4

Choose SATA for disk format, allocate at least 30GB of disk space (size can be chosen based on your needs)

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface

9

System Installation

After entering the boot menu, select the option starting with Installation

10

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it

11

Choose not to use GPT format

12

When the empty disk is displayed, select New

13

Select partition type Primary

14

Then you'll be prompted to specify the size of the space. Just press Enter to use all available space

15

Then select Flags, move to Bootable, press Enter until Boot appears under Flags

16

Then move to Write and press Enter to write changes

17

You'll be asked to confirm whether to continue. Type yes and press Enter to continue

18

After a progress bar completes, you'll return to the initial menu. Select Quit to exit the menu, everything is now ready

19

Then you'll return to the UI interface. Use the previously initialized disk and select the OK button

20

Use the arrow keys to select ext4 file system type, then select the OK button

21

Confirm formatting by selecting the Yes button

22

Confirm GRUB boot installation by selecting the OK button

23

Confirm the file system is readable and writable by selecting the OK button

24

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button

25

After a while, you'll enter the Android logo screen

26

Removing the Image

Then there will be a black screen. If it's still black after 3-5 minutes, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

ar

Then execute qm start 100 on the host machine again, and you should enter the Android system initialization interface

System Initialization

In the initialization interface, select the language and click the confirm button

27

It will try to connect to WiFi. Since our PVE installation uses a completely static network configuration, just skip this and set it up later

31

Click the next button to confirm the time settings

32

Click to cancel screen protection, confirm to skip again

33

After a period of black screen, the main screen application selection will appear. If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine as before, and it should display after entering VNC

Select Quickstep

34

Network Settings

After entering the desktop, you need to set up the network. Click the settings icon in the upper left corner

35

A dropdown appears, click and hold to pull down

36

Click the gear button

37

Enter Network & Internet settings

38

Double-click WIFI with the left mouse button

39

Modify the detected VirtWIFI. Right-click to bring up the selection box, then click Modify network

40

Advanced options appear, click to open hidden options

41

Configure the network settings as shown

IP address 172.16.1.xxx (replace xxx with your desired IP, I used 100 because my vmid is 100 for convenience)

Subnet mask 24

Default gateway 172.16.1.1

DNS 8.8.8.8 or 144.144.144.144

Then click the save button

42

At this point, the settings may still not be applied. Turn off WiFi and then turn it back on, it should then show as connected

43

Then exit to the main interface, click on Google Chrome, and try to open a webpage

44

You can see that opening this guide's URL works without problems, proving that the network is connected

45

Setting up an Android Virtual Machine with version 10 and later images

This guide demonstrates using:

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

as an example

1

Template Configuration

The host machine needs to execute the following command to install graphics environment dependencies

shell
apt install libgl1 libegl1 -y

Then start creating the virtual machine by clicking the Create VM button in the upper right corner. Fill in VMID, Name, Resource Pool

2

Select the Android image, then choose Linux for Type and an option with version 2.6 for Version

3

If the host machine has a GPU, select VirGL GPU for Graphic card.

If the host machine doesn't have a GPU, select VirtIO or Vmware compatible for Graphic card.

Select q35 for Machine, select OVMF (UEFI) for BIOS, and select local for EFI Storage.

4

Choose SATA for disk format. How much disk space to allocate is up to you, but at least 30GB is recommended

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface.

System Installation

After entering the boot menu, select the option ending with Installation

9

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it.

10

Choose not to use GPT format, continue using cfdisk format.

11

When the format selection box appears, select gpt.

12

When the empty disk is displayed, select New.

13

Because you need to create an EFI partition, you need to change the size rather than using the default. Change the number to 1 to allocate 1GB of disk space, then press Enter.

14

Then you'll return to the menu bar. Use the arrow keys to select Type, then press Enter to choose the format type for the partition

15

Use the arrow keys to select the first option EFI System, then press Enter

16

Now you're back at the menu bar. In the upper half of the page, you can see the specific partition size and format

17

Then press the down arrow key to select the next empty partition line

18

Select New from the menu bar, then press Enter

19

Here you need to fill in the partition size. Match it with the empty partition size shown in the upper right corner, then press Enter.

20

Return to the menu bar, select Write, press Enter to write the partition.

21

You'll be prompted to enter yes to confirm. Enter it and press Enter.

22

After a progress bar runs, you should return to the menu bar. Select Quit to exit the menu, everything is now ready

23

Then you'll return to the UI interface. Use the previously initialized 1GB disk and select the OK button

24

Use the arrow keys to select fat32 file system type, then select the OK button

25

Confirm not to modify the name by selecting the OK button

26

Confirm formatting by selecting the Yes button

27

Then you'll return to the initial UI bar. Select the second partition that is not 1GB in size and select the OK button

28

Use the arrow keys to select ext4 file system type, then select the OK button

29

Confirm not to modify the name by selecting the OK button

30

Confirm formatting by selecting the Yes button

31

Choose not to use extra space for updates by selecting the No button

32

Confirm GRUB2 EFI BootLoader by selecting the OK button

33

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button.

34

System Initialization

After a while, you'll enter the logo screen.

35

After some more time, you should enter the initial Android interface. You'll see a popup and the time. Hold the left mouse button and swipe up

36

The main screen application selection will appear. Select Quickstep

If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine, and it should display after entering VNC

37

Removing the Image

After the Android interface appears, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

br

Then execute qm start 100 on the host machine again, and you should enter the system's initial interface.

Network Settings

After entering the desktop, you need to set up the network. Hold the left mouse button in the indicated position and swipe up

38

A bunch of applications will pop up. Find the one called Bliss Ethernet Manager and click to open it

39

Click to open IP Assignment, select Static type, click the OK button to confirm

40

Click to open IP Address, enter 172.16.1.xxx/24 (I used 100 for xxx because my virtual machine VMID is 100 for easy identification), click the OK button to confirm

41

Click to open Gateway Address, enter 172.16.1.1, click the OK button to confirm

42

Click to open DNS Address, enter 8.8.8.8, click the OK button to confirm

43

Then in the application interface, click Interface Up and Refresh, then press the exit key on the keyboard to exit the program

44

Open the browser in the main interface to verify that the network is working properly

45

You can see that opening this guide works without problems, the network is functioning

46

',227),Re=[Ke];function Ne(Ye,We,Le,He,je,Qe){return t(),o("div",null,Re)}const Xe=e(Be,[["render",Ne]]);export{Je as __pageData,Xe as default}; diff --git a/assets/en_guide_pve_pve_android.md.bc9044ee.lean.js b/assets/en_guide_pve_pve_android.md.bc9044ee.lean.js deleted file mode 100644 index 1de428c992..0000000000 --- a/assets/en_guide_pve_pve_android.md.bc9044ee.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as s}from"./chunks/framework.70afa331.js";const a="/assets/a1.662d9415.png",n="/assets/a2.1d7d86db.png",i="/assets/a3.178777a1.png",r="/assets/a4.65c15963.png",p="/assets/a5.01b8514f.png",c="/assets/a6.67efded0.png",d="/assets/a7.b8de9a6c.png",l="/assets/a8.69056d9a.png",h="/assets/a9.d4cc5fc0.png",m="/assets/a10.36860678.png",g="/assets/a11.bbc20080.png",u="/assets/a12.da46fe54.png",f="/assets/a13.b49276aa.png",b="/assets/a14.908480a6.png",_="/assets/a15.9533f30d.png",y="/assets/a16.2257f2d8.png",k="/assets/a17.b57c7755.png",w="/assets/a18.c3a22602.png",v="/assets/a19.1eefd81d.png",x="/assets/a20.24042237.png",I="/assets/a21.2bb37c9a.png",C="/assets/a22.44ab6d75.png",A="/assets/a23.191de0ca.png",S="/assets/a24.d2a9c729.png",q="/assets/a25.3e24d99b.png",P="/assets/a26.2fce6332.png",O="/assets/ar.0d8bb8f3.png",T="/assets/a27.dd61884c.png",V="/assets/a31.6d3a9d85.png",z="/assets/a32.d9973307.png",E="/assets/a33.8b54ce3f.png",M="/assets/a34.07f5cc75.png",U="/assets/a35.78be61d4.png",G="/assets/a36.a36765c2.png",D="/assets/a37.e6740eaa.png",F="/assets/a38.999b4ffb.png",B="/assets/a39.9dac95e1.png",K="/assets/a40.7f5ad4ea.png",R="/assets/a41.bbc5e317.png",N="/assets/a42.de7d1da7.png",Y="/assets/a43.e713599d.png",W="/assets/a44.5c4e5e0a.png",L="/assets/a45.2c32612e.png",H="/assets/b1.c1fdb506.png",j="/assets/b2.519a9bf0.png",Q="/assets/b3.42fd37a2.png",$="/assets/b4.b6d283a7.png",J="/assets/b5.4cd5361f.png",X="/assets/b6.36f0470d.png",Z="/assets/b7.9714bb16.png",ee="/assets/b8.2eb373bf.png",te="/assets/b9.3f01ffdc.png",oe="/assets/b10.52a93636.png",se="/assets/b11.2e525d8d.png",ae="/assets/b12.54c3189d.png",ne="/assets/b13.3b3ae784.png",ie="/assets/b14.662b1a1b.png",re="/assets/b15.0c5536d8.png",pe="/assets/b16.0fbcfcb1.png",ce="/assets/b17.4e7429fe.png",de="/assets/b18.8211f293.png",le="/assets/b19.2128d0fa.png",he="/assets/b20.8a62698b.png",me="/assets/b21.dfe1e8f0.png",ge="/assets/b22.13e3438c.png",ue="/assets/b23.e293a560.png",fe="/assets/b24.23cbc29a.png",be="/assets/b25.f2c2ebd7.png",_e="/assets/b26.b7136167.png",ye="/assets/b27.cc8f8644.png",ke="/assets/b28.2bf4d8b9.png",we="/assets/b29.8d301c10.png",ve="/assets/b30.a50bc8f3.png",xe="/assets/b31.4881ca1d.png",Ie="/assets/b32.b857654b.png",Ce="/assets/b33.1125a81c.png",Ae="/assets/b34.2101ce9a.png",Se="/assets/b35.83c5a766.png",qe="/assets/b36.ea1f048c.png",Pe="/assets/b37.b60405a9.png",Oe="/assets/br.bb3418b4.png",Te="/assets/b38.4d73fbe3.png",Ve="/assets/b39.c59ccabe.png",ze="/assets/b40.c1d0ee00.png",Ee="/assets/b41.0c6d7432.png",Me="/assets/b42.66cc353b.png",Ue="/assets/b43.a775b641.png",Ge="/assets/b44.2d540844.png",De="/assets/b45.fe0240c6.png",Fe="/assets/b46.f6b9da14.png",Je=JSON.parse('{"title":"Android Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_android.md","filePath":"en/guide/pve/pve_android.md","lastUpdated":1747972048000}'),Be={name:"en/guide/pve/pve_android.md"},Ke=s('

Android Virtual Machine

Android System Image Download

Download links for Android system version 9 and earlier:

International

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

Domestic (China)

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Download links for Android system version 10 and later:

https://blissos.org/index.html#download

Virtual Machine Setup

Setting up an Android Virtual Machine with version 9 and earlier images

This guide demonstrates using:

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

as an example

1

Template Configuration

Create a virtual machine with VMID 100 and select the corresponding storage disk

2

Select the Android image, then choose Linux for Type and choose an option with version 2.6 for Version

3

Select Vmware compatible for Graphic card, other options are default as shown

4

Choose SATA for disk format, allocate at least 30GB of disk space (size can be chosen based on your needs)

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface

9

System Installation

After entering the boot menu, select the option starting with Installation

10

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it

11

Choose not to use GPT format

12

When the empty disk is displayed, select New

13

Select partition type Primary

14

Then you'll be prompted to specify the size of the space. Just press Enter to use all available space

15

Then select Flags, move to Bootable, press Enter until Boot appears under Flags

16

Then move to Write and press Enter to write changes

17

You'll be asked to confirm whether to continue. Type yes and press Enter to continue

18

After a progress bar completes, you'll return to the initial menu. Select Quit to exit the menu, everything is now ready

19

Then you'll return to the UI interface. Use the previously initialized disk and select the OK button

20

Use the arrow keys to select ext4 file system type, then select the OK button

21

Confirm formatting by selecting the Yes button

22

Confirm GRUB boot installation by selecting the OK button

23

Confirm the file system is readable and writable by selecting the OK button

24

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button

25

After a while, you'll enter the Android logo screen

26

Removing the Image

Then there will be a black screen. If it's still black after 3-5 minutes, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

ar

Then execute qm start 100 on the host machine again, and you should enter the Android system initialization interface

System Initialization

In the initialization interface, select the language and click the confirm button

27

It will try to connect to WiFi. Since our PVE installation uses a completely static network configuration, just skip this and set it up later

31

Click the next button to confirm the time settings

32

Click to cancel screen protection, confirm to skip again

33

After a period of black screen, the main screen application selection will appear. If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine as before, and it should display after entering VNC

Select Quickstep

34

Network Settings

After entering the desktop, you need to set up the network. Click the settings icon in the upper left corner

35

A dropdown appears, click and hold to pull down

36

Click the gear button

37

Enter Network & Internet settings

38

Double-click WIFI with the left mouse button

39

Modify the detected VirtWIFI. Right-click to bring up the selection box, then click Modify network

40

Advanced options appear, click to open hidden options

41

Configure the network settings as shown

IP address 172.16.1.xxx (replace xxx with your desired IP, I used 100 because my vmid is 100 for convenience)

Subnet mask 24

Default gateway 172.16.1.1

DNS 8.8.8.8 or 144.144.144.144

Then click the save button

42

At this point, the settings may still not be applied. Turn off WiFi and then turn it back on, it should then show as connected

43

Then exit to the main interface, click on Google Chrome, and try to open a webpage

44

You can see that opening this guide's URL works without problems, proving that the network is connected

45

Setting up an Android Virtual Machine with version 10 and later images

This guide demonstrates using:

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

as an example

1

Template Configuration

The host machine needs to execute the following command to install graphics environment dependencies

shell
apt install libgl1 libegl1 -y

Then start creating the virtual machine by clicking the Create VM button in the upper right corner. Fill in VMID, Name, Resource Pool

2

Select the Android image, then choose Linux for Type and an option with version 2.6 for Version

3

If the host machine has a GPU, select VirGL GPU for Graphic card.

If the host machine doesn't have a GPU, select VirtIO or Vmware compatible for Graphic card.

Select q35 for Machine, select OVMF (UEFI) for BIOS, and select local for EFI Storage.

4

Choose SATA for disk format. How much disk space to allocate is up to you, but at least 30GB is recommended

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface.

System Installation

After entering the boot menu, select the option ending with Installation

9

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it.

10

Choose not to use GPT format, continue using cfdisk format.

11

When the format selection box appears, select gpt.

12

When the empty disk is displayed, select New.

13

Because you need to create an EFI partition, you need to change the size rather than using the default. Change the number to 1 to allocate 1GB of disk space, then press Enter.

14

Then you'll return to the menu bar. Use the arrow keys to select Type, then press Enter to choose the format type for the partition

15

Use the arrow keys to select the first option EFI System, then press Enter

16

Now you're back at the menu bar. In the upper half of the page, you can see the specific partition size and format

17

Then press the down arrow key to select the next empty partition line

18

Select New from the menu bar, then press Enter

19

Here you need to fill in the partition size. Match it with the empty partition size shown in the upper right corner, then press Enter.

20

Return to the menu bar, select Write, press Enter to write the partition.

21

You'll be prompted to enter yes to confirm. Enter it and press Enter.

22

After a progress bar runs, you should return to the menu bar. Select Quit to exit the menu, everything is now ready

23

Then you'll return to the UI interface. Use the previously initialized 1GB disk and select the OK button

24

Use the arrow keys to select fat32 file system type, then select the OK button

25

Confirm not to modify the name by selecting the OK button

26

Confirm formatting by selecting the Yes button

27

Then you'll return to the initial UI bar. Select the second partition that is not 1GB in size and select the OK button

28

Use the arrow keys to select ext4 file system type, then select the OK button

29

Confirm not to modify the name by selecting the OK button

30

Confirm formatting by selecting the Yes button

31

Choose not to use extra space for updates by selecting the No button

32

Confirm GRUB2 EFI BootLoader by selecting the OK button

33

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button.

34

System Initialization

After a while, you'll enter the logo screen.

35

After some more time, you should enter the initial Android interface. You'll see a popup and the time. Hold the left mouse button and swipe up

36

The main screen application selection will appear. Select Quickstep

If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine, and it should display after entering VNC

37

Removing the Image

After the Android interface appears, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

br

Then execute qm start 100 on the host machine again, and you should enter the system's initial interface.

Network Settings

After entering the desktop, you need to set up the network. Hold the left mouse button in the indicated position and swipe up

38

A bunch of applications will pop up. Find the one called Bliss Ethernet Manager and click to open it

39

Click to open IP Assignment, select Static type, click the OK button to confirm

40

Click to open IP Address, enter 172.16.1.xxx/24 (I used 100 for xxx because my virtual machine VMID is 100 for easy identification), click the OK button to confirm

41

Click to open Gateway Address, enter 172.16.1.1, click the OK button to confirm

42

Click to open DNS Address, enter 8.8.8.8, click the OK button to confirm

43

Then in the application interface, click Interface Up and Refresh, then press the exit key on the keyboard to exit the program

44

Open the browser in the main interface to verify that the network is working properly

45

You can see that opening this guide works without problems, the network is functioning

46

',227),Re=[Ke];function Ne(Ye,We,Le,He,je,Qe){return t(),o("div",null,Re)}const Xe=e(Be,[["render",Ne]]);export{Je as __pageData,Xe as default}; diff --git a/assets/en_guide_pve_pve_custom.md.4615a36e.js b/assets/en_guide_pve_pve_custom.md.4615a36e.js deleted file mode 100644 index ad2330377c..0000000000 --- a/assets/en_guide_pve_pve_custom.md.4615a36e.js +++ /dev/null @@ -1,30 +0,0 @@ -import{_ as s,v as e,b as a,R as o}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Customized partitions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_custom.md","filePath":"en/guide/pve/pve_custom.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_custom.md"},t=o(`

Customized partitions

Installing Proxmox VE 7 on a non-Debian system

Minimum local hardware requirements are the same as for the previous normal installation.

You need to install docker first.

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

Then use uname -m to query the architecture and use the command corresponding to the architecture

The opened PVE panel information is:

Login username and password are both root, after logging in be sure to use web SSH to change the password to avoid being blown up.

When using host SSH, be sure to log into the corresponding https://IPV4:8006 to use SSH on the web panel, do not use the host's port 22 to manipulate the PVE.

Because the SSH on the web panel is inside Docker, it does not support subsequent one-click configurations, so please configure your own gateway, etc. to use it.

X86 architecture

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_x86_64

ARM architecture

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_aarch64

The web panel is actually opened in the container, but the network has used the host mode, the port of the PVE is about the same as the port of the host used.

But here the login username and password become root and root, if you need to change it please docker exec -it pve /bin/bash enter and change the password of root, then press ctrl key and A+D to exit.

There are many bugs need to be fixed, welcome to PR to solve the problem, the actual test on the Ubuntu system host machine to install Proxmox VE panel success, solved the problem of installing Proxmox VE over the network can only be used to use the Debian system as a host machine!

Optimizing the memory footprint of Proxmox-VE on low-configuration systems

The following optimization can reduce at least 400M memory occupation, some machines can reduce more than 6GB, the actual reduction of how much memory occupation to test by yourself.

Reduce the number of max_workers

Execute the following command to query

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

you can see

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

The default max_workers is 3, you can modify the corresponding file, the minimum max_workers can be 1, you can use the following commands to modify them:

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

Deactivation of HA services

Clusters (multi-nodes) can use the HA service, if it is a single node, or there is no need for HA use, you can execute the following command:

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

Disable firewall service

The service can be deactivated by executing the following command:

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

Discontinuation of cheduler service

If you don't need scheduled tasks, such as backups and synchronizations, you can deactivate the service by executing the following command:

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

Discontinuation of Spiceproxy service

If you do not need to use Spice for VM/container linking (the Arm version itself does not support Spice), you can deactivate the service by executing the following command:

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

Deleting the memory cache using a timed task

Clearing different types of caches and performing TRIM operations on file systems

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

The above commands require the sudo and crontab commands to be available on the host itself.

Self-mapping of public ports on KVM VMs with open NATs

Use the nano or vim command to modify the file to add port mapping:

/etc/iptables/rules.v4

For example, if I have a KVM VM with an intranet IP of 172.16.1.152, and MYSQL has been set up to listen to 3306, and I need to use the tcp protocol to map out to the 33306 port on the host IP, I would add the following line to the COMMIT line in the file above, then add the following line

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

Save the file and exit file editing and then execute:

service netfilter-persistent restart

Reload Port Mapping

At this point, on the host machine, execute the

lsof -i:33306

To see if the port mapping rule is in effect

Customizing the CPU TYPE when opening a Linux virtual machine

On the host computer, use something like

shell
echo "kvm64" > /usr/local/bin/cpu_type

Specifying the default CPU TYPE in this way allows you to replace kvm64 with the type you want

`,57),l=[t];function p(c,i,r,d,h,u){return e(),a("div",null,l)}const C=s(n,[["render",p]]);export{y as __pageData,C as default}; diff --git a/assets/en_guide_pve_pve_custom.md.4615a36e.lean.js b/assets/en_guide_pve_pve_custom.md.4615a36e.lean.js deleted file mode 100644 index ad2330377c..0000000000 --- a/assets/en_guide_pve_pve_custom.md.4615a36e.lean.js +++ /dev/null @@ -1,30 +0,0 @@ -import{_ as s,v as e,b as a,R as o}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"Customized partitions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_custom.md","filePath":"en/guide/pve/pve_custom.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_custom.md"},t=o(`

Customized partitions

Installing Proxmox VE 7 on a non-Debian system

Minimum local hardware requirements are the same as for the previous normal installation.

You need to install docker first.

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

Then use uname -m to query the architecture and use the command corresponding to the architecture

The opened PVE panel information is:

Login username and password are both root, after logging in be sure to use web SSH to change the password to avoid being blown up.

When using host SSH, be sure to log into the corresponding https://IPV4:8006 to use SSH on the web panel, do not use the host's port 22 to manipulate the PVE.

Because the SSH on the web panel is inside Docker, it does not support subsequent one-click configurations, so please configure your own gateway, etc. to use it.

X86 architecture

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_x86_64

ARM architecture

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_aarch64

The web panel is actually opened in the container, but the network has used the host mode, the port of the PVE is about the same as the port of the host used.

But here the login username and password become root and root, if you need to change it please docker exec -it pve /bin/bash enter and change the password of root, then press ctrl key and A+D to exit.

There are many bugs need to be fixed, welcome to PR to solve the problem, the actual test on the Ubuntu system host machine to install Proxmox VE panel success, solved the problem of installing Proxmox VE over the network can only be used to use the Debian system as a host machine!

Optimizing the memory footprint of Proxmox-VE on low-configuration systems

The following optimization can reduce at least 400M memory occupation, some machines can reduce more than 6GB, the actual reduction of how much memory occupation to test by yourself.

Reduce the number of max_workers

Execute the following command to query

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

you can see

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

The default max_workers is 3, you can modify the corresponding file, the minimum max_workers can be 1, you can use the following commands to modify them:

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

Deactivation of HA services

Clusters (multi-nodes) can use the HA service, if it is a single node, or there is no need for HA use, you can execute the following command:

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

Disable firewall service

The service can be deactivated by executing the following command:

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

Discontinuation of cheduler service

If you don't need scheduled tasks, such as backups and synchronizations, you can deactivate the service by executing the following command:

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

Discontinuation of Spiceproxy service

If you do not need to use Spice for VM/container linking (the Arm version itself does not support Spice), you can deactivate the service by executing the following command:

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

Deleting the memory cache using a timed task

Clearing different types of caches and performing TRIM operations on file systems

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

The above commands require the sudo and crontab commands to be available on the host itself.

Self-mapping of public ports on KVM VMs with open NATs

Use the nano or vim command to modify the file to add port mapping:

/etc/iptables/rules.v4

For example, if I have a KVM VM with an intranet IP of 172.16.1.152, and MYSQL has been set up to listen to 3306, and I need to use the tcp protocol to map out to the 33306 port on the host IP, I would add the following line to the COMMIT line in the file above, then add the following line

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

Save the file and exit file editing and then execute:

service netfilter-persistent restart

Reload Port Mapping

At this point, on the host machine, execute the

lsof -i:33306

To see if the port mapping rule is in effect

Customizing the CPU TYPE when opening a Linux virtual machine

On the host computer, use something like

shell
echo "kvm64" > /usr/local/bin/cpu_type

Specifying the default CPU TYPE in this way allows you to replace kvm64 with the type you want

`,57),l=[t];function p(c,i,r,d,h,u){return e(),a("div",null,l)}const C=s(n,[["render",p]]);export{y as __pageData,C as default}; diff --git a/assets/en_guide_pve_pve_custom.md.BNwEwNPy.js b/assets/en_guide_pve_pve_custom.md.BNwEwNPy.js new file mode 100644 index 0000000000..49ae5026d3 --- /dev/null +++ b/assets/en_guide_pve_pve_custom.md.BNwEwNPy.js @@ -0,0 +1,30 @@ +import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Customized partitions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_custom.md","filePath":"en/guide/pve/pve_custom.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_custom.md"};function o(p,s,l,h,c,r){return i(),a("div",null,s[0]||(s[0]=[t(`

Customized partitions

Installing Proxmox VE 7 on a non-Debian system

Minimum local hardware requirements are the same as for the previous normal installation.

You need to install docker first.

curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

Then use uname -m to query the architecture and use the command corresponding to the architecture

The opened PVE panel information is:

Login username and password are both root, after logging in be sure to use web SSH to change the password to avoid being blown up.

When using host SSH, be sure to log into the corresponding https://IPV4:8006 to use SSH on the web panel, do not use the host's port 22 to manipulate the PVE.

Because the SSH on the web panel is inside Docker, it does not support subsequent one-click configurations, so please configure your own gateway, etc. to use it.

X86 architecture

bash
docker run -idt --network host \\
+--privileged \\
+--name pve \\
+--add-host pve:10.13.14.101 \\
+--hostname pve \\
+spiritlhl/pve:7_x86_64

ARM architecture

bash
docker run -idt --network host \\
+--privileged \\
+--name pve \\
+--add-host pve:10.13.14.101 \\
+--hostname pve \\
+spiritlhl/pve:7_aarch64

The web panel is actually opened in the container, but the network has used the host mode, the port of the PVE is about the same as the port of the host used.

But here the login username and password become root and root, if you need to change it please docker exec -it pve /bin/bash enter and change the password of root, then press ctrl key and A+D to exit.

There are many bugs need to be fixed, welcome to PR to solve the problem, the actual test on the Ubuntu system host machine to install Proxmox VE panel success, solved the problem of installing Proxmox VE over the network can only be used to use the Debian system as a host machine!

Optimizing the memory footprint of Proxmox-VE on low-configuration systems

The following optimization can reduce at least 400M memory occupation, some machines can reduce more than 6GB, the actual reduction of how much memory occupation to test by yourself.

Reduce the number of max_workers

Execute the following command to query

cd /usr/share/perl5/PVE/Service
+grep 'max_workers => 3' *

you can see

pvedaemon.pm:    max_workers => 3,
+pveproxy.pm:    max_workers => 3,
+spiceproxy.pm:    max_workers => 3, # todo: do we need more?

The default max_workers is 3, you can modify the corresponding file, the minimum max_workers can be 1, you can use the following commands to modify them:

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

Deactivation of HA services

Clusters (multi-nodes) can use the HA service, if it is a single node, or there is no need for HA use, you can execute the following command:

systemctl stop pve-ha-lrm.service 
+systemctl stop pve-ha-crm.service 
+systemctl disable pve-ha-lrm.service 
+systemctl disable pve-ha-crm.service

Disable firewall service

The service can be deactivated by executing the following command:

systemctl stop pve-firewall.service 
+systemctl disable pve-firewall.service

Discontinuation of cheduler service

If you don't need scheduled tasks, such as backups and synchronizations, you can deactivate the service by executing the following command:

systemctl stop pvescheduler.service
+systemctl disable pvescheduler.service

Discontinuation of Spiceproxy service

If you do not need to use Spice for VM/container linking (the Arm version itself does not support Spice), you can deactivate the service by executing the following command:

systemctl stop spiceproxy.service 
+systemctl disable spiceproxy.service

Deleting the memory cache using a timed task

Clearing different types of caches and performing TRIM operations on file systems

shell
TEMP_CRON=$(mktemp)
+sudo crontab -l > $TEMP_CRON
+echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
+sudo crontab $TEMP_CRON
+rm $TEMP_CRON

The above commands require the sudo and crontab commands to be available on the host itself.

Self-mapping of public ports on KVM VMs with open NATs

Use the nano or vim command to modify the file to add port mapping:

/etc/iptables/rules.v4

For example, if I have a KVM VM with an intranet IP of 172.16.1.152, and MYSQL has been set up to listen to 3306, and I need to use the tcp protocol to map out to the 33306 port on the host IP, I would add the following line to the COMMIT line in the file above, then add the following line

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

Save the file and exit file editing and then execute:

service netfilter-persistent restart

Reload Port Mapping

At this point, on the host machine, execute the

lsof -i:33306

To see if the port mapping rule is in effect

Customizing the CPU TYPE when opening a Linux virtual machine

On the host computer, use something like

shell
echo "kvm64" > /usr/local/bin/cpu_type

Specifying the default CPU TYPE in this way allows you to replace kvm64 with the type you want

`,57)]))}const u=e(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_pve_pve_custom.md.BNwEwNPy.lean.js b/assets/en_guide_pve_pve_custom.md.BNwEwNPy.lean.js new file mode 100644 index 0000000000..9c6ac9c7ae --- /dev/null +++ b/assets/en_guide_pve_pve_custom.md.BNwEwNPy.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Customized partitions","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_custom.md","filePath":"en/guide/pve/pve_custom.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_custom.md"};function o(p,s,l,h,c,r){return i(),a("div",null,s[0]||(s[0]=[t("",57)]))}const u=e(n,[["render",o]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_pve_pve_install.md.69e0d919.js b/assets/en_guide_pve_pve_install.md.69e0d919.js deleted file mode 100644 index bb54ba485f..0000000000 --- a/assets/en_guide_pve_pve_install.md.69e0d919.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"PVE Body Installation","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_install.md","filePath":"en/guide/pve/pve_install.md","lastUpdated":1747972048000}'),a={name:"en/guide/pve/pve_install.md"},n=s('

PVE Body Installation

If you don't know how to choose an option during installation, just press enter.

TIP

For low-configuration hosts, it is recommended to check the contents of the Custom partition after all the content has been installed to perform memory tuning and reduce the memory footprint.

One-click PVE installation

TIP

Suggest debian12, the actual test part of the independent server debian11 system will appear a reboot network will be lost, debian12 does not have such a problem!

  • The installation is the latest PVE from the apt source at the moment.
  • For example, debian10 is pve6.4, debian11 is pve7.x, debian12 is pve8.x
  • Changes to the /etc/hosts file (to fix the wrong hostname setting for merchants and to add the required content for PVE)
  • /etc/cloud/cloud.cfg file modification (to avoid overwriting modified hostname etc.)
  • /etc/network/interfaces file modification (fix auto, dhcp type to static, add vmbr0 gateway)
  • Detect whether it is China IP, if it is China IP use Tsinghua mirror source, otherwise use the official source, and at the same time deal with the source of apt and the corresponding nameserver, to avoid disconnections
  • Create vmbr0 (independent IP gateway), the host allows addr and gateway for intranet IP or extranet IP, has been automatically recognized
  • vmbr0 creation support to open pure IPV4, pure IPV6, dual-stack virtual machine, automatic identification of IPV4 address and IPV6 address, automatic identification of the corresponding IP interval
  • Installation of the necessary toolkit for PVE to open a virtual machine
  • x86_64 replace enterprise subscriptions in apt sources with community sources, arm sources built using third-party patches for fixes
  • Print query Linux system kernel and PVE kernel installed or not
  • Setting up DNS detection 8.8.8.8.8 for boot add DNS systemd service
  • Download PVE and printout of login information after adding APT source link for PVE

All modified files have been set to read-only mode to avoid overwriting after reboot.

If you want to modify the file, please use chattr -i file path to cancel the read-only lock, and run chattr +i file path to lock the read-only lock when you finish modifying the file.

You will be prompted to reboot your system once during the execution process, After rebooting, be sure to wait at least 20 seconds to make sure the system does not reboot automatically again.

Because the original environment may be missing ifupdown or ifupdown2 environment, there is a self-installation daemon loaded for the installation, after the installation of the system will automatically reboot the system again, wait for 20 seconds without reboot to ensure that the installation has been run.

If the host itself exists SLAAC assigned IPV6 address, will be able to choose whether to use the largest IPV6 subnet range, the default carriage return does not use the largest IPV6 subnet range only use the local IPV6, if you subsequently need to attach a separate IPV6 address to the virtual machine/container, the option must be selected y.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

or

shell
bash install_pve.sh

TIP

After successful installation, the web page may not be safe to open, click on Advanced or More Options and insist on accessing it!

The login information is your SSH account and password.

Pre-configure the environment

  • Creating a resource pool mypool
  • Remove the subscription popup
  • Attempt to enable hardware passthrough
  • Detect and auto-install AppArmor modules.
  • Before rebooting the system, it is recommended to hook up nezha probe to facilitate the use of the command line in the background without SSH, to avoid the possibility that SSH may lead to the loss of the root password after the reboot due to the merchant's strange presets.
  • Before executing reboot, you need to wait for the background task to finish executing, some host system apt command execution is very slow, you have to wait for a while to finish executing, of course, most of the machines are not so bad!

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

Automatically configure the host's gateway

WARNING

Before using this command, please make sure that you have restarted the server and that PVE can use the WEB terminal normally before executing this command. Do not execute this command immediately after restarting the machine, wait for at least 1 minute after the WEB terminal is successfully started before executing this command. If the WEB side doesn't start, run systemctl status pveproxy to see if it starts, if it's stuck, run systemctl start pveproxy to start the WEB side.

TIP

This step is most likely to cause SSH disconnections, the reason is to modify the network without waiting for the PVE kernel to start, which will result in setting conflicts, so wait at least a few minutes until the kernel is started, that is, the WEB side is started successfully before execution.

TIP

If the host needs to attach an IPV6 tunnel (add an IPV6 subnet to a host that does not have an IPV6 address) before executing this command, please check the IPV6 free subnet attachment section to attach to the corresponding configuration file, but please ignore 'initial environment modifications' and attach directly, and then execute the following one-click gateway configuration commands after verifying that you have an IPV6 address.

  • If vmbr0 is not created, it is automatically created with the same logic as the main installation
  • Create vmbr1 (NAT gateway) to support IPV4 servers that open NAT for IPV6 networks with NAT.
  • Create vmbr2 (standalone IPV6 gateway), use ndppd to solve the problem of MAC verification of IPV6 addresses by the host, support the opening of servers with standalone IPV6 networks.
  • If you want to see the complete settings, you can execute cat /etc/network/interfaces to see, if you need to modify the gateway you need to modify the file, the web site can not be modified!
  • Load iptables and set back to source and allow NAT port forwarding.

In short, vmbr0 is responsible for v4 standalone IPs, and vmbr1 is responsible for complex v4/v6 NATs, vmbr2 is responsible for v6 standalone IPs.

Open independent IPV4 virtual machine using vmbr0, gateway with the host, IPV4/CIDR using the same network segment address and the same subnet mask, using the host's unbound IPV4 address for IPV4/CIDR, of course, if the subsequent use of this script does not need to pay attention to this point of the nuances of the thing

Use vmbr1 for IPV4 VM with NAT, 172.16.1.1 for gateway, 172.16.1.x/24 for IPV4/CIDR, where x can't be 1, but of course you don't need to pay attention to this minutia if you use this script later.

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

This step may require you to reboot your system after a few minutes of successful execution, see the final execution of the script at the end of the tip. However, a reboot will ensure that some of the hidden settings are loaded successfully, so be sure to reboot the server once if you are in a position to do so.

',32),i=[n];function l(r,c,p,d,h,u){return t(),o("div",null,i)}const y=e(a,[["render",l]]);export{f as __pageData,y as default}; diff --git a/assets/en_guide_pve_pve_install.md.69e0d919.lean.js b/assets/en_guide_pve_pve_install.md.69e0d919.lean.js deleted file mode 100644 index bb54ba485f..0000000000 --- a/assets/en_guide_pve_pve_install.md.69e0d919.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as o,R as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"PVE Body Installation","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_install.md","filePath":"en/guide/pve/pve_install.md","lastUpdated":1747972048000}'),a={name:"en/guide/pve/pve_install.md"},n=s('

PVE Body Installation

If you don't know how to choose an option during installation, just press enter.

TIP

For low-configuration hosts, it is recommended to check the contents of the Custom partition after all the content has been installed to perform memory tuning and reduce the memory footprint.

One-click PVE installation

TIP

Suggest debian12, the actual test part of the independent server debian11 system will appear a reboot network will be lost, debian12 does not have such a problem!

  • The installation is the latest PVE from the apt source at the moment.
  • For example, debian10 is pve6.4, debian11 is pve7.x, debian12 is pve8.x
  • Changes to the /etc/hosts file (to fix the wrong hostname setting for merchants and to add the required content for PVE)
  • /etc/cloud/cloud.cfg file modification (to avoid overwriting modified hostname etc.)
  • /etc/network/interfaces file modification (fix auto, dhcp type to static, add vmbr0 gateway)
  • Detect whether it is China IP, if it is China IP use Tsinghua mirror source, otherwise use the official source, and at the same time deal with the source of apt and the corresponding nameserver, to avoid disconnections
  • Create vmbr0 (independent IP gateway), the host allows addr and gateway for intranet IP or extranet IP, has been automatically recognized
  • vmbr0 creation support to open pure IPV4, pure IPV6, dual-stack virtual machine, automatic identification of IPV4 address and IPV6 address, automatic identification of the corresponding IP interval
  • Installation of the necessary toolkit for PVE to open a virtual machine
  • x86_64 replace enterprise subscriptions in apt sources with community sources, arm sources built using third-party patches for fixes
  • Print query Linux system kernel and PVE kernel installed or not
  • Setting up DNS detection 8.8.8.8.8 for boot add DNS systemd service
  • Download PVE and printout of login information after adding APT source link for PVE

All modified files have been set to read-only mode to avoid overwriting after reboot.

If you want to modify the file, please use chattr -i file path to cancel the read-only lock, and run chattr +i file path to lock the read-only lock when you finish modifying the file.

You will be prompted to reboot your system once during the execution process, After rebooting, be sure to wait at least 20 seconds to make sure the system does not reboot automatically again.

Because the original environment may be missing ifupdown or ifupdown2 environment, there is a self-installation daemon loaded for the installation, after the installation of the system will automatically reboot the system again, wait for 20 seconds without reboot to ensure that the installation has been run.

If the host itself exists SLAAC assigned IPV6 address, will be able to choose whether to use the largest IPV6 subnet range, the default carriage return does not use the largest IPV6 subnet range only use the local IPV6, if you subsequently need to attach a separate IPV6 address to the virtual machine/container, the option must be selected y.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

or

shell
bash install_pve.sh

TIP

After successful installation, the web page may not be safe to open, click on Advanced or More Options and insist on accessing it!

The login information is your SSH account and password.

Pre-configure the environment

  • Creating a resource pool mypool
  • Remove the subscription popup
  • Attempt to enable hardware passthrough
  • Detect and auto-install AppArmor modules.
  • Before rebooting the system, it is recommended to hook up nezha probe to facilitate the use of the command line in the background without SSH, to avoid the possibility that SSH may lead to the loss of the root password after the reboot due to the merchant's strange presets.
  • Before executing reboot, you need to wait for the background task to finish executing, some host system apt command execution is very slow, you have to wait for a while to finish executing, of course, most of the machines are not so bad!

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

Automatically configure the host's gateway

WARNING

Before using this command, please make sure that you have restarted the server and that PVE can use the WEB terminal normally before executing this command. Do not execute this command immediately after restarting the machine, wait for at least 1 minute after the WEB terminal is successfully started before executing this command. If the WEB side doesn't start, run systemctl status pveproxy to see if it starts, if it's stuck, run systemctl start pveproxy to start the WEB side.

TIP

This step is most likely to cause SSH disconnections, the reason is to modify the network without waiting for the PVE kernel to start, which will result in setting conflicts, so wait at least a few minutes until the kernel is started, that is, the WEB side is started successfully before execution.

TIP

If the host needs to attach an IPV6 tunnel (add an IPV6 subnet to a host that does not have an IPV6 address) before executing this command, please check the IPV6 free subnet attachment section to attach to the corresponding configuration file, but please ignore 'initial environment modifications' and attach directly, and then execute the following one-click gateway configuration commands after verifying that you have an IPV6 address.

  • If vmbr0 is not created, it is automatically created with the same logic as the main installation
  • Create vmbr1 (NAT gateway) to support IPV4 servers that open NAT for IPV6 networks with NAT.
  • Create vmbr2 (standalone IPV6 gateway), use ndppd to solve the problem of MAC verification of IPV6 addresses by the host, support the opening of servers with standalone IPV6 networks.
  • If you want to see the complete settings, you can execute cat /etc/network/interfaces to see, if you need to modify the gateway you need to modify the file, the web site can not be modified!
  • Load iptables and set back to source and allow NAT port forwarding.

In short, vmbr0 is responsible for v4 standalone IPs, and vmbr1 is responsible for complex v4/v6 NATs, vmbr2 is responsible for v6 standalone IPs.

Open independent IPV4 virtual machine using vmbr0, gateway with the host, IPV4/CIDR using the same network segment address and the same subnet mask, using the host's unbound IPV4 address for IPV4/CIDR, of course, if the subsequent use of this script does not need to pay attention to this point of the nuances of the thing

Use vmbr1 for IPV4 VM with NAT, 172.16.1.1 for gateway, 172.16.1.x/24 for IPV4/CIDR, where x can't be 1, but of course you don't need to pay attention to this minutia if you use this script later.

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

This step may require you to reboot your system after a few minutes of successful execution, see the final execution of the script at the end of the tip. However, a reboot will ensure that some of the hidden settings are loaded successfully, so be sure to reboot the server once if you are in a position to do so.

',32),i=[n];function l(r,c,p,d,h,u){return t(),o("div",null,i)}const y=e(a,[["render",l]]);export{f as __pageData,y as default}; diff --git a/assets/en_guide_pve_pve_install.md.DG8IYoZ0.js b/assets/en_guide_pve_pve_install.md.DG8IYoZ0.js new file mode 100644 index 0000000000..550e310d65 --- /dev/null +++ b/assets/en_guide_pve_pve_install.md.DG8IYoZ0.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"PVE Body Installation","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_install.md","filePath":"en/guide/pve/pve_install.md","lastUpdated":1747984962000}'),o={name:"en/guide/pve/pve_install.md"};function n(l,e,r,h,c,d){return s(),i("div",null,e[0]||(e[0]=[a('

PVE Body Installation

If you don't know how to choose an option during installation, just press enter.

TIP

For low-configuration hosts, it is recommended to check the contents of the Custom partition after all the content has been installed to perform memory tuning and reduce the memory footprint.

One-click PVE installation

TIP

Suggest debian12, the actual test part of the independent server debian11 system will appear a reboot network will be lost, debian12 does not have such a problem!

  • The installation is the latest PVE from the apt source at the moment.
  • For example, debian10 is pve6.4, debian11 is pve7.x, debian12 is pve8.x
  • Changes to the /etc/hosts file (to fix the wrong hostname setting for merchants and to add the required content for PVE)
  • /etc/cloud/cloud.cfg file modification (to avoid overwriting modified hostname etc.)
  • /etc/network/interfaces file modification (fix auto, dhcp type to static, add vmbr0 gateway)
  • Detect whether it is China IP, if it is China IP use Tsinghua mirror source, otherwise use the official source, and at the same time deal with the source of apt and the corresponding nameserver, to avoid disconnections
  • Create vmbr0 (independent IP gateway), the host allows addr and gateway for intranet IP or extranet IP, has been automatically recognized
  • vmbr0 creation support to open pure IPV4, pure IPV6, dual-stack virtual machine, automatic identification of IPV4 address and IPV6 address, automatic identification of the corresponding IP interval
  • Installation of the necessary toolkit for PVE to open a virtual machine
  • x86_64 replace enterprise subscriptions in apt sources with community sources, arm sources built using third-party patches for fixes
  • Print query Linux system kernel and PVE kernel installed or not
  • Setting up DNS detection 8.8.8.8.8 for boot add DNS systemd service
  • Download PVE and printout of login information after adding APT source link for PVE

All modified files have been set to read-only mode to avoid overwriting after reboot.

If you want to modify the file, please use chattr -i file path to cancel the read-only lock, and run chattr +i file path to lock the read-only lock when you finish modifying the file.

You will be prompted to reboot your system once during the execution process, After rebooting, be sure to wait at least 20 seconds to make sure the system does not reboot automatically again.

Because the original environment may be missing ifupdown or ifupdown2 environment, there is a self-installation daemon loaded for the installation, after the installation of the system will automatically reboot the system again, wait for 20 seconds without reboot to ensure that the installation has been run.

If the host itself exists SLAAC assigned IPV6 address, will be able to choose whether to use the largest IPV6 subnet range, the default carriage return does not use the largest IPV6 subnet range only use the local IPV6, if you subsequently need to attach a separate IPV6 address to the virtual machine/container, the option must be selected y.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

or

shell
bash install_pve.sh

TIP

After successful installation, the web page may not be safe to open, click on Advanced or More Options and insist on accessing it!

The login information is your SSH account and password.

Pre-configure the environment

  • Creating a resource pool mypool
  • Remove the subscription popup
  • Attempt to enable hardware passthrough
  • Detect and auto-install AppArmor modules.
  • Before rebooting the system, it is recommended to hook up nezha probe to facilitate the use of the command line in the background without SSH, to avoid the possibility that SSH may lead to the loss of the root password after the reboot due to the merchant's strange presets.
  • Before executing reboot, you need to wait for the background task to finish executing, some host system apt command execution is very slow, you have to wait for a while to finish executing, of course, most of the machines are not so bad!

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

Automatically configure the host's gateway

WARNING

Before using this command, please make sure that you have restarted the server and that PVE can use the WEB terminal normally before executing this command. Do not execute this command immediately after restarting the machine, wait for at least 1 minute after the WEB terminal is successfully started before executing this command. If the WEB side doesn't start, run systemctl status pveproxy to see if it starts, if it's stuck, run systemctl start pveproxy to start the WEB side.

TIP

This step is most likely to cause SSH disconnections, the reason is to modify the network without waiting for the PVE kernel to start, which will result in setting conflicts, so wait at least a few minutes until the kernel is started, that is, the WEB side is started successfully before execution.

TIP

If the host needs to attach an IPV6 tunnel (add an IPV6 subnet to a host that does not have an IPV6 address) before executing this command, please check the IPV6 free subnet attachment section to attach to the corresponding configuration file, but please ignore 'initial environment modifications' and attach directly, and then execute the following one-click gateway configuration commands after verifying that you have an IPV6 address.

  • If vmbr0 is not created, it is automatically created with the same logic as the main installation
  • Create vmbr1 (NAT gateway) to support IPV4 servers that open NAT for IPV6 networks with NAT.
  • Create vmbr2 (standalone IPV6 gateway), use ndppd to solve the problem of MAC verification of IPV6 addresses by the host, support the opening of servers with standalone IPV6 networks.
  • If you want to see the complete settings, you can execute cat /etc/network/interfaces to see, if you need to modify the gateway you need to modify the file, the web site can not be modified!
  • Load iptables and set back to source and allow NAT port forwarding.

In short, vmbr0 is responsible for v4 standalone IPs, and vmbr1 is responsible for complex v4/v6 NATs, vmbr2 is responsible for v6 standalone IPs.

Open independent IPV4 virtual machine using vmbr0, gateway with the host, IPV4/CIDR using the same network segment address and the same subnet mask, using the host's unbound IPV4 address for IPV4/CIDR, of course, if the subsequent use of this script does not need to pay attention to this point of the nuances of the thing

Use vmbr1 for IPV4 VM with NAT, 172.16.1.1 for gateway, 172.16.1.x/24 for IPV4/CIDR, where x can't be 1, but of course you don't need to pay attention to this minutia if you use this script later.

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

This step may require you to reboot your system after a few minutes of successful execution, see the final execution of the script at the end of the tip. However, a reboot will ensure that some of the hidden settings are loaded successfully, so be sure to reboot the server once if you are in a position to do so.

',32)]))}const m=t(o,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_pve_pve_install.md.DG8IYoZ0.lean.js b/assets/en_guide_pve_pve_install.md.DG8IYoZ0.lean.js new file mode 100644 index 0000000000..82074d9e48 --- /dev/null +++ b/assets/en_guide_pve_pve_install.md.DG8IYoZ0.lean.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"PVE Body Installation","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_install.md","filePath":"en/guide/pve/pve_install.md","lastUpdated":1747984962000}'),o={name:"en/guide/pve/pve_install.md"};function n(l,e,r,h,c,d){return s(),i("div",null,e[0]||(e[0]=[a("",32)]))}const m=t(o,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/en_guide_pve_pve_kvm.md.97ca4d66.js b/assets/en_guide_pve_pve_kvm.md.97ca4d66.js deleted file mode 100644 index 1eb640e798..0000000000 --- a/assets/en_guide_pve_pve_kvm.md.97ca4d66.js +++ /dev/null @@ -1,15 +0,0 @@ -import{_ as s,v as a,b as e,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"Linux Virtual Machine (KVM/TCG Virtualization)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_kvm.md","filePath":"en/guide/pve/pve_kvm.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_kvm.md"},o=t(`

Linux Virtual Machine (KVM/TCG Virtualization)

SSH Login Instructions

When open a virtual machine, the default generated username can be something other than root, in which case you need to run sudo -i to switch to root!

If the default username is not root, the default unset root password is password or oneclickvirt.

After logging into SSH and switching to root privileges, be sure to change the root password, which can be changed using the following command:

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

Considerations for opening a virtual machine with an IPV6 address

Due to long-term inactivity IPV6 does not use may lead to NDP broadcast cache invalidation reset, generally idle for about 50 minutes will appear IPV6 unavailable, commonly known as "IPV6 cutoff", at this time it is necessary to set up a timer task.

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

Executing the above commands in the opened virtual machine ensures that the IPV6 network is always used and does not fail over.

Images available for creating virtual machines

  • Pre-installed with cloud-init enabled.
  • Enabled SSH login.
  • Pre-configured SSH to listen on ports 22 for both IPv4 and IPv6.
  • Enabled password authentication for login.
  • Enabled root login.
  • Partially pre-installed QEMU guest agent.

The list of currently available image names is as follows:

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

and

https://github.com/oneclickvirt/pve_kvm_images

Daily patch images stored in the Release of this repository.

Virtual machines with standalone NAT configuration.

  • Automatically deploy NAT servers with the default Debian 10 image, chosen for its minimal footprint.
  • It's possible to customize the image used through the command, and pre-configured images are available. These images come with storage settings ranging from 2 to 10 GB of disk space. For regular use, at least 10 GB of disk space is recommended. You can increase the disk size if certain images fail to start.
  • The command allows for specifying the storage disk location. When not specified, it defaults to the local disk, which is the system disk. It can also be set to a mount disk as displayed in PVE.
  • Recommended custom memory size is 512 MB.
  • Automatic internal and external port mapping, including ports 22, 80, 443, and 25 other port numbers shared between internal and external networks.
  • After generation, there's a wait time for the virtual machine's internal cloud-init configuration to establish network and login information. This process takes approximately 5 minutes.
  • Pertinent virtual machine information will be stored in the NOTES section of the corresponding VM on the web interface, accessible for viewing through the web portal.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically added. However, there won't be any public IPV6 addresses.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

System Support:

  • For x86_64 architecture systems listed in this link, simply use the filename without the .qcow2 extension when using.
  • For arm architecture systems listed at this link, use the system name and version number, such as ubuntu20 or ubuntu22.

TIP

Note that usernames consisting of only numbers may cause issues with cloud-init. It's preferable to use usernames that are entirely in English or start with an English character.

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

Meaning of each parameter

shell
# ./buildvm.sh VMID Username Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Public_Port_Start Public_Port_End System Storage_Disk Independent_IPV6_address(leave default N blank)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

After setup is completed, you can execute cat vm111 to view the information or check the NOTES section for the corresponding VM on the WEB interface.

Below is the information for the example VM that has been set up:

AttributeValue
VMID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size10G
SSH Port40001
Port 8040002
Port 44340003
Port Range for NAT50000 to 50025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific VM

  • Stop VM
  • Delete VM
  • Delete port mapping
  • Restart network
  • Delete log files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the VM with the corresponding VMID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each VMID, and more than one can be deleted at a time.

Batch Creation of Virtual Machines with NAT

WARNING

Before initial use, ensure that the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port forwarding, as conflicting settings may result in bugs.

TIP

Before initiating the batch creation process, please use the 'screen' command to execute it in the background. This will help avoid interruptions due to the instability of SSH caused by extended batch creation times.

  • The batch creation process can be run multiple times to generate multiple virtual machines (VMs).
  • NAT servers are automatically created during the process. If left blank, the default Debian 11 image will be used. You can also customize the image name. Refer to the list of supported images in the previous section.
  • Automatic internal and external port mapping is performed, including ports 22, 80, 443, and other ports with identical internal and external numbers (25 ports in total).
  • After generation, a waiting period is required for the cloud-init configuration of the VM's network and login information to be set up. This process takes approximately 5 minutes. There is a 60-second interval between creating each VM to avoid potential performance issues.
  • The default network configuration for VMs created in batches includes port mappings for ports 22, 80, 443, and a range of 25 ports for internal and external communication.
  • You can customize the number of CPU cores, memory size, disk size, and which storage disk on the host machine to use for batch creation. Ensure you calculate available resources before proceeding.
  • Relevant information about the virtual machines will be stored in the 'NOTES' section of the corresponding VM on the web interface, where you can view them.
  • If the host machine comes with an IPv6 subnet, an IPv6 network will be automatically attached, although there will be no public IPv6 addresses available.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

After the setup is completed, you can execute cat vmlog to view the information, or check the NOTES in the corresponding VM on the web interface.

Delete All Virtual Machines

  • Delete all VMs
  • Delete all NAT port mappings
  • Restart the network
  • Delete log files
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

Before modifying the VM configuration for PVE, you must shut it down first. After making the configuration changes, start it again to avoid configuration reload errors.

Setting Up Virtual Machines with Dedicated IPv4 Addresses

Three scripts, each with its own advantages and disadvantages.

The first two scripts don't require an additional IPV4 address to be bound to the vmbr0 interface beforehand, and the opened VM will directly bind the additional IPV4 address.

The last script requires additional IPV4 addresses to be bound to the vmbr0 interface beforehand, and the opened VM will do NAT full port mapping to the intranet IPV4 address, **without directly binding additional IPV4 addresses.

Automatically selects additional IPV4 addresses on the same subnet as the host machine to open the virtual machine

WARNING

Before use, ensure that the current host machine has at least 2 available IP addresses within its IP range, and there are unallocated IP addresses. These unallocated IP addresses should not be bound to the host machine.

TIP

At this point, the IPV4 address appended is the address following the host's current IPV4 address in sequence. For example, if the current host address is 1.1.1.32 and then 1.1.1.33 there is already a virtual machine, then this script appends an IP address of 1.1.1.34.

  • Automatically detect available IP ranges. Use ping to identify unallocated IP addresses and select one to bind to the virtual machine.
  • If the host machine has an accompanying IPv6 subnet, there will be an option to attach an IPv6 address.
  • Relevant system information will be stored in the corresponding virtual machine's NOTE section, accessible for viewing on the web interface.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • The automatically appended IPV4 address is within the same subnet as the host's IPV4 address (IP address prefix is the same)
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

Meaning of each parameter

shell
# ./buildvm_extra_ip.sh VMID Username Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB OS Storage_Disk Attach_IPV6(Default is N)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

The above command is used to create a virtual machine with a dedicated IPv4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
OSdebian12
Storagelocal disk
IPv6 AddonNot attached by default

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Manually Assign Additional IPV4 Addresses to Open Virtual Machines

  • Manual specification of IPV4 address with subnet length in the command is required.
  • If the host machine comes with an IPV6 subnet, you can choose whether to add an IPV6 address additionally.
  • If the vendor has provided an IPV4 address and subnet length, please carefully compare and write the parameters in the command format shown below.
  • Relevant system information will be stored in the NOTE of the corresponding virtual machine and can be viewed on the WEB end.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • Manually appended IPV4 addresses that are in different subnets from the host's IPV4 address (different IP address prefixes) will use the host's IP address as the gateway
  • Manually appended IPV4 addresses that are within the same subnet as the host's IPV4 address (same IP address prefix) will use the host's gateway as the gateway
  • Optionally specify the MAC address of the virtual machine
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

TIP

If IP addresses within different subnets are appended without a MAC address, the router will not recognize the source MAC address, and the traffic will be flagged as “misuse” and “may” cause the server to be blocked. (If you are using a Hetzner standalone server, it is recommended that you provide the MAC address of the attached IPV4 address to prevent abuse from being reported.)

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

Meaning of each parameter

shell
# ./buildvm_manual_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N) MAC_ADDRESS(Optional whether to specify)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
Subnet/24 Subnet
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Host manually appends an additional IPV4 address and then specifies the IPV4 address to open the virtual machine

  • You need to add the extra IPV4 address to vmbr0 in /etc/network/interfaces (note that chattr -i unlocks the file and then chattr +i locks it back).
  • Other features are similar to opening a NAT-enabled VM, except that here the mapping is no longer partial port mapping or mapping to the host's IPV4 address, but full-port one-by-one mapping to additional IPV4 addresses
  • Traffic coming into the VM from outside the VM goes to the bound additional IPV4 address, and traffic going out of the VM goes to the original host's IPV4 address

TIP

Make sure you can SSH into the host with the extra IPV4 address before opening, but curl ip.sb still shows the original host IPV4 address.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

Meaning of each parameter

shell
# ./buildvm_fullnat_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Incoming and outgoing traffic goes to the bound IPV4 address

execute

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

This will cause the host to lose the ability to open VMs/containers with NAT that do not have a separate IPV4 address, so be careful!

After this, You will only be able to open VMs with separate IPV4 addresses.

Creating Virtual Machines with Pure IPv6 Addresses

The prerequisite is that the host provides an IPv6 subnet instead of just a standalone IPv6 address, and the host does not have MAC address verification enabled.

Automatic Selection of IPv6 Addresses without Manual Specification

  • Pure IPV6 refers to a bound public IPV6 address, where the actual VM still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address, based on the virtual machine's number, to the virtual machine.
  • System-related information will be stored in the NOTES section of the respective virtual machine, accessible for viewing on the web interface.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

Meaning of each parameter

shell
# ./buildvm_onlyv6.sh VMID username password CPU_cores memory_GB disk_GB operating_system storage_disk

TIP

Note that the password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

The above command is used to create a virtual machine with only IPv6 addresses.

ParameterValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage Disklocal

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Delete Example vm152

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
`,122),l=[o];function i(r,p,c,d,h,u){return a(),e("div",null,l)}const y=s(n,[["render",i]]);export{m as __pageData,y as default}; diff --git a/assets/en_guide_pve_pve_kvm.md.97ca4d66.lean.js b/assets/en_guide_pve_pve_kvm.md.97ca4d66.lean.js deleted file mode 100644 index 1eb640e798..0000000000 --- a/assets/en_guide_pve_pve_kvm.md.97ca4d66.lean.js +++ /dev/null @@ -1,15 +0,0 @@ -import{_ as s,v as a,b as e,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"Linux Virtual Machine (KVM/TCG Virtualization)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_kvm.md","filePath":"en/guide/pve/pve_kvm.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_kvm.md"},o=t(`

Linux Virtual Machine (KVM/TCG Virtualization)

SSH Login Instructions

When open a virtual machine, the default generated username can be something other than root, in which case you need to run sudo -i to switch to root!

If the default username is not root, the default unset root password is password or oneclickvirt.

After logging into SSH and switching to root privileges, be sure to change the root password, which can be changed using the following command:

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

Considerations for opening a virtual machine with an IPV6 address

Due to long-term inactivity IPV6 does not use may lead to NDP broadcast cache invalidation reset, generally idle for about 50 minutes will appear IPV6 unavailable, commonly known as "IPV6 cutoff", at this time it is necessary to set up a timer task.

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

Executing the above commands in the opened virtual machine ensures that the IPV6 network is always used and does not fail over.

Images available for creating virtual machines

  • Pre-installed with cloud-init enabled.
  • Enabled SSH login.
  • Pre-configured SSH to listen on ports 22 for both IPv4 and IPv6.
  • Enabled password authentication for login.
  • Enabled root login.
  • Partially pre-installed QEMU guest agent.

The list of currently available image names is as follows:

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

and

https://github.com/oneclickvirt/pve_kvm_images

Daily patch images stored in the Release of this repository.

Virtual machines with standalone NAT configuration.

  • Automatically deploy NAT servers with the default Debian 10 image, chosen for its minimal footprint.
  • It's possible to customize the image used through the command, and pre-configured images are available. These images come with storage settings ranging from 2 to 10 GB of disk space. For regular use, at least 10 GB of disk space is recommended. You can increase the disk size if certain images fail to start.
  • The command allows for specifying the storage disk location. When not specified, it defaults to the local disk, which is the system disk. It can also be set to a mount disk as displayed in PVE.
  • Recommended custom memory size is 512 MB.
  • Automatic internal and external port mapping, including ports 22, 80, 443, and 25 other port numbers shared between internal and external networks.
  • After generation, there's a wait time for the virtual machine's internal cloud-init configuration to establish network and login information. This process takes approximately 5 minutes.
  • Pertinent virtual machine information will be stored in the NOTES section of the corresponding VM on the web interface, accessible for viewing through the web portal.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically added. However, there won't be any public IPV6 addresses.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

System Support:

  • For x86_64 architecture systems listed in this link, simply use the filename without the .qcow2 extension when using.
  • For arm architecture systems listed at this link, use the system name and version number, such as ubuntu20 or ubuntu22.

TIP

Note that usernames consisting of only numbers may cause issues with cloud-init. It's preferable to use usernames that are entirely in English or start with an English character.

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

Meaning of each parameter

shell
# ./buildvm.sh VMID Username Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Public_Port_Start Public_Port_End System Storage_Disk Independent_IPV6_address(leave default N blank)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

After setup is completed, you can execute cat vm111 to view the information or check the NOTES section for the corresponding VM on the WEB interface.

Below is the information for the example VM that has been set up:

AttributeValue
VMID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size10G
SSH Port40001
Port 8040002
Port 44340003
Port Range for NAT50000 to 50025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific VM

  • Stop VM
  • Delete VM
  • Delete port mapping
  • Restart network
  • Delete log files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the VM with the corresponding VMID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each VMID, and more than one can be deleted at a time.

Batch Creation of Virtual Machines with NAT

WARNING

Before initial use, ensure that the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port forwarding, as conflicting settings may result in bugs.

TIP

Before initiating the batch creation process, please use the 'screen' command to execute it in the background. This will help avoid interruptions due to the instability of SSH caused by extended batch creation times.

  • The batch creation process can be run multiple times to generate multiple virtual machines (VMs).
  • NAT servers are automatically created during the process. If left blank, the default Debian 11 image will be used. You can also customize the image name. Refer to the list of supported images in the previous section.
  • Automatic internal and external port mapping is performed, including ports 22, 80, 443, and other ports with identical internal and external numbers (25 ports in total).
  • After generation, a waiting period is required for the cloud-init configuration of the VM's network and login information to be set up. This process takes approximately 5 minutes. There is a 60-second interval between creating each VM to avoid potential performance issues.
  • The default network configuration for VMs created in batches includes port mappings for ports 22, 80, 443, and a range of 25 ports for internal and external communication.
  • You can customize the number of CPU cores, memory size, disk size, and which storage disk on the host machine to use for batch creation. Ensure you calculate available resources before proceeding.
  • Relevant information about the virtual machines will be stored in the 'NOTES' section of the corresponding VM on the web interface, where you can view them.
  • If the host machine comes with an IPv6 subnet, an IPv6 network will be automatically attached, although there will be no public IPv6 addresses available.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

After the setup is completed, you can execute cat vmlog to view the information, or check the NOTES in the corresponding VM on the web interface.

Delete All Virtual Machines

  • Delete all VMs
  • Delete all NAT port mappings
  • Restart the network
  • Delete log files
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

Before modifying the VM configuration for PVE, you must shut it down first. After making the configuration changes, start it again to avoid configuration reload errors.

Setting Up Virtual Machines with Dedicated IPv4 Addresses

Three scripts, each with its own advantages and disadvantages.

The first two scripts don't require an additional IPV4 address to be bound to the vmbr0 interface beforehand, and the opened VM will directly bind the additional IPV4 address.

The last script requires additional IPV4 addresses to be bound to the vmbr0 interface beforehand, and the opened VM will do NAT full port mapping to the intranet IPV4 address, **without directly binding additional IPV4 addresses.

Automatically selects additional IPV4 addresses on the same subnet as the host machine to open the virtual machine

WARNING

Before use, ensure that the current host machine has at least 2 available IP addresses within its IP range, and there are unallocated IP addresses. These unallocated IP addresses should not be bound to the host machine.

TIP

At this point, the IPV4 address appended is the address following the host's current IPV4 address in sequence. For example, if the current host address is 1.1.1.32 and then 1.1.1.33 there is already a virtual machine, then this script appends an IP address of 1.1.1.34.

  • Automatically detect available IP ranges. Use ping to identify unallocated IP addresses and select one to bind to the virtual machine.
  • If the host machine has an accompanying IPv6 subnet, there will be an option to attach an IPv6 address.
  • Relevant system information will be stored in the corresponding virtual machine's NOTE section, accessible for viewing on the web interface.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • The automatically appended IPV4 address is within the same subnet as the host's IPV4 address (IP address prefix is the same)
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

Meaning of each parameter

shell
# ./buildvm_extra_ip.sh VMID Username Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB OS Storage_Disk Attach_IPV6(Default is N)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

The above command is used to create a virtual machine with a dedicated IPv4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
OSdebian12
Storagelocal disk
IPv6 AddonNot attached by default

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Manually Assign Additional IPV4 Addresses to Open Virtual Machines

  • Manual specification of IPV4 address with subnet length in the command is required.
  • If the host machine comes with an IPV6 subnet, you can choose whether to add an IPV6 address additionally.
  • If the vendor has provided an IPV4 address and subnet length, please carefully compare and write the parameters in the command format shown below.
  • Relevant system information will be stored in the NOTE of the corresponding virtual machine and can be viewed on the WEB end.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • Manually appended IPV4 addresses that are in different subnets from the host's IPV4 address (different IP address prefixes) will use the host's IP address as the gateway
  • Manually appended IPV4 addresses that are within the same subnet as the host's IPV4 address (same IP address prefix) will use the host's gateway as the gateway
  • Optionally specify the MAC address of the virtual machine
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

TIP

If IP addresses within different subnets are appended without a MAC address, the router will not recognize the source MAC address, and the traffic will be flagged as “misuse” and “may” cause the server to be blocked. (If you are using a Hetzner standalone server, it is recommended that you provide the MAC address of the attached IPV4 address to prevent abuse from being reported.)

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

Meaning of each parameter

shell
# ./buildvm_manual_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N) MAC_ADDRESS(Optional whether to specify)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
Subnet/24 Subnet
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Host manually appends an additional IPV4 address and then specifies the IPV4 address to open the virtual machine

  • You need to add the extra IPV4 address to vmbr0 in /etc/network/interfaces (note that chattr -i unlocks the file and then chattr +i locks it back).
  • Other features are similar to opening a NAT-enabled VM, except that here the mapping is no longer partial port mapping or mapping to the host's IPV4 address, but full-port one-by-one mapping to additional IPV4 addresses
  • Traffic coming into the VM from outside the VM goes to the bound additional IPV4 address, and traffic going out of the VM goes to the original host's IPV4 address

TIP

Make sure you can SSH into the host with the extra IPV4 address before opening, but curl ip.sb still shows the original host IPV4 address.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

Meaning of each parameter

shell
# ./buildvm_fullnat_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Incoming and outgoing traffic goes to the bound IPV4 address

execute

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

This will cause the host to lose the ability to open VMs/containers with NAT that do not have a separate IPV4 address, so be careful!

After this, You will only be able to open VMs with separate IPV4 addresses.

Creating Virtual Machines with Pure IPv6 Addresses

The prerequisite is that the host provides an IPv6 subnet instead of just a standalone IPv6 address, and the host does not have MAC address verification enabled.

Automatic Selection of IPv6 Addresses without Manual Specification

  • Pure IPV6 refers to a bound public IPV6 address, where the actual VM still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address, based on the virtual machine's number, to the virtual machine.
  • System-related information will be stored in the NOTES section of the respective virtual machine, accessible for viewing on the web interface.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

Meaning of each parameter

shell
# ./buildvm_onlyv6.sh VMID username password CPU_cores memory_GB disk_GB operating_system storage_disk

TIP

Note that the password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

The above command is used to create a virtual machine with only IPv6 addresses.

ParameterValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage Disklocal

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Delete Example vm152

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
`,122),l=[o];function i(r,p,c,d,h,u){return a(),e("div",null,l)}const y=s(n,[["render",i]]);export{m as __pageData,y as default}; diff --git a/assets/en_guide_pve_pve_kvm.md.CutjUOCm.js b/assets/en_guide_pve_pve_kvm.md.CutjUOCm.js new file mode 100644 index 0000000000..eb86940c99 --- /dev/null +++ b/assets/en_guide_pve_pve_kvm.md.CutjUOCm.js @@ -0,0 +1,15 @@ +import{_ as t,c as i,o as a,ag as e}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Linux Virtual Machine (KVM/TCG Virtualization)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_kvm.md","filePath":"en/guide/pve/pve_kvm.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_kvm.md"};function l(h,s,r,o,d,p){return a(),i("div",null,s[0]||(s[0]=[e(`

Linux Virtual Machine (KVM/TCG Virtualization)

SSH Login Instructions

When open a virtual machine, the default generated username can be something other than root, in which case you need to run sudo -i to switch to root!

If the default username is not root, the default unset root password is password or oneclickvirt.

After logging into SSH and switching to root privileges, be sure to change the root password, which can be changed using the following command:

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

Considerations for opening a virtual machine with an IPV6 address

Due to long-term inactivity IPV6 does not use may lead to NDP broadcast cache invalidation reset, generally idle for about 50 minutes will appear IPV6 unavailable, commonly known as "IPV6 cutoff", at this time it is necessary to set up a timer task.

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

Executing the above commands in the opened virtual machine ensures that the IPV6 network is always used and does not fail over.

Images available for creating virtual machines

  • Pre-installed with cloud-init enabled.
  • Enabled SSH login.
  • Pre-configured SSH to listen on ports 22 for both IPv4 and IPv6.
  • Enabled password authentication for login.
  • Enabled root login.
  • Partially pre-installed QEMU guest agent.

The list of currently available image names is as follows:

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

and

https://github.com/oneclickvirt/pve_kvm_images

Daily patch images stored in the Release of this repository.

Virtual machines with standalone NAT configuration.

  • Automatically deploy NAT servers with the default Debian 10 image, chosen for its minimal footprint.
  • It's possible to customize the image used through the command, and pre-configured images are available. These images come with storage settings ranging from 2 to 10 GB of disk space. For regular use, at least 10 GB of disk space is recommended. You can increase the disk size if certain images fail to start.
  • The command allows for specifying the storage disk location. When not specified, it defaults to the local disk, which is the system disk. It can also be set to a mount disk as displayed in PVE.
  • Recommended custom memory size is 512 MB.
  • Automatic internal and external port mapping, including ports 22, 80, 443, and 25 other port numbers shared between internal and external networks.
  • After generation, there's a wait time for the virtual machine's internal cloud-init configuration to establish network and login information. This process takes approximately 5 minutes.
  • Pertinent virtual machine information will be stored in the NOTES section of the corresponding VM on the web interface, accessible for viewing through the web portal.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically added. However, there won't be any public IPV6 addresses.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

System Support:

  • For x86_64 architecture systems listed in this link, simply use the filename without the .qcow2 extension when using.
  • For arm architecture systems listed at this link, use the system name and version number, such as ubuntu20 or ubuntu22.

TIP

Note that usernames consisting of only numbers may cause issues with cloud-init. It's preferable to use usernames that are entirely in English or start with an English character.

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

Meaning of each parameter

shell
# ./buildvm.sh VMID Username Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Public_Port_Start Public_Port_End System Storage_Disk Independent_IPV6_address(leave default N blank)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

After setup is completed, you can execute cat vm111 to view the information or check the NOTES section for the corresponding VM on the WEB interface.

Below is the information for the example VM that has been set up:

AttributeValue
VMID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size10G
SSH Port40001
Port 8040002
Port 44340003
Port Range for NAT50000 to 50025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific VM

  • Stop VM
  • Delete VM
  • Delete port mapping
  • Restart network
  • Delete log files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the VM with the corresponding VMID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each VMID, and more than one can be deleted at a time.

Batch Creation of Virtual Machines with NAT

WARNING

Before initial use, ensure that the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port forwarding, as conflicting settings may result in bugs.

TIP

Before initiating the batch creation process, please use the 'screen' command to execute it in the background. This will help avoid interruptions due to the instability of SSH caused by extended batch creation times.

  • The batch creation process can be run multiple times to generate multiple virtual machines (VMs).
  • NAT servers are automatically created during the process. If left blank, the default Debian 11 image will be used. You can also customize the image name. Refer to the list of supported images in the previous section.
  • Automatic internal and external port mapping is performed, including ports 22, 80, 443, and other ports with identical internal and external numbers (25 ports in total).
  • After generation, a waiting period is required for the cloud-init configuration of the VM's network and login information to be set up. This process takes approximately 5 minutes. There is a 60-second interval between creating each VM to avoid potential performance issues.
  • The default network configuration for VMs created in batches includes port mappings for ports 22, 80, 443, and a range of 25 ports for internal and external communication.
  • You can customize the number of CPU cores, memory size, disk size, and which storage disk on the host machine to use for batch creation. Ensure you calculate available resources before proceeding.
  • Relevant information about the virtual machines will be stored in the 'NOTES' section of the corresponding VM on the web interface, where you can view them.
  • If the host machine comes with an IPv6 subnet, an IPv6 network will be automatically attached, although there will be no public IPv6 addresses available.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

After the setup is completed, you can execute cat vmlog to view the information, or check the NOTES in the corresponding VM on the web interface.

Delete All Virtual Machines

  • Delete all VMs
  • Delete all NAT port mappings
  • Restart the network
  • Delete log files
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4
+rm -rf vmlog
+rm -rf vm*

TIP

Before modifying the VM configuration for PVE, you must shut it down first. After making the configuration changes, start it again to avoid configuration reload errors.

Setting Up Virtual Machines with Dedicated IPv4 Addresses

Three scripts, each with its own advantages and disadvantages.

The first two scripts don't require an additional IPV4 address to be bound to the vmbr0 interface beforehand, and the opened VM will directly bind the additional IPV4 address.

The last script requires additional IPV4 addresses to be bound to the vmbr0 interface beforehand, and the opened VM will do NAT full port mapping to the intranet IPV4 address, **without directly binding additional IPV4 addresses.

Automatically selects additional IPV4 addresses on the same subnet as the host machine to open the virtual machine

WARNING

Before use, ensure that the current host machine has at least 2 available IP addresses within its IP range, and there are unallocated IP addresses. These unallocated IP addresses should not be bound to the host machine.

TIP

At this point, the IPV4 address appended is the address following the host's current IPV4 address in sequence. For example, if the current host address is 1.1.1.32 and then 1.1.1.33 there is already a virtual machine, then this script appends an IP address of 1.1.1.34.

  • Automatically detect available IP ranges. Use ping to identify unallocated IP addresses and select one to bind to the virtual machine.
  • If the host machine has an accompanying IPv6 subnet, there will be an option to attach an IPv6 address.
  • Relevant system information will be stored in the corresponding virtual machine's NOTE section, accessible for viewing on the web interface.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • The automatically appended IPV4 address is within the same subnet as the host's IPV4 address (IP address prefix is the same)
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

Meaning of each parameter

shell
# ./buildvm_extra_ip.sh VMID Username Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB OS Storage_Disk Attach_IPV6(Default is N)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

The above command is used to create a virtual machine with a dedicated IPv4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
OSdebian12
Storagelocal disk
IPv6 AddonNot attached by default

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Manually Assign Additional IPV4 Addresses to Open Virtual Machines

  • Manual specification of IPV4 address with subnet length in the command is required.
  • If the host machine comes with an IPV6 subnet, you can choose whether to add an IPV6 address additionally.
  • If the vendor has provided an IPV4 address and subnet length, please carefully compare and write the parameters in the command format shown below.
  • Relevant system information will be stored in the NOTE of the corresponding virtual machine and can be viewed on the WEB end.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • Manually appended IPV4 addresses that are in different subnets from the host's IPV4 address (different IP address prefixes) will use the host's IP address as the gateway
  • Manually appended IPV4 addresses that are within the same subnet as the host's IPV4 address (same IP address prefix) will use the host's gateway as the gateway
  • Optionally specify the MAC address of the virtual machine
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

TIP

If IP addresses within different subnets are appended without a MAC address, the router will not recognize the source MAC address, and the traffic will be flagged as “misuse” and “may” cause the server to be blocked. (If you are using a Hetzner standalone server, it is recommended that you provide the MAC address of the attached IPV4 address to prevent abuse from being reported.)

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

Meaning of each parameter

shell
# ./buildvm_manual_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N) MAC_ADDRESS(Optional whether to specify)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
Subnet/24 Subnet
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Host manually appends an additional IPV4 address and then specifies the IPV4 address to open the virtual machine

  • You need to add the extra IPV4 address to vmbr0 in /etc/network/interfaces (note that chattr -i unlocks the file and then chattr +i locks it back).
  • Other features are similar to opening a NAT-enabled VM, except that here the mapping is no longer partial port mapping or mapping to the host's IPV4 address, but full-port one-by-one mapping to additional IPV4 addresses
  • Traffic coming into the VM from outside the VM goes to the bound additional IPV4 address, and traffic going out of the VM goes to the original host's IPV4 address

TIP

Make sure you can SSH into the host with the extra IPV4 address before opening, but curl ip.sb still shows the original host IPV4 address.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

Meaning of each parameter

shell
# ./buildvm_fullnat_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Incoming and outgoing traffic goes to the bound IPV4 address

execute

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
+sed -i "\\|$line|d" /etc/iptables/rules.v4
+service netfilter-persistent restart

This will cause the host to lose the ability to open VMs/containers with NAT that do not have a separate IPV4 address, so be careful!

After this, You will only be able to open VMs with separate IPV4 addresses.

Creating Virtual Machines with Pure IPv6 Addresses

The prerequisite is that the host provides an IPv6 subnet instead of just a standalone IPv6 address, and the host does not have MAC address verification enabled.

Automatic Selection of IPv6 Addresses without Manual Specification

  • Pure IPV6 refers to a bound public IPV6 address, where the actual VM still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address, based on the virtual machine's number, to the virtual machine.
  • System-related information will be stored in the NOTES section of the respective virtual machine, accessible for viewing on the web interface.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

Meaning of each parameter

shell
# ./buildvm_onlyv6.sh VMID username password CPU_cores memory_GB disk_GB operating_system storage_disk

TIP

Note that the password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

The above command is used to create a virtual machine with only IPv6 addresses.

ParameterValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage Disklocal

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Delete Example vm152

shell
qm stop 152
+qm destroy 152
+systemctl restart ndpresponder.service
+rm -rf vm152
`,122)]))}const u=t(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_pve_pve_kvm.md.CutjUOCm.lean.js b/assets/en_guide_pve_pve_kvm.md.CutjUOCm.lean.js new file mode 100644 index 0000000000..f008a96b42 --- /dev/null +++ b/assets/en_guide_pve_pve_kvm.md.CutjUOCm.lean.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as a,ag as e}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"Linux Virtual Machine (KVM/TCG Virtualization)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_kvm.md","filePath":"en/guide/pve/pve_kvm.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_kvm.md"};function l(h,s,r,o,d,p){return a(),i("div",null,s[0]||(s[0]=[e("",122)]))}const u=t(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/en_guide_pve_pve_lxc.md.5f264fc4.js b/assets/en_guide_pve_pve_lxc.md.5f264fc4.js deleted file mode 100644 index 05f8e7c5e6..0000000000 --- a/assets/en_guide_pve_pve_lxc.md.5f264fc4.js +++ /dev/null @@ -1,12 +0,0 @@ -import{_ as s,v as e,b as a,R as t}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"LXC Virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_lxc.md","filePath":"en/guide/pve/pve_lxc.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_lxc.md"},o=t(`

LXC Virtualization

WARNING

If you need to open more than 200 LXC containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Images available for creating LXC Containers

x86_64:

Auto-patching images: https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

Automated daily pulls for compilation and patching

Self-patching images: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

Some of these images are flawed and not guaranteed to be available for all PVEs, with names like ubuntu16.04, debian6, centos7, opensuse42.2, opensuse42.3 Don't use them unless necessary.

and

Run pveam available --section system to see the names and version numbers of the officially available systems.

Priority: Self-patching images (not supported by Proxmox-VE 5 and below) > Official default images (both supported) image

The version has been automatically recognized by a script to use the corresponding image.

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

Supported systems can be viewed in the file above, which lists debian and ubuntu systems do not use the aliases in it, just use the numeric designators.

TIP

All system parameters are lowercase system names spliced with version numbers, e.g. debian11, ubuntu22, etc. (Self-patched images support some out-of-the-way systems, such as centos6, centos7, debian8, debian9, etc.)

The default CT username for all systems is root

TIP

Of course, sometimes there are special cases where the version may be current/base, in which case it is sufficient to use only the English system name, e.g. archlinux, gentoo, kali.

Creating Individual LXC Containers for Virtualization

WARNING

Before initial use, ensure that the current PVE (Proxmox Virtual Environment) is clean and the host machine has not undergone any port mapping, as conflicts in settings could lead to bugs.

TIP

Before creating containers, use the 'screen' command to run them in the background. This helps to avoid extended creation times that might lead to interruptions due to unstable SSH connections.

  • Automatically create NAT servers using the default Debian 11 image, or customize the system image as needed.
  • Automatically perform internal and external network port mapping, including ports 22, 80, 443, and 25 additional ports with identical numbers for both internal and external networks.
  • After generation, allow some time for the virtual machine to configure its internal network and login information. This process takes approximately 3 minutes.
  • The default network configuration includes port mappings for 22, 80, 443, and a range of 25 ports for both internal and external networks.
  • Customize the number of cores, memory size, disk size, and the storage disk on the host machine for allocation. Ensure that you calculate available resources before creating containers.
  • Optionally specify the storage disk location in the command. When not specified, it defaults to the local disk, which is the system disk. Alternatively, you can specify a mount disk as displayed in PVE.
  • The created containers are enabled with SSH by default, allowing root login. They are also configured to support nested virtualization for Docker.
  • Relevant container information will be stored in the respective container's notes, accessible through the web interface.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically attached, but no public IPV6 addresses will be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

Meaning of each parameter

shell
# ./buildct.sh CTID Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Start_Public_Port End_Public_Port System Storage_Disk Independent_IPV6_address(leave default N blank)

Test Example

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

After setting up, you can execute cat ct111 to view the information, or check the NOTES section on the web interface.

Here is the information for the created example CT:

Please note that "CT" and other technical terms might have specific meanings in different contexts. If "CT" stands for something specific in your domain, you might want to provide additional context for accurate translation.

AttributeValue
CTID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size5G
SSH Port20001
Port 8020002
Port 44320003
Port Range for NAT30000 to 30025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific CT

  • Stop CT
  • Delete CT
  • Delete Port Mapping
  • Restart Network
  • Delete Log Files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the CT with the corresponding CTID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each CTID, and more than one can be deleted at a time.

Batch Creation of LXC Containers with NAT

WARNING

Make sure the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port mapping before the first use, as conflicting settings may result in bugs.

TIP

Before initiating the creation process, it's recommended to use the 'screen' command to execute the batch creation. This will prevent interruptions due to potential instability in SSH during the extended creation time.

  • It is possible to run the batch container creation process multiple times. However, please be mindful of allocating enough memory to the host machine to prevent system crashes. For adding swap space, refer to this link.
  • There is a 60-second interval between creating each container to avoid sudden performance bottlenecks.
  • Customization options include selecting the number of CPU cores, memory size, disk size, and the storage drive on the host machine. Ensure that you have calculated available resources appropriately before initiating the process.
  • The created containers have SSH enabled by default, allowing root login. Additionally, they are configured to support nested virtualization for Docker usage.
  • Relevant information about the containers will be stored in the corresponding container's notes, which can be viewed on the web interface.
  • If the host machine has an IPv6 subnet, it will be automatically assigned to the containers. However, public IPv6 addresses will not be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

After the setup is complete, you can execute cat ctlog to view the information, or check in the NOTES section on the web interface.

Delete All CT

  • Delete all CTs
  • Delete port mappings for all NATs
  • Restart the network
  • Delete log files
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

Creating Virtual Machines with Pure IPv6 Addresses

The premise is that the host provides an IPv6 subnet rather than a standalone IPv6 address, and the host does not have MAC address filtering enabled.

Automatic Selection of IPv6 Addresses, No Manual Configuration Needed

  • Pure IPV6 refers to a bound public IPV6 address, where the actual container still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address based on the container number to the container.
  • Relevant system information will be stored in the NOTES of the corresponding container, accessible for viewing on the web interface.

Download script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

Example Usage

shell
./buildct_onlyv6.sh CTID Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB Operating_System Storage_Disk
shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

The above command signifies the creation of a container with a pure IPV6 address.

AttributeValue
Container TypeCT
CTID152
Usernameroot
Passwordoneclick123
CPU Cores1
Memory1024MB
Disk10G
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion Example

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
`,68),l=[o];function r(p,i,c,d,C,h){return e(),a("div",null,l)}const m=s(n,[["render",r]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_pve_pve_lxc.md.5f264fc4.lean.js b/assets/en_guide_pve_pve_lxc.md.5f264fc4.lean.js deleted file mode 100644 index 05f8e7c5e6..0000000000 --- a/assets/en_guide_pve_pve_lxc.md.5f264fc4.lean.js +++ /dev/null @@ -1,12 +0,0 @@ -import{_ as s,v as e,b as a,R as t}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"LXC Virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_lxc.md","filePath":"en/guide/pve/pve_lxc.md","lastUpdated":1747972048000}'),n={name:"en/guide/pve/pve_lxc.md"},o=t(`

LXC Virtualization

WARNING

If you need to open more than 200 LXC containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Images available for creating LXC Containers

x86_64:

Auto-patching images: https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

Automated daily pulls for compilation and patching

Self-patching images: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

Some of these images are flawed and not guaranteed to be available for all PVEs, with names like ubuntu16.04, debian6, centos7, opensuse42.2, opensuse42.3 Don't use them unless necessary.

and

Run pveam available --section system to see the names and version numbers of the officially available systems.

Priority: Self-patching images (not supported by Proxmox-VE 5 and below) > Official default images (both supported) image

The version has been automatically recognized by a script to use the corresponding image.

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

Supported systems can be viewed in the file above, which lists debian and ubuntu systems do not use the aliases in it, just use the numeric designators.

TIP

All system parameters are lowercase system names spliced with version numbers, e.g. debian11, ubuntu22, etc. (Self-patched images support some out-of-the-way systems, such as centos6, centos7, debian8, debian9, etc.)

The default CT username for all systems is root

TIP

Of course, sometimes there are special cases where the version may be current/base, in which case it is sufficient to use only the English system name, e.g. archlinux, gentoo, kali.

Creating Individual LXC Containers for Virtualization

WARNING

Before initial use, ensure that the current PVE (Proxmox Virtual Environment) is clean and the host machine has not undergone any port mapping, as conflicts in settings could lead to bugs.

TIP

Before creating containers, use the 'screen' command to run them in the background. This helps to avoid extended creation times that might lead to interruptions due to unstable SSH connections.

  • Automatically create NAT servers using the default Debian 11 image, or customize the system image as needed.
  • Automatically perform internal and external network port mapping, including ports 22, 80, 443, and 25 additional ports with identical numbers for both internal and external networks.
  • After generation, allow some time for the virtual machine to configure its internal network and login information. This process takes approximately 3 minutes.
  • The default network configuration includes port mappings for 22, 80, 443, and a range of 25 ports for both internal and external networks.
  • Customize the number of cores, memory size, disk size, and the storage disk on the host machine for allocation. Ensure that you calculate available resources before creating containers.
  • Optionally specify the storage disk location in the command. When not specified, it defaults to the local disk, which is the system disk. Alternatively, you can specify a mount disk as displayed in PVE.
  • The created containers are enabled with SSH by default, allowing root login. They are also configured to support nested virtualization for Docker.
  • Relevant container information will be stored in the respective container's notes, accessible through the web interface.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically attached, but no public IPV6 addresses will be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

Meaning of each parameter

shell
# ./buildct.sh CTID Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Start_Public_Port End_Public_Port System Storage_Disk Independent_IPV6_address(leave default N blank)

Test Example

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

After setting up, you can execute cat ct111 to view the information, or check the NOTES section on the web interface.

Here is the information for the created example CT:

Please note that "CT" and other technical terms might have specific meanings in different contexts. If "CT" stands for something specific in your domain, you might want to provide additional context for accurate translation.

AttributeValue
CTID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size5G
SSH Port20001
Port 8020002
Port 44320003
Port Range for NAT30000 to 30025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific CT

  • Stop CT
  • Delete CT
  • Delete Port Mapping
  • Restart Network
  • Delete Log Files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the CT with the corresponding CTID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each CTID, and more than one can be deleted at a time.

Batch Creation of LXC Containers with NAT

WARNING

Make sure the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port mapping before the first use, as conflicting settings may result in bugs.

TIP

Before initiating the creation process, it's recommended to use the 'screen' command to execute the batch creation. This will prevent interruptions due to potential instability in SSH during the extended creation time.

  • It is possible to run the batch container creation process multiple times. However, please be mindful of allocating enough memory to the host machine to prevent system crashes. For adding swap space, refer to this link.
  • There is a 60-second interval between creating each container to avoid sudden performance bottlenecks.
  • Customization options include selecting the number of CPU cores, memory size, disk size, and the storage drive on the host machine. Ensure that you have calculated available resources appropriately before initiating the process.
  • The created containers have SSH enabled by default, allowing root login. Additionally, they are configured to support nested virtualization for Docker usage.
  • Relevant information about the containers will be stored in the corresponding container's notes, which can be viewed on the web interface.
  • If the host machine has an IPv6 subnet, it will be automatically assigned to the containers. However, public IPv6 addresses will not be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

After the setup is complete, you can execute cat ctlog to view the information, or check in the NOTES section on the web interface.

Delete All CT

  • Delete all CTs
  • Delete port mappings for all NATs
  • Restart the network
  • Delete log files
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

Creating Virtual Machines with Pure IPv6 Addresses

The premise is that the host provides an IPv6 subnet rather than a standalone IPv6 address, and the host does not have MAC address filtering enabled.

Automatic Selection of IPv6 Addresses, No Manual Configuration Needed

  • Pure IPV6 refers to a bound public IPV6 address, where the actual container still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address based on the container number to the container.
  • Relevant system information will be stored in the NOTES of the corresponding container, accessible for viewing on the web interface.

Download script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

Example Usage

shell
./buildct_onlyv6.sh CTID Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB Operating_System Storage_Disk
shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

The above command signifies the creation of a container with a pure IPV6 address.

AttributeValue
Container TypeCT
CTID152
Usernameroot
Passwordoneclick123
CPU Cores1
Memory1024MB
Disk10G
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion Example

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
`,68),l=[o];function r(p,i,c,d,C,h){return e(),a("div",null,l)}const m=s(n,[["render",r]]);export{y as __pageData,m as default}; diff --git a/assets/en_guide_pve_pve_lxc.md.DacQBeid.js b/assets/en_guide_pve_pve_lxc.md.DacQBeid.js new file mode 100644 index 0000000000..3eb1cbcb61 --- /dev/null +++ b/assets/en_guide_pve_pve_lxc.md.DacQBeid.js @@ -0,0 +1,12 @@ +import{_ as s,c as t,o as e,ag as a}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"LXC Virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_lxc.md","filePath":"en/guide/pve/pve_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_lxc.md"};function l(h,i,r,o,p,d){return e(),t("div",null,i[0]||(i[0]=[a(`

LXC Virtualization

WARNING

If you need to open more than 200 LXC containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Images available for creating LXC Containers

x86_64:

Auto-patching images: https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

Automated daily pulls for compilation and patching

Self-patching images: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

Some of these images are flawed and not guaranteed to be available for all PVEs, with names like ubuntu16.04, debian6, centos7, opensuse42.2, opensuse42.3 Don't use them unless necessary.

and

Run pveam available --section system to see the names and version numbers of the officially available systems.

Priority: Self-patching images (not supported by Proxmox-VE 5 and below) > Official default images (both supported) image

The version has been automatically recognized by a script to use the corresponding image.

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

Supported systems can be viewed in the file above, which lists debian and ubuntu systems do not use the aliases in it, just use the numeric designators.

TIP

All system parameters are lowercase system names spliced with version numbers, e.g. debian11, ubuntu22, etc. (Self-patched images support some out-of-the-way systems, such as centos6, centos7, debian8, debian9, etc.)

The default CT username for all systems is root

TIP

Of course, sometimes there are special cases where the version may be current/base, in which case it is sufficient to use only the English system name, e.g. archlinux, gentoo, kali.

Creating Individual LXC Containers for Virtualization

WARNING

Before initial use, ensure that the current PVE (Proxmox Virtual Environment) is clean and the host machine has not undergone any port mapping, as conflicts in settings could lead to bugs.

TIP

Before creating containers, use the 'screen' command to run them in the background. This helps to avoid extended creation times that might lead to interruptions due to unstable SSH connections.

  • Automatically create NAT servers using the default Debian 11 image, or customize the system image as needed.
  • Automatically perform internal and external network port mapping, including ports 22, 80, 443, and 25 additional ports with identical numbers for both internal and external networks.
  • After generation, allow some time for the virtual machine to configure its internal network and login information. This process takes approximately 3 minutes.
  • The default network configuration includes port mappings for 22, 80, 443, and a range of 25 ports for both internal and external networks.
  • Customize the number of cores, memory size, disk size, and the storage disk on the host machine for allocation. Ensure that you calculate available resources before creating containers.
  • Optionally specify the storage disk location in the command. When not specified, it defaults to the local disk, which is the system disk. Alternatively, you can specify a mount disk as displayed in PVE.
  • The created containers are enabled with SSH by default, allowing root login. They are also configured to support nested virtualization for Docker.
  • Relevant container information will be stored in the respective container's notes, accessible through the web interface.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically attached, but no public IPV6 addresses will be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

Meaning of each parameter

shell
# ./buildct.sh CTID Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Start_Public_Port End_Public_Port System Storage_Disk Independent_IPV6_address(leave default N blank)

Test Example

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

After setting up, you can execute cat ct111 to view the information, or check the NOTES section on the web interface.

Here is the information for the created example CT:

Please note that "CT" and other technical terms might have specific meanings in different contexts. If "CT" stands for something specific in your domain, you might want to provide additional context for accurate translation.

AttributeValue
CTID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size5G
SSH Port20001
Port 8020002
Port 44320003
Port Range for NAT30000 to 30025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific CT

  • Stop CT
  • Delete CT
  • Delete Port Mapping
  • Restart Network
  • Delete Log Files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the CT with the corresponding CTID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each CTID, and more than one can be deleted at a time.

Batch Creation of LXC Containers with NAT

WARNING

Make sure the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port mapping before the first use, as conflicting settings may result in bugs.

TIP

Before initiating the creation process, it's recommended to use the 'screen' command to execute the batch creation. This will prevent interruptions due to potential instability in SSH during the extended creation time.

  • It is possible to run the batch container creation process multiple times. However, please be mindful of allocating enough memory to the host machine to prevent system crashes. For adding swap space, refer to this link.
  • There is a 60-second interval between creating each container to avoid sudden performance bottlenecks.
  • Customization options include selecting the number of CPU cores, memory size, disk size, and the storage drive on the host machine. Ensure that you have calculated available resources appropriately before initiating the process.
  • The created containers have SSH enabled by default, allowing root login. Additionally, they are configured to support nested virtualization for Docker usage.
  • Relevant information about the containers will be stored in the corresponding container's notes, which can be viewed on the web interface.
  • If the host machine has an IPv6 subnet, it will be automatically assigned to the containers. However, public IPv6 addresses will not be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

After the setup is complete, you can execute cat ctlog to view the information, or check in the NOTES section on the web interface.

Delete All CT

  • Delete all CTs
  • Delete port mappings for all NATs
  • Restart the network
  • Delete log files
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
+rm -rf ct*
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4

Creating Virtual Machines with Pure IPv6 Addresses

The premise is that the host provides an IPv6 subnet rather than a standalone IPv6 address, and the host does not have MAC address filtering enabled.

Automatic Selection of IPv6 Addresses, No Manual Configuration Needed

  • Pure IPV6 refers to a bound public IPV6 address, where the actual container still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address based on the container number to the container.
  • Relevant system information will be stored in the NOTES of the corresponding container, accessible for viewing on the web interface.

Download script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

Example Usage

shell
./buildct_onlyv6.sh CTID Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB Operating_System Storage_Disk
shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

The above command signifies the creation of a container with a pure IPV6 address.

AttributeValue
Container TypeCT
CTID152
Usernameroot
Passwordoneclick123
CPU Cores1
Memory1024MB
Disk10G
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion Example

shell
rm -rf ct*
+pct stop 152 
+pct destroy 152
+systemctl restart ndpresponder.service
`,68)]))}const g=s(n,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_pve_pve_lxc.md.DacQBeid.lean.js b/assets/en_guide_pve_pve_lxc.md.DacQBeid.lean.js new file mode 100644 index 0000000000..cc393dead2 --- /dev/null +++ b/assets/en_guide_pve_pve_lxc.md.DacQBeid.lean.js @@ -0,0 +1 @@ +import{_ as s,c as t,o as e,ag as a}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"LXC Virtualization","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_lxc.md","filePath":"en/guide/pve/pve_lxc.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_lxc.md"};function l(h,i,r,o,p,d){return e(),t("div",null,i[0]||(i[0]=[a("",68)]))}const g=s(n,[["render",l]]);export{k as __pageData,g as default}; diff --git a/assets/en_guide_pve_pve_macos.md.785a524c.js b/assets/en_guide_pve_pve_macos.md.785a524c.js deleted file mode 100644 index 1eaff24ddc..0000000000 --- a/assets/en_guide_pve_pve_macos.md.785a524c.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as e,v as a,b as s,R as t}from"./chunks/framework.70afa331.js";import{_ as o}from"./chunks/wk7.776871bd.js";const n="/assets/mac0.935d53f3.png",i="/assets/mac00.4296be7b.png",l="/assets/mac1.3307e401.png",c="/assets/mac2.da6ce0bc.png",r="/assets/mac3.76a50b9f.png",p="/assets/mac4.c341ba50.png",d="/assets/mac5.39e1c9a4.png",m="/assets/mac6.1cc0462b.png",h="/assets/mac7.181275ae.png",u="/assets/mac8.dd556f02.png",y="/assets/mac9.c5d88eba.png",g="/assets/mac10.e9c284db.png",C="/assets/mac11.a7587e0e.png",f="/assets/mac12.06b051d3.png",b="/assets/mac13.7d4e3199.png",A="/assets/mac14.39a58b6a.png",k="/assets/mac15.f151793c.png",D="/assets/mac16.eae177db.png",w="/assets/mac17.be61913a.png",v="/assets/mac18.f9454618.png",_="/assets/mac19.845f5510.png",S="/assets/mac20.49a5800c.png",N=JSON.parse('{"title":"Setting Up MacOS Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_macos.md","filePath":"en/guide/pve/pve_macos.md","lastUpdated":1747972048000}'),x={name:"en/guide/pve/pve_macos.md"},F=t(`

Setting Up MacOS Virtual Machine

Prerequisites

System and hardware configuration requirements --> Environment detection

You can only set up a MacOS virtual machine when the environment detection confirms that the host machine supports KVM nested virtualization. Otherwise, it will be detected by hardware and cannot be set up.

Setting Up the Prerequisites

  • Automatically identify CPU type (AMD or Intel) and set nested virtualization parameters according to the type.
  • Modify GRUB boot parameters to enable IOMMU and disable default framebuffer.
  • Add VFIO module support for hardware device passthrough.
  • Blacklist sound card and graphics card driver modules to avoid conflicts with macOS.
  • Configure KVM-related kernel parameters, ignore MSR errors, and improve compatibility.
  • Patch Proxmox frontend status detection logic to bypass status restrictions.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

After successful execution, it will show that the system will restart in 15 seconds. This is the normal process, as kernel parameters cannot take effect without restarting.

System Image Download

  • All images have pre-installed components and are relatively large (minimum about 4.9GB). Download and extraction tasks will run in the background.
  • Images are complete systems with all components and can be booted and used without internet connection.
  • If the free space on the system disk is less than twice the size of the image, the download will be rejected.
  • Images are in 7z compressed format and need to be extracted before use.
  • You can check the status of current download and extraction tasks at any time. Virtual machines can only be created after completion.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh --lang=en

Or

shell
bash install_macos_images.sh --lang=en

After the background download task starts, you can close the SSH window and wait for 30 minutes to 3 hours (depending on your server bandwidth and connectivity) to download the ISO 7z compressed package.

When the download task is complete and the current download task query shows empty, you can choose to execute the extraction task. The waiting time for extraction depends on your server's CPU performance.

When the extraction task is complete and the current extraction task query shows empty, all preparations are ready.

Tasks of the same type can run concurrently, and any task can be canceled at any time by entering the PID value.

Build from https://github.com/oneclickvirt/macos currently supported image compressed packages:

# Listed by system release date from old to new
-high-sierra.iso.7z (Size: 5.23GB)
-mojave.iso.7z (Size: 6.03GB)
-catalina.iso.7z (Size: 8.33GB)
-big‑sur.iso.7z (Size: 12.21GB)
-monterey.iso.7z (Size: 12.36GB)
-ventura.iso.7z (Size: 12.31GB)
-sonoma.iso.7z (Size: 14.41GB)
-sequoia.iso.7z (Size: 15.02GB)

MACOS Virtual Machine Template Setup

  • Systems high-sierra, mojave, catalina require at least 2 cores, 4G of RAM and 40G of hard disk to run.
  • big-sur and newer MACOS systems require at least 6 cores, 6G RAM and 50G hard disk.
  • The newer the version of the system (the later the serial number of the download), the more hardware is required.
  • All images are boot disk images without any personal data, so disk allocation, login information setup, and network settings need to be manually configured according to the instructions.
  • You need to manually start the virtual machine from the web interface. Before starting, you can check if all templates meet your expectations.

Download Template Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

Parameter Meanings

shell
# ./buildvm_macos.sh VMID CPU_cores Memory Disk SSH_port VNC_port System Storage_disk Independent_IPV6(default_N_if_empty)

TIP

The disk size here is only the size of the virtual machine's disk. During the actual setup process, the program will also mount the boot disk and system image, so the actual disk requirement for setting up a virtual machine is virtual machine disk size + image size + boot disk size (500MB). Always be aware of whether your disk space is sufficient for setting up virtual machines.

Example Command

Using the oldest version (high-sierra) as an example, the supported configuration is as follows (very laggy)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

After the template is set up, you can run cat vm100 to view information, or check the NOTES in the corresponding VM in the WEB interface.

Here is the information for the example VM:

PropertyValue
VMID100
CPU cores2
Memory size4096MB
Disk size45G
SSH port44022
VNC port45901
Systemhigh-sierra
Host storage disklocal
Independent IPV6N

TIP

Note that VMID can only use numbers from 100 to 256, other numbers are not available

MACOS System Boot and Installation

After completing the previous steps, you can see a gray virtual machine waiting to be started in the panel.

mac0

After clicking start, enter the VNC panel. The selection box on the left has a full-screen button. It is recommended to operate in full screen to avoid resolution issues.

mac00

After about 3 minutes of boot disk loading, a startup disk will be displayed on the left center of the screen. Click directly or press Enter.

After another 3-5 minutes of startup disk loading, four selection boxes will appear. Select Disk Utility and click to enter.

mac1

After entering, you can see three disks and one image. Find the disk larger than 40G named QEMU HARDDISK Media, and click Erase.

mac2

A pop-up window will appear, requiring you to rename the name to macos for easy identification and use later, then click Erase to continue initialization.

mac3

After initialization is complete, click Done.

mac4

Now you need to exit the Disk Utility interface. Click Disk Utility in the upper right corner and select Quit Disk Utility to exit the current selection box.

mac5

Then you return to the previous four selection boxes. Select Install macOS XXXX (since I am using Big Sur as an example, XXXX is Big Sur), and click continue.

mac6

In the following steps, continue clicking continue, then click Agree, and then Agree again.

mac7

mac8

mac9

Until those three disks appear again, but here you can see the disk larger than 40G named macos. Select it and click continue.

mac10

After a period of file copying and disk loading (about 12 minutes), you will formally enter the system installation phase. Choose your region based on where the host machine is located.

mac11

After selecting the region, continue clicking continue.

mac12

mac13

Until the Migration Assistant data migration option appears, select Not Now in the lower left corner to not import user data.

mac14

Then you will be prompted to create a user. Fill in the username, account name, and login password. After setting up, click continue.

mac15

After that, you will continue clicking continue until the system installation is complete.

Network Configuration

Since the system installation was performed in an offline environment, you need to manually configure a static network connection to the host's bridge.

Click the WIFI button in the upper right corner, turn off WIFI, and then click Network Preferences ...

mac16

After entering the settings interface, click the Advanced button to enter the advanced settings interface.

mac17

Fill in the static network configuration in the TCP/IP tab.

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx (replace xxx with the IP you want to bind, my vmid is 100, so I wrote 100 for convenience)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

If you need to configure an IPV6 network, similar to the IPV4 settings above, you will need to fill in the public IPV6 address bound to the virtual machine (written in the Note box in the PVE panel), subnet mask 128, and the default gateway obtained by executing cat /usr/local/bin/pve_check_ipv6 on the host.

mac18

Fill in the static network DNS configuration in the DNS tab.

Generally, adding 8.8.8.8 and 1.1.1.1 is sufficient. For use in mainland China, use 114.114.114.114.

mac19

After filling in and applying, the top left of the settings will show that the network is connected.

mac20

Now, opening the default browser and visiting any website will allow you to access public network resources, proving that the network has worked.

Remove ISO

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Macos system is to uninstall opencore.iso and xxxx (the system image used for installation).iso, similar to the Windows system uninstallation of win image and virtio image in the example picture above.

',90),M=[F];function P(I,B,q,E,z,V){return a(),s("div",null,M)}const G=e(x,[["render",P]]);export{N as __pageData,G as default}; diff --git a/assets/en_guide_pve_pve_macos.md.785a524c.lean.js b/assets/en_guide_pve_pve_macos.md.785a524c.lean.js deleted file mode 100644 index 1eaff24ddc..0000000000 --- a/assets/en_guide_pve_pve_macos.md.785a524c.lean.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as e,v as a,b as s,R as t}from"./chunks/framework.70afa331.js";import{_ as o}from"./chunks/wk7.776871bd.js";const n="/assets/mac0.935d53f3.png",i="/assets/mac00.4296be7b.png",l="/assets/mac1.3307e401.png",c="/assets/mac2.da6ce0bc.png",r="/assets/mac3.76a50b9f.png",p="/assets/mac4.c341ba50.png",d="/assets/mac5.39e1c9a4.png",m="/assets/mac6.1cc0462b.png",h="/assets/mac7.181275ae.png",u="/assets/mac8.dd556f02.png",y="/assets/mac9.c5d88eba.png",g="/assets/mac10.e9c284db.png",C="/assets/mac11.a7587e0e.png",f="/assets/mac12.06b051d3.png",b="/assets/mac13.7d4e3199.png",A="/assets/mac14.39a58b6a.png",k="/assets/mac15.f151793c.png",D="/assets/mac16.eae177db.png",w="/assets/mac17.be61913a.png",v="/assets/mac18.f9454618.png",_="/assets/mac19.845f5510.png",S="/assets/mac20.49a5800c.png",N=JSON.parse('{"title":"Setting Up MacOS Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_macos.md","filePath":"en/guide/pve/pve_macos.md","lastUpdated":1747972048000}'),x={name:"en/guide/pve/pve_macos.md"},F=t(`

Setting Up MacOS Virtual Machine

Prerequisites

System and hardware configuration requirements --> Environment detection

You can only set up a MacOS virtual machine when the environment detection confirms that the host machine supports KVM nested virtualization. Otherwise, it will be detected by hardware and cannot be set up.

Setting Up the Prerequisites

  • Automatically identify CPU type (AMD or Intel) and set nested virtualization parameters according to the type.
  • Modify GRUB boot parameters to enable IOMMU and disable default framebuffer.
  • Add VFIO module support for hardware device passthrough.
  • Blacklist sound card and graphics card driver modules to avoid conflicts with macOS.
  • Configure KVM-related kernel parameters, ignore MSR errors, and improve compatibility.
  • Patch Proxmox frontend status detection logic to bypass status restrictions.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

After successful execution, it will show that the system will restart in 15 seconds. This is the normal process, as kernel parameters cannot take effect without restarting.

System Image Download

  • All images have pre-installed components and are relatively large (minimum about 4.9GB). Download and extraction tasks will run in the background.
  • Images are complete systems with all components and can be booted and used without internet connection.
  • If the free space on the system disk is less than twice the size of the image, the download will be rejected.
  • Images are in 7z compressed format and need to be extracted before use.
  • You can check the status of current download and extraction tasks at any time. Virtual machines can only be created after completion.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh --lang=en

Or

shell
bash install_macos_images.sh --lang=en

After the background download task starts, you can close the SSH window and wait for 30 minutes to 3 hours (depending on your server bandwidth and connectivity) to download the ISO 7z compressed package.

When the download task is complete and the current download task query shows empty, you can choose to execute the extraction task. The waiting time for extraction depends on your server's CPU performance.

When the extraction task is complete and the current extraction task query shows empty, all preparations are ready.

Tasks of the same type can run concurrently, and any task can be canceled at any time by entering the PID value.

Build from https://github.com/oneclickvirt/macos currently supported image compressed packages:

# Listed by system release date from old to new
-high-sierra.iso.7z (Size: 5.23GB)
-mojave.iso.7z (Size: 6.03GB)
-catalina.iso.7z (Size: 8.33GB)
-big‑sur.iso.7z (Size: 12.21GB)
-monterey.iso.7z (Size: 12.36GB)
-ventura.iso.7z (Size: 12.31GB)
-sonoma.iso.7z (Size: 14.41GB)
-sequoia.iso.7z (Size: 15.02GB)

MACOS Virtual Machine Template Setup

  • Systems high-sierra, mojave, catalina require at least 2 cores, 4G of RAM and 40G of hard disk to run.
  • big-sur and newer MACOS systems require at least 6 cores, 6G RAM and 50G hard disk.
  • The newer the version of the system (the later the serial number of the download), the more hardware is required.
  • All images are boot disk images without any personal data, so disk allocation, login information setup, and network settings need to be manually configured according to the instructions.
  • You need to manually start the virtual machine from the web interface. Before starting, you can check if all templates meet your expectations.

Download Template Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

Parameter Meanings

shell
# ./buildvm_macos.sh VMID CPU_cores Memory Disk SSH_port VNC_port System Storage_disk Independent_IPV6(default_N_if_empty)

TIP

The disk size here is only the size of the virtual machine's disk. During the actual setup process, the program will also mount the boot disk and system image, so the actual disk requirement for setting up a virtual machine is virtual machine disk size + image size + boot disk size (500MB). Always be aware of whether your disk space is sufficient for setting up virtual machines.

Example Command

Using the oldest version (high-sierra) as an example, the supported configuration is as follows (very laggy)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

After the template is set up, you can run cat vm100 to view information, or check the NOTES in the corresponding VM in the WEB interface.

Here is the information for the example VM:

PropertyValue
VMID100
CPU cores2
Memory size4096MB
Disk size45G
SSH port44022
VNC port45901
Systemhigh-sierra
Host storage disklocal
Independent IPV6N

TIP

Note that VMID can only use numbers from 100 to 256, other numbers are not available

MACOS System Boot and Installation

After completing the previous steps, you can see a gray virtual machine waiting to be started in the panel.

mac0

After clicking start, enter the VNC panel. The selection box on the left has a full-screen button. It is recommended to operate in full screen to avoid resolution issues.

mac00

After about 3 minutes of boot disk loading, a startup disk will be displayed on the left center of the screen. Click directly or press Enter.

After another 3-5 minutes of startup disk loading, four selection boxes will appear. Select Disk Utility and click to enter.

mac1

After entering, you can see three disks and one image. Find the disk larger than 40G named QEMU HARDDISK Media, and click Erase.

mac2

A pop-up window will appear, requiring you to rename the name to macos for easy identification and use later, then click Erase to continue initialization.

mac3

After initialization is complete, click Done.

mac4

Now you need to exit the Disk Utility interface. Click Disk Utility in the upper right corner and select Quit Disk Utility to exit the current selection box.

mac5

Then you return to the previous four selection boxes. Select Install macOS XXXX (since I am using Big Sur as an example, XXXX is Big Sur), and click continue.

mac6

In the following steps, continue clicking continue, then click Agree, and then Agree again.

mac7

mac8

mac9

Until those three disks appear again, but here you can see the disk larger than 40G named macos. Select it and click continue.

mac10

After a period of file copying and disk loading (about 12 minutes), you will formally enter the system installation phase. Choose your region based on where the host machine is located.

mac11

After selecting the region, continue clicking continue.

mac12

mac13

Until the Migration Assistant data migration option appears, select Not Now in the lower left corner to not import user data.

mac14

Then you will be prompted to create a user. Fill in the username, account name, and login password. After setting up, click continue.

mac15

After that, you will continue clicking continue until the system installation is complete.

Network Configuration

Since the system installation was performed in an offline environment, you need to manually configure a static network connection to the host's bridge.

Click the WIFI button in the upper right corner, turn off WIFI, and then click Network Preferences ...

mac16

After entering the settings interface, click the Advanced button to enter the advanced settings interface.

mac17

Fill in the static network configuration in the TCP/IP tab.

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx (replace xxx with the IP you want to bind, my vmid is 100, so I wrote 100 for convenience)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

If you need to configure an IPV6 network, similar to the IPV4 settings above, you will need to fill in the public IPV6 address bound to the virtual machine (written in the Note box in the PVE panel), subnet mask 128, and the default gateway obtained by executing cat /usr/local/bin/pve_check_ipv6 on the host.

mac18

Fill in the static network DNS configuration in the DNS tab.

Generally, adding 8.8.8.8 and 1.1.1.1 is sufficient. For use in mainland China, use 114.114.114.114.

mac19

After filling in and applying, the top left of the settings will show that the network is connected.

mac20

Now, opening the default browser and visiting any website will allow you to access public network resources, proving that the network has worked.

Remove ISO

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Macos system is to uninstall opencore.iso and xxxx (the system image used for installation).iso, similar to the Windows system uninstallation of win image and virtio image in the example picture above.

',90),M=[F];function P(I,B,q,E,z,V){return a(),s("div",null,M)}const G=e(x,[["render",P]]);export{N as __pageData,G as default}; diff --git a/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.js b/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.js new file mode 100644 index 0000000000..45e59f21c1 --- /dev/null +++ b/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.js @@ -0,0 +1,9 @@ +import{_ as t}from"./chunks/wk7.BpuwpIoq.js";import{_ as a,c as s,o as i,ag as n}from"./chunks/framework.CSeR4K32.js";const o="/assets/mac0.CofQ9vw_.png",r="/assets/mac00.DelKhhmr.png",l="/assets/mac1.D7yJtJrl.png",c="/assets/mac2.du7V_m90.png",p="/assets/mac3.BCWQuf_Q.png",d="/assets/mac4.B0L5oLF9.png",h="/assets/mac5.QrcmrZyS.png",m="/assets/mac6.CEnQahaC.png",u="/assets/mac7.Cq44sm3y.png",g="/assets/mac8.CfhgXZ8s.png",k="/assets/mac9.DIA9P3VH.png",y="/assets/mac10.CZg7Yifb.png",b="/assets/mac11.P11nsmhn.png",f="/assets/mac12.DHTBO7ih.png",v="/assets/mac13.DDrsH3zK.png",F="/assets/mac14.dLHoMtJy.png",_="/assets/mac15.vkr7IxY1.png",C="/assets/mac16.CeB_3pKz.png",w="/assets/mac17.qkqeaTbW.png",x="/assets/mac18.ChbyoMxq.png",B="/assets/mac19.C_d085-7.png",S="/assets/mac20.DsWyqQaw.png",T=JSON.parse('{"title":"Setting Up MacOS Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_macos.md","filePath":"en/guide/pve/pve_macos.md","lastUpdated":1747984962000}'),E={name:"en/guide/pve/pve_macos.md"};function P(I,e,q,M,A,D){return i(),s("div",null,e[0]||(e[0]=[n(`

Setting Up MacOS Virtual Machine

Prerequisites

System and hardware configuration requirements --> Environment detection

You can only set up a MacOS virtual machine when the environment detection confirms that the host machine supports KVM nested virtualization. Otherwise, it will be detected by hardware and cannot be set up.

Setting Up the Prerequisites

  • Automatically identify CPU type (AMD or Intel) and set nested virtualization parameters according to the type.
  • Modify GRUB boot parameters to enable IOMMU and disable default framebuffer.
  • Add VFIO module support for hardware device passthrough.
  • Blacklist sound card and graphics card driver modules to avoid conflicts with macOS.
  • Configure KVM-related kernel parameters, ignore MSR errors, and improve compatibility.
  • Patch Proxmox frontend status detection logic to bypass status restrictions.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

After successful execution, it will show that the system will restart in 15 seconds. This is the normal process, as kernel parameters cannot take effect without restarting.

System Image Download

  • All images have pre-installed components and are relatively large (minimum about 4.9GB). Download and extraction tasks will run in the background.
  • Images are complete systems with all components and can be booted and used without internet connection.
  • If the free space on the system disk is less than twice the size of the image, the download will be rejected.
  • Images are in 7z compressed format and need to be extracted before use.
  • You can check the status of current download and extraction tasks at any time. Virtual machines can only be created after completion.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh --lang=en

Or

shell
bash install_macos_images.sh --lang=en

After the background download task starts, you can close the SSH window and wait for 30 minutes to 3 hours (depending on your server bandwidth and connectivity) to download the ISO 7z compressed package.

When the download task is complete and the current download task query shows empty, you can choose to execute the extraction task. The waiting time for extraction depends on your server's CPU performance.

When the extraction task is complete and the current extraction task query shows empty, all preparations are ready.

Tasks of the same type can run concurrently, and any task can be canceled at any time by entering the PID value.

Build from https://github.com/oneclickvirt/macos currently supported image compressed packages:

# Listed by system release date from old to new
+high-sierra.iso.7z (Size: 5.23GB)
+mojave.iso.7z (Size: 6.03GB)
+catalina.iso.7z (Size: 8.33GB)
+big‑sur.iso.7z (Size: 12.21GB)
+monterey.iso.7z (Size: 12.36GB)
+ventura.iso.7z (Size: 12.31GB)
+sonoma.iso.7z (Size: 14.41GB)
+sequoia.iso.7z (Size: 15.02GB)

MACOS Virtual Machine Template Setup

  • Systems high-sierra, mojave, catalina require at least 2 cores, 4G of RAM and 40G of hard disk to run.
  • big-sur and newer MACOS systems require at least 6 cores, 6G RAM and 50G hard disk.
  • The newer the version of the system (the later the serial number of the download), the more hardware is required.
  • All images are boot disk images without any personal data, so disk allocation, login information setup, and network settings need to be manually configured according to the instructions.
  • You need to manually start the virtual machine from the web interface. Before starting, you can check if all templates meet your expectations.

Download Template Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

Parameter Meanings

shell
# ./buildvm_macos.sh VMID CPU_cores Memory Disk SSH_port VNC_port System Storage_disk Independent_IPV6(default_N_if_empty)

TIP

The disk size here is only the size of the virtual machine's disk. During the actual setup process, the program will also mount the boot disk and system image, so the actual disk requirement for setting up a virtual machine is virtual machine disk size + image size + boot disk size (500MB). Always be aware of whether your disk space is sufficient for setting up virtual machines.

Example Command

Using the oldest version (high-sierra) as an example, the supported configuration is as follows (very laggy)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

After the template is set up, you can run cat vm100 to view information, or check the NOTES in the corresponding VM in the WEB interface.

Here is the information for the example VM:

PropertyValue
VMID100
CPU cores2
Memory size4096MB
Disk size45G
SSH port44022
VNC port45901
Systemhigh-sierra
Host storage disklocal
Independent IPV6N

TIP

Note that VMID can only use numbers from 100 to 256, other numbers are not available

MACOS System Boot and Installation

After completing the previous steps, you can see a gray virtual machine waiting to be started in the panel.

mac0

After clicking start, enter the VNC panel. The selection box on the left has a full-screen button. It is recommended to operate in full screen to avoid resolution issues.

mac00

After about 3 minutes of boot disk loading, a startup disk will be displayed on the left center of the screen. Click directly or press Enter.

After another 3-5 minutes of startup disk loading, four selection boxes will appear. Select Disk Utility and click to enter.

mac1

After entering, you can see three disks and one image. Find the disk larger than 40G named QEMU HARDDISK Media, and click Erase.

mac2

A pop-up window will appear, requiring you to rename the name to macos for easy identification and use later, then click Erase to continue initialization.

mac3

After initialization is complete, click Done.

mac4

Now you need to exit the Disk Utility interface. Click Disk Utility in the upper right corner and select Quit Disk Utility to exit the current selection box.

mac5

Then you return to the previous four selection boxes. Select Install macOS XXXX (since I am using Big Sur as an example, XXXX is Big Sur), and click continue.

mac6

In the following steps, continue clicking continue, then click Agree, and then Agree again.

mac7

mac8

mac9

Until those three disks appear again, but here you can see the disk larger than 40G named macos. Select it and click continue.

mac10

After a period of file copying and disk loading (about 12 minutes), you will formally enter the system installation phase. Choose your region based on where the host machine is located.

mac11

After selecting the region, continue clicking continue.

mac12

mac13

Until the Migration Assistant data migration option appears, select Not Now in the lower left corner to not import user data.

mac14

Then you will be prompted to create a user. Fill in the username, account name, and login password. After setting up, click continue.

mac15

After that, you will continue clicking continue until the system installation is complete.

Network Configuration

Since the system installation was performed in an offline environment, you need to manually configure a static network connection to the host's bridge.

Click the WIFI button in the upper right corner, turn off WIFI, and then click Network Preferences ...

mac16

After entering the settings interface, click the Advanced button to enter the advanced settings interface.

mac17

Fill in the static network configuration in the TCP/IP tab.

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx (replace xxx with the IP you want to bind, my vmid is 100, so I wrote 100 for convenience)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

If you need to configure an IPV6 network, similar to the IPV4 settings above, you will need to fill in the public IPV6 address bound to the virtual machine (written in the Note box in the PVE panel), subnet mask 128, and the default gateway obtained by executing cat /usr/local/bin/pve_check_ipv6 on the host.

mac18

Fill in the static network DNS configuration in the DNS tab.

Generally, adding 8.8.8.8 and 1.1.1.1 is sufficient. For use in mainland China, use 114.114.114.114.

mac19

After filling in and applying, the top left of the settings will show that the network is connected.

mac20

Now, opening the default browser and visiting any website will allow you to access public network resources, proving that the network has worked.

Remove ISO

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Macos system is to uninstall opencore.iso and xxxx (the system image used for installation).iso, similar to the Windows system uninstallation of win image and virtio image in the example picture above.

',90)]))}const N=a(E,[["render",P]]);export{T as __pageData,N as default}; diff --git a/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.lean.js b/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.lean.js new file mode 100644 index 0000000000..fc15819295 --- /dev/null +++ b/assets/en_guide_pve_pve_macos.md.Cy9mzi8X.lean.js @@ -0,0 +1 @@ +import{_ as t}from"./chunks/wk7.BpuwpIoq.js";import{_ as a,c as s,o as i,ag as n}from"./chunks/framework.CSeR4K32.js";const o="/assets/mac0.CofQ9vw_.png",r="/assets/mac00.DelKhhmr.png",l="/assets/mac1.D7yJtJrl.png",c="/assets/mac2.du7V_m90.png",p="/assets/mac3.BCWQuf_Q.png",d="/assets/mac4.B0L5oLF9.png",h="/assets/mac5.QrcmrZyS.png",m="/assets/mac6.CEnQahaC.png",u="/assets/mac7.Cq44sm3y.png",g="/assets/mac8.CfhgXZ8s.png",k="/assets/mac9.DIA9P3VH.png",y="/assets/mac10.CZg7Yifb.png",b="/assets/mac11.P11nsmhn.png",f="/assets/mac12.DHTBO7ih.png",v="/assets/mac13.DDrsH3zK.png",F="/assets/mac14.dLHoMtJy.png",_="/assets/mac15.vkr7IxY1.png",C="/assets/mac16.CeB_3pKz.png",w="/assets/mac17.qkqeaTbW.png",x="/assets/mac18.ChbyoMxq.png",B="/assets/mac19.C_d085-7.png",S="/assets/mac20.DsWyqQaw.png",T=JSON.parse('{"title":"Setting Up MacOS Virtual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_macos.md","filePath":"en/guide/pve/pve_macos.md","lastUpdated":1747984962000}'),E={name:"en/guide/pve/pve_macos.md"};function P(I,e,q,M,A,D){return i(),s("div",null,e[0]||(e[0]=[n("",90)]))}const N=a(E,[["render",P]]);export{T as __pageData,N as default}; diff --git a/assets/en_guide_pve_pve_precheck.md.2c6a4e25.js b/assets/en_guide_pve_pve_precheck.md.2c6a4e25.js deleted file mode 100644 index 5f488f49a0..0000000000 --- a/assets/en_guide_pve_pve_precheck.md.2c6a4e25.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const o="/assets/pve_kvm_1.0f7e84f0.png",n="/assets/pve_kvm_2.cefb9578.png",r="/assets/pve_kvm_3.1d307586.png",v=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_precheck.md","filePath":"en/guide/pve/pve_precheck.md","lastUpdated":1747972048000}'),i={name:"en/guide/pve/pve_precheck.md"},l=a(`

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If there are unadapted merchants or machines welcome to contact @spiritlhl_bot, will try to support it sometime!

WARNING

Will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running it.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/pve

Various requirements

It is recommended that debian try to use the latest stable version of the system before use.

Do not use this set of scripts in the dynamic IP server (reboot the machine automatically switch the local IP server is not supported, reboot the machine after the IP does not automatically switch the support)

The one-click installation script of this project only adapts to Debian systems, non-Debian can not be installed through the APT source, the official only gives the image of Debian, other systems can only use the ISO installation, or use custom partitions and other ways to solve the problem in the FAQ partition.

  • System requirements: Debian 8+

TIP

It is recommended to install debian11 instead of debian12, because the latter is a beta version, and the debian11 installation is the stable version.

  • Hardware requirements: 2 cores 2G RAM x86_64 or arm architecture server hard disk at least 20G
  • Hardware requirements for KVM: VM-X or AMD-V support (some VPS and all Dedicated servers support).
  • If hardware or system requirements are not met, you can use incus to batch open LXC containers Jump

If you use IPV6 tunnels for IPV6 subnet attachment on the host, be sure to add the contents in the corresponding file when PVE is successfully installed but the gateway is not automatically set, and do not add IPV6 tunnels at the very beginning (without installing PVE).

Setting up virtual memory (SWAP) (optional, not required)

TIP

Memory to open some swap lest the machine blow up, if your host computer does not have enough memory and a lot of free hard disk.

Unit conversion: Enter 1024 to generate 1G SWAP-virtual memory, virtual memory takes up hard disk space, when the actual memory is not enough to use the virtual memory will automatically use the virtual memory for memory use, but then bring the IO high occupancy and CPU performance occupancy!

It is recommended to use only twice the size of the actual memory as virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Detecting the environment

  • This project related scripts must be executed before the execution of this script to detect the environment, if it does not meet the requirements of the installation of PVE will not be able to use the subsequent scripts
  • Detection of the local IPV6 network configuration (with or without IPV6 can be installed, just query)
  • Detection of the hardware configuration meets the minimum requirements
  • Detection of the hardware environment can be nested virtualization KVM type of servers, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • Detect whether the system environment can be nested virtualization KVM type of server, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • can not be nested virtualization KVM servers do not recommend the installation of the PVE, it is better to use incus for better performance.

Command:

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

If you need to update the IPV6 information before querying, then execute the following command before querying

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

Commands to set up the testing environment for executing this project are as follows:

图片

To perform the above-mentioned query, you only need to use the one-click script below to automatically create a virtual machine. There is no need to manually modify settings on the web interface.

图片

After creating the virtual machines using the subsequent script as mentioned above, it may be necessary to manually modify the settings on the web interface. You will need to disable hardware nested virtualization for each respective virtual machine, as shown in the following diagram.

图片

Stop the virtual machine before making modifications. After the modifications are done, you can start the machine to use NOVNC. Failure to close it may result in bugs that render this virtual machine unusable.

If you forcibly install PVE to enable KVM, even if the startup fails, you can also disable this option and try to start the virtual machine to see if it works.

The reason for these issues is what was stated above, the host does not support nested virtualized KVMs for acceleration.

TIP

Please use the "screen" command to suspend execution before launching the virtual machine, in order to avoid prolonged startup times. Unstable SSH connections could lead to interruptions during the intermediate execution.



',37),p=[l];function c(h,u,m,d,y,b){return t(),s("div",null,p)}const g=e(i,[["render",c]]);export{v as __pageData,g as default}; diff --git a/assets/en_guide_pve_pve_precheck.md.2c6a4e25.lean.js b/assets/en_guide_pve_pve_precheck.md.2c6a4e25.lean.js deleted file mode 100644 index 5f488f49a0..0000000000 --- a/assets/en_guide_pve_pve_precheck.md.2c6a4e25.lean.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const o="/assets/pve_kvm_1.0f7e84f0.png",n="/assets/pve_kvm_2.cefb9578.png",r="/assets/pve_kvm_3.1d307586.png",v=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_precheck.md","filePath":"en/guide/pve/pve_precheck.md","lastUpdated":1747972048000}'),i={name:"en/guide/pve/pve_precheck.md"},l=a(`

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If there are unadapted merchants or machines welcome to contact @spiritlhl_bot, will try to support it sometime!

WARNING

Will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running it.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/pve

Various requirements

It is recommended that debian try to use the latest stable version of the system before use.

Do not use this set of scripts in the dynamic IP server (reboot the machine automatically switch the local IP server is not supported, reboot the machine after the IP does not automatically switch the support)

The one-click installation script of this project only adapts to Debian systems, non-Debian can not be installed through the APT source, the official only gives the image of Debian, other systems can only use the ISO installation, or use custom partitions and other ways to solve the problem in the FAQ partition.

  • System requirements: Debian 8+

TIP

It is recommended to install debian11 instead of debian12, because the latter is a beta version, and the debian11 installation is the stable version.

  • Hardware requirements: 2 cores 2G RAM x86_64 or arm architecture server hard disk at least 20G
  • Hardware requirements for KVM: VM-X or AMD-V support (some VPS and all Dedicated servers support).
  • If hardware or system requirements are not met, you can use incus to batch open LXC containers Jump

If you use IPV6 tunnels for IPV6 subnet attachment on the host, be sure to add the contents in the corresponding file when PVE is successfully installed but the gateway is not automatically set, and do not add IPV6 tunnels at the very beginning (without installing PVE).

Setting up virtual memory (SWAP) (optional, not required)

TIP

Memory to open some swap lest the machine blow up, if your host computer does not have enough memory and a lot of free hard disk.

Unit conversion: Enter 1024 to generate 1G SWAP-virtual memory, virtual memory takes up hard disk space, when the actual memory is not enough to use the virtual memory will automatically use the virtual memory for memory use, but then bring the IO high occupancy and CPU performance occupancy!

It is recommended to use only twice the size of the actual memory as virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Detecting the environment

  • This project related scripts must be executed before the execution of this script to detect the environment, if it does not meet the requirements of the installation of PVE will not be able to use the subsequent scripts
  • Detection of the local IPV6 network configuration (with or without IPV6 can be installed, just query)
  • Detection of the hardware configuration meets the minimum requirements
  • Detection of the hardware environment can be nested virtualization KVM type of servers, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • Detect whether the system environment can be nested virtualization KVM type of server, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • can not be nested virtualization KVM servers do not recommend the installation of the PVE, it is better to use incus for better performance.

Command:

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

If you need to update the IPV6 information before querying, then execute the following command before querying

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

Commands to set up the testing environment for executing this project are as follows:

图片

To perform the above-mentioned query, you only need to use the one-click script below to automatically create a virtual machine. There is no need to manually modify settings on the web interface.

图片

After creating the virtual machines using the subsequent script as mentioned above, it may be necessary to manually modify the settings on the web interface. You will need to disable hardware nested virtualization for each respective virtual machine, as shown in the following diagram.

图片

Stop the virtual machine before making modifications. After the modifications are done, you can start the machine to use NOVNC. Failure to close it may result in bugs that render this virtual machine unusable.

If you forcibly install PVE to enable KVM, even if the startup fails, you can also disable this option and try to start the virtual machine to see if it works.

The reason for these issues is what was stated above, the host does not support nested virtualized KVMs for acceleration.

TIP

Please use the "screen" command to suspend execution before launching the virtual machine, in order to avoid prolonged startup times. Unstable SSH connections could lead to interruptions during the intermediate execution.



',37),p=[l];function c(h,u,m,d,y,b){return t(),s("div",null,p)}const g=e(i,[["render",c]]);export{v as __pageData,g as default}; diff --git a/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.js b/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.js new file mode 100644 index 0000000000..9166956b7c --- /dev/null +++ b/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.js @@ -0,0 +1,3 @@ +import{_ as t,c as i,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const n="/assets/pve_kvm_1.BEDy-Dxt.png",o="/assets/pve_kvm_2.C98l0GO8.png",r="/assets/pve_kvm_3.DzuyyWMo.png",g=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_precheck.md","filePath":"en/guide/pve/pve_precheck.md","lastUpdated":1747984962000}'),l={name:"en/guide/pve/pve_precheck.md"};function h(p,e,c,d,u,m){return s(),i("div",null,e[0]||(e[0]=[a(`

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If there are unadapted merchants or machines welcome to contact @spiritlhl_bot, will try to support it sometime!

WARNING

Will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running it.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/pve

Various requirements

It is recommended that debian try to use the latest stable version of the system before use.

Do not use this set of scripts in the dynamic IP server (reboot the machine automatically switch the local IP server is not supported, reboot the machine after the IP does not automatically switch the support)

The one-click installation script of this project only adapts to Debian systems, non-Debian can not be installed through the APT source, the official only gives the image of Debian, other systems can only use the ISO installation, or use custom partitions and other ways to solve the problem in the FAQ partition.

  • System requirements: Debian 8+

TIP

It is recommended to install debian11 instead of debian12, because the latter is a beta version, and the debian11 installation is the stable version.

  • Hardware requirements: 2 cores 2G RAM x86_64 or arm architecture server hard disk at least 20G
  • Hardware requirements for KVM: VM-X or AMD-V support (some VPS and all Dedicated servers support).
  • If hardware or system requirements are not met, you can use incus to batch open LXC containers Jump

If you use IPV6 tunnels for IPV6 subnet attachment on the host, be sure to add the contents in the corresponding file when PVE is successfully installed but the gateway is not automatically set, and do not add IPV6 tunnels at the very beginning (without installing PVE).

Setting up virtual memory (SWAP) (optional, not required)

TIP

Memory to open some swap lest the machine blow up, if your host computer does not have enough memory and a lot of free hard disk.

Unit conversion: Enter 1024 to generate 1G SWAP-virtual memory, virtual memory takes up hard disk space, when the actual memory is not enough to use the virtual memory will automatically use the virtual memory for memory use, but then bring the IO high occupancy and CPU performance occupancy!

It is recommended to use only twice the size of the actual memory as virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Detecting the environment

  • This project related scripts must be executed before the execution of this script to detect the environment, if it does not meet the requirements of the installation of PVE will not be able to use the subsequent scripts
  • Detection of the local IPV6 network configuration (with or without IPV6 can be installed, just query)
  • Detection of the hardware configuration meets the minimum requirements
  • Detection of the hardware environment can be nested virtualization KVM type of servers, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • Detect whether the system environment can be nested virtualization KVM type of server, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • can not be nested virtualization KVM servers do not recommend the installation of the PVE, it is better to use incus for better performance.

Command:

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

If you need to update the IPV6 information before querying, then execute the following command before querying

bash
rm -rf /usr/local/bin/pve_ipv6*
+rm -rf /usr/local/bin/pve_check_ipv6*
+rm -rf /usr/local/bin/pve_last_ipv6*

Commands to set up the testing environment for executing this project are as follows:

图片

To perform the above-mentioned query, you only need to use the one-click script below to automatically create a virtual machine. There is no need to manually modify settings on the web interface.

图片

After creating the virtual machines using the subsequent script as mentioned above, it may be necessary to manually modify the settings on the web interface. You will need to disable hardware nested virtualization for each respective virtual machine, as shown in the following diagram.

图片

Stop the virtual machine before making modifications. After the modifications are done, you can start the machine to use NOVNC. Failure to close it may result in bugs that render this virtual machine unusable.

If you forcibly install PVE to enable KVM, even if the startup fails, you can also disable this option and try to start the virtual machine to see if it works.

The reason for these issues is what was stated above, the host does not support nested virtualized KVMs for acceleration.

TIP

Please use the "screen" command to suspend execution before launching the virtual machine, in order to avoid prolonged startup times. Unstable SSH connections could lead to interruptions during the intermediate execution.



',37)]))}const b=t(l,[["render",h]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.lean.js b/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.lean.js new file mode 100644 index 0000000000..4a20844e3a --- /dev/null +++ b/assets/en_guide_pve_pve_precheck.md.Dc6vpMBO.lean.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as s,ag as a}from"./chunks/framework.CSeR4K32.js";const n="/assets/pve_kvm_1.BEDy-Dxt.png",o="/assets/pve_kvm_2.C98l0GO8.png",r="/assets/pve_kvm_3.DzuyyWMo.png",g=JSON.parse('{"title":"Preface","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_precheck.md","filePath":"en/guide/pve/pve_precheck.md","lastUpdated":1747984962000}'),l={name:"en/guide/pve/pve_precheck.md"};function h(p,e,c,d,u,m){return s(),i("div",null,e[0]||(e[0]=[a("",37)]))}const b=t(l,[["render",h]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_qa.md.3406e13c.js b/assets/en_guide_pve_pve_qa.md.3406e13c.js deleted file mode 100644 index 0469a98290..0000000000 --- a/assets/en_guide_pve_pve_qa.md.3406e13c.js +++ /dev/null @@ -1,13 +0,0 @@ -import{_ as e,v as s,b as a,R as t}from"./chunks/framework.70afa331.js";const o="/assets/onlinepkg.30da8d76.png",n="/assets/dns0.1beb9fa7.png",g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_qa.md","filePath":"en/guide/pve/pve_qa.md","lastUpdated":1747972048000}'),l={name:"en/guide/pve/pve_qa.md"},r=t(`

Solve the puzzle

Within 30 seconds of executing the script, the machine dropped.

Original system execution

systemctl restart networking

See if it is not directly offline, if so that is the machine native problem, hot plug or dhcp caused by the network can not restart, it is recommended to replace the host system or DD a new system to try!

Generally speaking, this situation occurs in the exclusive service Debian11 system, switch to Debian12 system will not be a problem!

Installation of PVE fails with an error saying that some packages do not exist.

Execute the following command to query the source of apt

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

If you see

deb file://
-deb cdrom:[

A line starting like this proves that the host is using local sources instead of network sources, and you need to replace the sources in /etc/apt/sources.list with a line such as

pct

Replace the network source with the same to install using the PVE one-click install script.

Replacing the network source can be done using the following command for apt source replacement

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

Successful PVE Installation but Lost Connection After Reboot

If the machine successfully installs PVE and the web interface is accessible, but loses connection after a reboot, please execute the following commands after a successful PVE installation and before rebooting:

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

Then report the rebooted disconnected machine to @spiritlhl_bot for the script to be updated and repaired automatically.

Successful PVE Installation but can not resolve host after reboot

Common in low version of Debian system (cloud server) after installing PVE reboot no matter what URL to visit the report error

curl: (6) Could not resolve host:

View the file at this time

cat /etc/resolv.conf

Statements beginning with nameserver may be found to be absent.

You need to set up DNS on this web page

screenshot-1708136079861

After setting up the DNS, check the file again and you will find the following content

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

At this point, requesting any URL again will resolve it successfully

PVE Installation Failed

If you encounter any issues with installing on certain machines, and if you're in a hurry, you can try using the scripts from the following repository to reinstall as Debian 11 first.

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

The system username after dd at this point is root, and the password is oneclickvirt139.

If it doesn't work, check the issues and descriptions in https://github.com/leitbogioro/Tools A common problem is that the machine is raid0 not raid10, and you need to add a parameter to specify the value of the raid.

If you have time or if it's still not working, please contact @spiritlhl_bot for assistance.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the \`\`\`/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT\`\`, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

What to do if you accidentally delete a NAT mapping rule

Use the following command to map back

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

Adding a New Node to an Existing PVE Cluster (Create / Join Cluster)

To form a cluster from two independent Proxmox VE instances, the following prerequisites must be met:

Cluster Prerequisites

  1. Unique Hostnames
    The hostname of each node must be unique to avoid conflicts. It is recommended to use names like pve1, pve2, etc.

  2. Unique VMIDs
    There must be no duplicate VMIDs across the two PVE nodes. If conflicts exist, adjust the VMIDs beforehand to prevent issues during cluster merge.

  3. Network Connectivity & Low Latency
    Both nodes must be able to ping each other. A low-latency network (LAN or high-speed public connection) is recommended for reliable cluster communication.

Creating the Cluster (Run on Any Node)

  1. Log in to the web interface of the node where the cluster will be created (e.g., pve1).
  2. Navigate to: Datacenter → Cluster → Create Cluster.
  3. Enter a name for the cluster (Cluster Name).
  4. Select the network interface to be used for cluster communication (e.g., public IP if only one interface is available).
  5. Click Create to initialize the cluster.
  6. Once the cluster is created, click Join Information and copy the displayed information for use on the joining node.

Note: The cluster has no "master" or "slave" nodes—any node can be the one that initiates the cluster.

Joining the Cluster (Run on the Second Node)

  1. Log in to the web interface of the node to be added (e.g., pve2).
  2. Navigate to: Datacenter → Cluster → Join Cluster.
  3. Paste the Join Information from pve1 into the input field.
  4. Enter the password of root user on pve1 in the Peer Password field.
  5. Click Join to begin the joining process.
  6. Wait until the process completes successfully, then refresh the page or re-login. You should now see both nodes in the same cluster.

Cluster Benefits

  • Nodes can share resources and migrate virtual machines.
  • ISO images and templates can be transferred more conveniently between nodes.

Verified VPS Providers

VPS Providers Offering KVM Virtualization with NAT

spartanhost Debian12 on a Dedicated Server (Debian11 has problems)

interserver VPS or dedicated servers

frantech Las Vegas Tier 2

eugamehost US Phoenix Black Friday Special

amhost Testing version

digitalocean Perminu Intel and Regular 4-core versions

skrime Lowest configuration of AMD Ryzen KVM Server

webdock AMD KVM Server

4vps Russian and Greek testing versions

adtaq Storage KVM server with lowest configuration

nocix Dedicated servers

online.net Debian12 on a Dedicated Server (Debian11 has problems)

OVH Public Cloud needs to be installed after dd as a pure system using the following command

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd ' oneclickvirt139' --network "static"

At this point, the system username after dd is root, and the password is oneclickvirt139.

If it doesn't work, please check the issues and instructions in https://github.com/leitbogioro/Tools. A common problem is that OVH standalone servers are dd'd, which requires the source system to be remounted as raid1 on debian12 by default, and then parameterized to specify dd'd as raid0 in order to be successful, using the following command

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

VPS Providers Offering NAT with LXC Virtualization

Tencent Cloud Worry-Free and Student editions

spectraip KVM servers

Linode Lowest configuration with dedicated CPU

hosthatch Special high-configuration servers

hetzner Cloud servers

rackdog Servers with floating IP

vultr Standard Cloud servers

azure Standard machines

scaleway ARM architecture servers

aws EC2 servers

Google cloud platform - GCP AMD servers

`,91),p=[r];function i(c,h,d,u,y,C){return s(),a("div",null,p)}const b=e(l,[["render",i]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_qa.md.3406e13c.lean.js b/assets/en_guide_pve_pve_qa.md.3406e13c.lean.js deleted file mode 100644 index 0469a98290..0000000000 --- a/assets/en_guide_pve_pve_qa.md.3406e13c.lean.js +++ /dev/null @@ -1,13 +0,0 @@ -import{_ as e,v as s,b as a,R as t}from"./chunks/framework.70afa331.js";const o="/assets/onlinepkg.30da8d76.png",n="/assets/dns0.1beb9fa7.png",g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_qa.md","filePath":"en/guide/pve/pve_qa.md","lastUpdated":1747972048000}'),l={name:"en/guide/pve/pve_qa.md"},r=t(`

Solve the puzzle

Within 30 seconds of executing the script, the machine dropped.

Original system execution

systemctl restart networking

See if it is not directly offline, if so that is the machine native problem, hot plug or dhcp caused by the network can not restart, it is recommended to replace the host system or DD a new system to try!

Generally speaking, this situation occurs in the exclusive service Debian11 system, switch to Debian12 system will not be a problem!

Installation of PVE fails with an error saying that some packages do not exist.

Execute the following command to query the source of apt

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

If you see

deb file://
-deb cdrom:[

A line starting like this proves that the host is using local sources instead of network sources, and you need to replace the sources in /etc/apt/sources.list with a line such as

pct

Replace the network source with the same to install using the PVE one-click install script.

Replacing the network source can be done using the following command for apt source replacement

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

Successful PVE Installation but Lost Connection After Reboot

If the machine successfully installs PVE and the web interface is accessible, but loses connection after a reboot, please execute the following commands after a successful PVE installation and before rebooting:

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

Then report the rebooted disconnected machine to @spiritlhl_bot for the script to be updated and repaired automatically.

Successful PVE Installation but can not resolve host after reboot

Common in low version of Debian system (cloud server) after installing PVE reboot no matter what URL to visit the report error

curl: (6) Could not resolve host:

View the file at this time

cat /etc/resolv.conf

Statements beginning with nameserver may be found to be absent.

You need to set up DNS on this web page

screenshot-1708136079861

After setting up the DNS, check the file again and you will find the following content

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

At this point, requesting any URL again will resolve it successfully

PVE Installation Failed

If you encounter any issues with installing on certain machines, and if you're in a hurry, you can try using the scripts from the following repository to reinstall as Debian 11 first.

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

The system username after dd at this point is root, and the password is oneclickvirt139.

If it doesn't work, check the issues and descriptions in https://github.com/leitbogioro/Tools A common problem is that the machine is raid0 not raid10, and you need to add a parameter to specify the value of the raid.

If you have time or if it's still not working, please contact @spiritlhl_bot for assistance.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the \`\`\`/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT\`\`, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

What to do if you accidentally delete a NAT mapping rule

Use the following command to map back

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

Adding a New Node to an Existing PVE Cluster (Create / Join Cluster)

To form a cluster from two independent Proxmox VE instances, the following prerequisites must be met:

Cluster Prerequisites

  1. Unique Hostnames
    The hostname of each node must be unique to avoid conflicts. It is recommended to use names like pve1, pve2, etc.

  2. Unique VMIDs
    There must be no duplicate VMIDs across the two PVE nodes. If conflicts exist, adjust the VMIDs beforehand to prevent issues during cluster merge.

  3. Network Connectivity & Low Latency
    Both nodes must be able to ping each other. A low-latency network (LAN or high-speed public connection) is recommended for reliable cluster communication.

Creating the Cluster (Run on Any Node)

  1. Log in to the web interface of the node where the cluster will be created (e.g., pve1).
  2. Navigate to: Datacenter → Cluster → Create Cluster.
  3. Enter a name for the cluster (Cluster Name).
  4. Select the network interface to be used for cluster communication (e.g., public IP if only one interface is available).
  5. Click Create to initialize the cluster.
  6. Once the cluster is created, click Join Information and copy the displayed information for use on the joining node.

Note: The cluster has no "master" or "slave" nodes—any node can be the one that initiates the cluster.

Joining the Cluster (Run on the Second Node)

  1. Log in to the web interface of the node to be added (e.g., pve2).
  2. Navigate to: Datacenter → Cluster → Join Cluster.
  3. Paste the Join Information from pve1 into the input field.
  4. Enter the password of root user on pve1 in the Peer Password field.
  5. Click Join to begin the joining process.
  6. Wait until the process completes successfully, then refresh the page or re-login. You should now see both nodes in the same cluster.

Cluster Benefits

  • Nodes can share resources and migrate virtual machines.
  • ISO images and templates can be transferred more conveniently between nodes.

Verified VPS Providers

VPS Providers Offering KVM Virtualization with NAT

spartanhost Debian12 on a Dedicated Server (Debian11 has problems)

interserver VPS or dedicated servers

frantech Las Vegas Tier 2

eugamehost US Phoenix Black Friday Special

amhost Testing version

digitalocean Perminu Intel and Regular 4-core versions

skrime Lowest configuration of AMD Ryzen KVM Server

webdock AMD KVM Server

4vps Russian and Greek testing versions

adtaq Storage KVM server with lowest configuration

nocix Dedicated servers

online.net Debian12 on a Dedicated Server (Debian11 has problems)

OVH Public Cloud needs to be installed after dd as a pure system using the following command

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd ' oneclickvirt139' --network "static"

At this point, the system username after dd is root, and the password is oneclickvirt139.

If it doesn't work, please check the issues and instructions in https://github.com/leitbogioro/Tools. A common problem is that OVH standalone servers are dd'd, which requires the source system to be remounted as raid1 on debian12 by default, and then parameterized to specify dd'd as raid0 in order to be successful, using the following command

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

VPS Providers Offering NAT with LXC Virtualization

Tencent Cloud Worry-Free and Student editions

spectraip KVM servers

Linode Lowest configuration with dedicated CPU

hosthatch Special high-configuration servers

hetzner Cloud servers

rackdog Servers with floating IP

vultr Standard Cloud servers

azure Standard machines

scaleway ARM architecture servers

aws EC2 servers

Google cloud platform - GCP AMD servers

`,91),p=[r];function i(c,h,d,u,y,C){return s(),a("div",null,p)}const b=e(l,[["render",i]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_qa.md.BYBr2UQn.js b/assets/en_guide_pve_pve_qa.md.BYBr2UQn.js new file mode 100644 index 0000000000..54daf9a0ea --- /dev/null +++ b/assets/en_guide_pve_pve_qa.md.BYBr2UQn.js @@ -0,0 +1,13 @@ +import{_ as s,c as t,o as a,ag as i}from"./chunks/framework.CSeR4K32.js";const n="/assets/onlinepkg.-C5qKOrj.png",r="/assets/dns0.DDagSewr.png",g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_qa.md","filePath":"en/guide/pve/pve_qa.md","lastUpdated":1747984962000}'),o={name:"en/guide/pve/pve_qa.md"};function l(h,e,p,d,c,k){return a(),t("div",null,e[0]||(e[0]=[i(`

Solve the puzzle

Within 30 seconds of executing the script, the machine dropped.

Original system execution

systemctl restart networking

See if it is not directly offline, if so that is the machine native problem, hot plug or dhcp caused by the network can not restart, it is recommended to replace the host system or DD a new system to try!

Generally speaking, this situation occurs in the exclusive service Debian11 system, switch to Debian12 system will not be a problem!

Installation of PVE fails with an error saying that some packages do not exist.

Execute the following command to query the source of apt

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

If you see

deb file://
+deb cdrom:[

A line starting like this proves that the host is using local sources instead of network sources, and you need to replace the sources in /etc/apt/sources.list with a line such as

pct

Replace the network source with the same to install using the PVE one-click install script.

Replacing the network source can be done using the following command for apt source replacement

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

Successful PVE Installation but Lost Connection After Reboot

If the machine successfully installs PVE and the web interface is accessible, but loses connection after a reboot, please execute the following commands after a successful PVE installation and before rebooting:

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
+if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
+    chattr -i /etc/network/interfaces
+    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
+    chattr +i /etc/network/interfaces
+fi

Then report the rebooted disconnected machine to @spiritlhl_bot for the script to be updated and repaired automatically.

Successful PVE Installation but can not resolve host after reboot

Common in low version of Debian system (cloud server) after installing PVE reboot no matter what URL to visit the report error

curl: (6) Could not resolve host:

View the file at this time

cat /etc/resolv.conf

Statements beginning with nameserver may be found to be absent.

You need to set up DNS on this web page

screenshot-1708136079861

After setting up the DNS, check the file again and you will find the following content

search .
+nameserver 8.8.8.8
+nameserver 8.8.4.4

At this point, requesting any URL again will resolve it successfully

PVE Installation Failed

If you encounter any issues with installing on certain machines, and if you're in a hurry, you can try using the scripts from the following repository to reinstall as Debian 11 first.

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

The system username after dd at this point is root, and the password is oneclickvirt139.

If it doesn't work, check the issues and descriptions in https://github.com/leitbogioro/Tools A common problem is that the machine is raid0 not raid10, and you need to add a parameter to specify the value of the raid.

If you have time or if it's still not working, please contact @spiritlhl_bot for assistance.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the \`\`\`/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT\`\`, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

What to do if you accidentally delete a NAT mapping rule

Use the following command to map back

shell
iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+cat /etc/iptables/rules.v4 | iptables-restore

Adding a New Node to an Existing PVE Cluster (Create / Join Cluster)

To form a cluster from two independent Proxmox VE instances, the following prerequisites must be met:

Cluster Prerequisites

  1. Unique Hostnames
    The hostname of each node must be unique to avoid conflicts. It is recommended to use names like pve1, pve2, etc.

  2. Unique VMIDs
    There must be no duplicate VMIDs across the two PVE nodes. If conflicts exist, adjust the VMIDs beforehand to prevent issues during cluster merge.

  3. Network Connectivity & Low Latency
    Both nodes must be able to ping each other. A low-latency network (LAN or high-speed public connection) is recommended for reliable cluster communication.

Creating the Cluster (Run on Any Node)

  1. Log in to the web interface of the node where the cluster will be created (e.g., pve1).
  2. Navigate to: Datacenter → Cluster → Create Cluster.
  3. Enter a name for the cluster (Cluster Name).
  4. Select the network interface to be used for cluster communication (e.g., public IP if only one interface is available).
  5. Click Create to initialize the cluster.
  6. Once the cluster is created, click Join Information and copy the displayed information for use on the joining node.

Note: The cluster has no "master" or "slave" nodes—any node can be the one that initiates the cluster.

Joining the Cluster (Run on the Second Node)

  1. Log in to the web interface of the node to be added (e.g., pve2).
  2. Navigate to: Datacenter → Cluster → Join Cluster.
  3. Paste the Join Information from pve1 into the input field.
  4. Enter the password of root user on pve1 in the Peer Password field.
  5. Click Join to begin the joining process.
  6. Wait until the process completes successfully, then refresh the page or re-login. You should now see both nodes in the same cluster.

Cluster Benefits

  • Nodes can share resources and migrate virtual machines.
  • ISO images and templates can be transferred more conveniently between nodes.

Verified VPS Providers

VPS Providers Offering KVM Virtualization with NAT

spartanhost Debian12 on a Dedicated Server (Debian11 has problems)

interserver VPS or dedicated servers

frantech Las Vegas Tier 2

eugamehost US Phoenix Black Friday Special

amhost Testing version

digitalocean Perminu Intel and Regular 4-core versions

skrime Lowest configuration of AMD Ryzen KVM Server

webdock AMD KVM Server

4vps Russian and Greek testing versions

adtaq Storage KVM server with lowest configuration

nocix Dedicated servers

online.net Debian12 on a Dedicated Server (Debian11 has problems)

OVH Public Cloud needs to be installed after dd as a pure system using the following command

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd ' oneclickvirt139' --network "static"

At this point, the system username after dd is root, and the password is oneclickvirt139.

If it doesn't work, please check the issues and instructions in https://github.com/leitbogioro/Tools. A common problem is that OVH standalone servers are dd'd, which requires the source system to be remounted as raid1 on debian12 by default, and then parameterized to specify dd'd as raid0 in order to be successful, using the following command

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

VPS Providers Offering NAT with LXC Virtualization

Tencent Cloud Worry-Free and Student editions

spectraip KVM servers

Linode Lowest configuration with dedicated CPU

hosthatch Special high-configuration servers

hetzner Cloud servers

rackdog Servers with floating IP

vultr Standard Cloud servers

azure Standard machines

scaleway ARM architecture servers

aws EC2 servers

Google cloud platform - GCP AMD servers

`,91)]))}const f=s(o,[["render",l]]);export{g as __pageData,f as default}; diff --git a/assets/en_guide_pve_pve_qa.md.BYBr2UQn.lean.js b/assets/en_guide_pve_pve_qa.md.BYBr2UQn.lean.js new file mode 100644 index 0000000000..e022e7fe1b --- /dev/null +++ b/assets/en_guide_pve_pve_qa.md.BYBr2UQn.lean.js @@ -0,0 +1 @@ +import{_ as s,c as t,o as a,ag as i}from"./chunks/framework.CSeR4K32.js";const n="/assets/onlinepkg.-C5qKOrj.png",r="/assets/dns0.DDagSewr.png",g=JSON.parse('{"title":"Solve the puzzle","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_qa.md","filePath":"en/guide/pve/pve_qa.md","lastUpdated":1747984962000}'),o={name:"en/guide/pve/pve_qa.md"};function l(h,e,p,d,c,k){return a(),t("div",null,e[0]||(e[0]=[i("",91)]))}const f=s(o,[["render",l]]);export{g as __pageData,f as default}; diff --git a/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.js b/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.js new file mode 100644 index 0000000000..ef8873096a --- /dev/null +++ b/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.js @@ -0,0 +1 @@ +import{_ as r,c as t,o,ag as a}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/pve_thanks.md","filePath":"en/guide/pve/pve_thanks.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_thanks.md"};function p(i,e,s,l,h,m){return o(),t("div",null,e[0]||(e[0]=[a('

Acknowledgements

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda for providing PVE guidance.

',16)]))}const b=r(n,[["render",p]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.lean.js b/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.lean.js new file mode 100644 index 0000000000..e30bffbc3b --- /dev/null +++ b/assets/en_guide_pve_pve_thanks.md.Dw43XV-y.lean.js @@ -0,0 +1 @@ +import{_ as r,c as t,o,ag as a}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/pve_thanks.md","filePath":"en/guide/pve/pve_thanks.md","lastUpdated":1747984962000}'),n={name:"en/guide/pve/pve_thanks.md"};function p(i,e,s,l,h,m){return o(),t("div",null,e[0]||(e[0]=[a("",16)]))}const b=r(n,[["render",p]]);export{g as __pageData,b as default}; diff --git a/assets/en_guide_pve_pve_thanks.md.dc0491f9.js b/assets/en_guide_pve_pve_thanks.md.dc0491f9.js deleted file mode 100644 index 6c79e6a7a6..0000000000 --- a/assets/en_guide_pve_pve_thanks.md.dc0491f9.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as r,b as t,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/pve_thanks.md","filePath":"en/guide/pve/pve_thanks.md","lastUpdated":1747972048000}'),a={name:"en/guide/pve/pve_thanks.md"},n=o('

Acknowledgements

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda for providing PVE guidance.

',16),p=[n];function s(i,h,l,m,c,g){return r(),t("div",null,p)}const d=e(a,[["render",s]]);export{u as __pageData,d as default}; diff --git a/assets/en_guide_pve_pve_thanks.md.dc0491f9.lean.js b/assets/en_guide_pve_pve_thanks.md.dc0491f9.lean.js deleted file mode 100644 index 6c79e6a7a6..0000000000 --- a/assets/en_guide_pve_pve_thanks.md.dc0491f9.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as r,b as t,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"en/guide/pve/pve_thanks.md","filePath":"en/guide/pve/pve_thanks.md","lastUpdated":1747972048000}'),a={name:"en/guide/pve/pve_thanks.md"},n=o('

Acknowledgements

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

Thank @Ella-Alinda for providing PVE guidance.

',16),p=[n];function s(i,h,l,m,c,g){return r(),t("div",null,p)}const d=e(a,[["render",s]]);export{u as __pageData,d as default}; diff --git a/assets/en_guide_pve_pve_windows.md.923bbd33.js b/assets/en_guide_pve_pve_windows.md.923bbd33.js deleted file mode 100644 index d0bc61155c..0000000000 --- a/assets/en_guide_pve_pve_windows.md.923bbd33.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as t,v as o,b as i,R as s}from"./chunks/framework.70afa331.js";import{_ as e}from"./chunks/wk7.776871bd.js";const n="/assets/dlwiniso.a2c0c1ef.png",a="/assets/dlwiniso1.4fa2fea0.png",r="/assets/general.ea03923c.png",c="/assets/os.b2be1a5c.png",d="/assets/system.8e69987e.png",l="/assets/disks.8065a143.png",p="/assets/cpu.4618bc7b.png",h="/assets/memory.c4992870.png",g="/assets/network.48037353.png",m="/assets/finish.0c3eac87.png",u="/assets/start.3aebbfd4.png",w="/assets/gic1.42bfd260.png",f="/assets/gic2.ff78c941.png",k="/assets/gic3.4a04cf3d.png",_="/assets/gic4.e2343160.png",v="/assets/gic5.54522dff.png",I="/assets/gic6.97561122.png",b="/assets/gic7.a8679083.png",y="/assets/gic8.fe7d0b3c.png",O="/assets/gic9.4cdf4daa.png",x="/assets/net1.4f166207.png",S="/assets/net2.e2773ada.png",C="/assets/net3.40e8a226.png",V="/assets/net4.a81e777c.png",D="/assets/virtio.b42d8275.png",P="/assets/lower2.e782a20a.png",N="/assets/lower1.28498396.png",q="/assets/nodisk.5ec86f3b.png",U="/assets/nodisk1.671c1309.png",M="/assets/nodisk2.ff20bb76.png",A="/assets/nodisk3.71534a11.png",T="/assets/nodisk4.b08d75e3.png",W="/assets/wk4.004be17f.png",z="/assets/wk5.6cdba880.png",B="/assets/wk6.667c5c95.png",F="/assets/wk1.7d9f24d7.png",E="/assets/wk2.2e88d91a.png",R="/assets/wk3.975bc38e.png",te=JSON.parse('{"title":"Setting Up Windows Visual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_windows.md","filePath":"en/guide/pve/pve_windows.md","lastUpdated":1747972048000}'),G={name:"en/guide/pve/pve_windows.md"},L=s('

Setting Up Windows Visual Machine

Using ISO Image with VirtIO for VM Setup

1. Download the Image

Before installation, you need to download the image file via local(pve) --> ISO images --> Download from URL

For the download link (URL:), you can use files from: https://github.com/ILLKX/Windows-VirtIO

Enter win.iso as the File Name:

download

Click Download. After downloading is complete, you can see the file size of win.iso on the current page, confirming it's in ISO format.

downloaded

2. Setting Up the Template

Click Create VM in the top right corner of the page.

In the General window, select mypool for Resource Pool:, enter win for Name, then click Next.

general

In the OS window, select win.iso for ISO image. For Guest OS, select Microsoft Windows as the Type and choose the appropriate Version for your ISO. For example, if you downloaded Windows 2022, select 11/2022, then click Next.

OS

In the System window, select VirtIO-GPU for Graphic card, q35 for Machine, VirtIO SCSI for SCSI Controller, and Default (SeaBIOS) for BIOS, then click Next.

system

In the Disk window, select Write Back for Cache, enter your desired disk size in Disk size (GiB) (generally not less than 20), and choose the storage location in Storage. In this example, only the system disk local is available, so local is selected. Then click Next.

disk

In the CPU window, enter the number of cores needed in Cores, then click Next.

cpu

In the Memory window, enter the desired memory size in Memory (MiB), then click Next.

memory

In the Network window, select vmbr1 for Bridge, VirtIO (paravirtualized) for Model, uncheck Firewall, then click Next.

Network

In the Confirm window, click Finish.

finish

3. Graphical Installation Configuration

Click on the template you've set up on the left, click Start in the upper right corner to start the virtual machine, then click Console to enter the VNC interface and wait for the operating system to boot.

console

In the VNC, click Next, then Install now, then I don't have a product key, check Accept license, click Next, and then select Custom installation.

win0win1win2win3win4

If the image comes with VirtIO drivers, you should be able to see the available system storage disk and its size. Select it and click Next.

win5win6

Wait for the system to install. It may restart automatically several times and could take more than 10 minutes.

win7

After installation is complete, you'll be asked to set a password during first login.

win8

Once setup is complete, there's a pop-up box on the left side of the NOVNC page. Click the first button, then follow the login prompt by pressing Ctrl+Alt+last button to enter the login page.

4. Network Initialization

Since the PVE is set up with a static network through this project, you need to manually modify the bound IP address after logging in, rather than using DHCP.

Right-click in the bottom right corner of the desktop and select Open Network and Internet settings. In the settings page that appears, click Change adapter options. win9

In the Network Connections, select Ethernet and click Change settings of this connection. win10

In the popup window, select Internet Protocol Version 4 (TCP/IPv4) and click Properties. win11

In the new dialog box, select Use the following IP address and enter: IP address(I): 172.16.1.xxx (replace xxx with your desired IP, I used 100 for convenience as my vmid is 100) Subnet mask(U): 255.255.255.0 Default gateway(D): 172.16.1.1

Then select Use the following DNS server addresses and enter:

8.8.8.8
-144.144.144.144

Click OK in the bottom right corner, and make sure Validate settings upon exit is NOT checked.

win12

Click OK and Yes for any other dialog boxes, and your virtual machine will now have network connectivity.

5. Unmounting the CD Drive

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Using ISO Images without VirtIO for VM Installation

1. Download Images

For Windows images without VirtIO, you can use:

https://down.idc.wiki/ISOS/Windows/

For VirtIO ISO images, you can use:

https://down.idc.wiki/ISOS/Toolkit/

or

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

Alternatively, you can download just the MSI package, package it into an ISO format locally, and then upload it to ProxmoxVE.

This way, the package is smaller. The official package contains support for all Windows images and is about 500MB, while a self-packaged one is around 5MB.

2. VirtIO Import

Note that in ProxmoxVE version 8.x and later, you can select VirtIO boot loading by default in the OS section, as shown in the image:

virtio

In lower versions of ProxmoxVE, such as 7.x and 6.x, you cannot select VirtIO boot loading by default in the OS section:

lower

You need to manually add CD/DVD Drive by clicking Add in the Hardware section and selecting the downloaded VirtIO ISO file:

lower

Then proceed as usual until you reach:

nodisk

At this point, you can't find the hard disk. You need to select Load Driver:

nodisk

Then select the VirtIO as your driver disk, click open, and import the corresponding system driver from the amd64 directory:

nodisk

I'm using a Windows Server 2019 image, so I imported the 2k19 driver. After importing, select the imported driver and click Next:

nodisk

nodisk

Now you should be able to see the hard disk. Select it and continue with the installation steps as in the previous tutorial until the system installation is complete and you reach the desktop.

3. Installing Drivers via virtio-win-guest-tools

Once successfully installed and at the desktop, you still need to manually install the drivers.

Open the VirtIO driver's CD drive directory. At the bottom, there's a virtio-win-guest-tools program that will install the required VirtIO drivers, including the VirtIO network card driver:

wk

wk

wk

After clicking install, the network card driver will be installed. For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

4. Installing Network Card Driver (Alternative)

After successful installation and reaching the desktop, you may still need to manually install the network card driver to connect to the network:

  1. Open Control PanelDevice Manager
  2. Find the Ethernet Controller, right-click and select Update Driver
  3. Select Browse my computer for driver software (R)
  4. Browse to the VirtIO driver's CD drive directory
  5. Open the NetKVM folder
  6. Select the driver folder corresponding to your current system version (like the above operation, I would choose the 2k19 folder with amd64 drivers)
  7. Confirm the installation, and after completion, the VirtIO network card driver will be successfully loaded

wk

wk

wk

For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

5. Unmounting the CD Drive

In the ProxmoxVE web interface, manually click on the corresponding CD in the Hardware section, select Remove, and then restart the virtual machine. This way, you can use it directly:

wk

',97),K=[L];function H($,Y,j,X,J,Q){return o(),i("div",null,K)}const oe=t(G,[["render",H]]);export{te as __pageData,oe as default}; diff --git a/assets/en_guide_pve_pve_windows.md.923bbd33.lean.js b/assets/en_guide_pve_pve_windows.md.923bbd33.lean.js deleted file mode 100644 index d0bc61155c..0000000000 --- a/assets/en_guide_pve_pve_windows.md.923bbd33.lean.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as t,v as o,b as i,R as s}from"./chunks/framework.70afa331.js";import{_ as e}from"./chunks/wk7.776871bd.js";const n="/assets/dlwiniso.a2c0c1ef.png",a="/assets/dlwiniso1.4fa2fea0.png",r="/assets/general.ea03923c.png",c="/assets/os.b2be1a5c.png",d="/assets/system.8e69987e.png",l="/assets/disks.8065a143.png",p="/assets/cpu.4618bc7b.png",h="/assets/memory.c4992870.png",g="/assets/network.48037353.png",m="/assets/finish.0c3eac87.png",u="/assets/start.3aebbfd4.png",w="/assets/gic1.42bfd260.png",f="/assets/gic2.ff78c941.png",k="/assets/gic3.4a04cf3d.png",_="/assets/gic4.e2343160.png",v="/assets/gic5.54522dff.png",I="/assets/gic6.97561122.png",b="/assets/gic7.a8679083.png",y="/assets/gic8.fe7d0b3c.png",O="/assets/gic9.4cdf4daa.png",x="/assets/net1.4f166207.png",S="/assets/net2.e2773ada.png",C="/assets/net3.40e8a226.png",V="/assets/net4.a81e777c.png",D="/assets/virtio.b42d8275.png",P="/assets/lower2.e782a20a.png",N="/assets/lower1.28498396.png",q="/assets/nodisk.5ec86f3b.png",U="/assets/nodisk1.671c1309.png",M="/assets/nodisk2.ff20bb76.png",A="/assets/nodisk3.71534a11.png",T="/assets/nodisk4.b08d75e3.png",W="/assets/wk4.004be17f.png",z="/assets/wk5.6cdba880.png",B="/assets/wk6.667c5c95.png",F="/assets/wk1.7d9f24d7.png",E="/assets/wk2.2e88d91a.png",R="/assets/wk3.975bc38e.png",te=JSON.parse('{"title":"Setting Up Windows Visual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_windows.md","filePath":"en/guide/pve/pve_windows.md","lastUpdated":1747972048000}'),G={name:"en/guide/pve/pve_windows.md"},L=s('

Setting Up Windows Visual Machine

Using ISO Image with VirtIO for VM Setup

1. Download the Image

Before installation, you need to download the image file via local(pve) --> ISO images --> Download from URL

For the download link (URL:), you can use files from: https://github.com/ILLKX/Windows-VirtIO

Enter win.iso as the File Name:

download

Click Download. After downloading is complete, you can see the file size of win.iso on the current page, confirming it's in ISO format.

downloaded

2. Setting Up the Template

Click Create VM in the top right corner of the page.

In the General window, select mypool for Resource Pool:, enter win for Name, then click Next.

general

In the OS window, select win.iso for ISO image. For Guest OS, select Microsoft Windows as the Type and choose the appropriate Version for your ISO. For example, if you downloaded Windows 2022, select 11/2022, then click Next.

OS

In the System window, select VirtIO-GPU for Graphic card, q35 for Machine, VirtIO SCSI for SCSI Controller, and Default (SeaBIOS) for BIOS, then click Next.

system

In the Disk window, select Write Back for Cache, enter your desired disk size in Disk size (GiB) (generally not less than 20), and choose the storage location in Storage. In this example, only the system disk local is available, so local is selected. Then click Next.

disk

In the CPU window, enter the number of cores needed in Cores, then click Next.

cpu

In the Memory window, enter the desired memory size in Memory (MiB), then click Next.

memory

In the Network window, select vmbr1 for Bridge, VirtIO (paravirtualized) for Model, uncheck Firewall, then click Next.

Network

In the Confirm window, click Finish.

finish

3. Graphical Installation Configuration

Click on the template you've set up on the left, click Start in the upper right corner to start the virtual machine, then click Console to enter the VNC interface and wait for the operating system to boot.

console

In the VNC, click Next, then Install now, then I don't have a product key, check Accept license, click Next, and then select Custom installation.

win0win1win2win3win4

If the image comes with VirtIO drivers, you should be able to see the available system storage disk and its size. Select it and click Next.

win5win6

Wait for the system to install. It may restart automatically several times and could take more than 10 minutes.

win7

After installation is complete, you'll be asked to set a password during first login.

win8

Once setup is complete, there's a pop-up box on the left side of the NOVNC page. Click the first button, then follow the login prompt by pressing Ctrl+Alt+last button to enter the login page.

4. Network Initialization

Since the PVE is set up with a static network through this project, you need to manually modify the bound IP address after logging in, rather than using DHCP.

Right-click in the bottom right corner of the desktop and select Open Network and Internet settings. In the settings page that appears, click Change adapter options. win9

In the Network Connections, select Ethernet and click Change settings of this connection. win10

In the popup window, select Internet Protocol Version 4 (TCP/IPv4) and click Properties. win11

In the new dialog box, select Use the following IP address and enter: IP address(I): 172.16.1.xxx (replace xxx with your desired IP, I used 100 for convenience as my vmid is 100) Subnet mask(U): 255.255.255.0 Default gateway(D): 172.16.1.1

Then select Use the following DNS server addresses and enter:

8.8.8.8
-144.144.144.144

Click OK in the bottom right corner, and make sure Validate settings upon exit is NOT checked.

win12

Click OK and Yes for any other dialog boxes, and your virtual machine will now have network connectivity.

5. Unmounting the CD Drive

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Using ISO Images without VirtIO for VM Installation

1. Download Images

For Windows images without VirtIO, you can use:

https://down.idc.wiki/ISOS/Windows/

For VirtIO ISO images, you can use:

https://down.idc.wiki/ISOS/Toolkit/

or

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

Alternatively, you can download just the MSI package, package it into an ISO format locally, and then upload it to ProxmoxVE.

This way, the package is smaller. The official package contains support for all Windows images and is about 500MB, while a self-packaged one is around 5MB.

2. VirtIO Import

Note that in ProxmoxVE version 8.x and later, you can select VirtIO boot loading by default in the OS section, as shown in the image:

virtio

In lower versions of ProxmoxVE, such as 7.x and 6.x, you cannot select VirtIO boot loading by default in the OS section:

lower

You need to manually add CD/DVD Drive by clicking Add in the Hardware section and selecting the downloaded VirtIO ISO file:

lower

Then proceed as usual until you reach:

nodisk

At this point, you can't find the hard disk. You need to select Load Driver:

nodisk

Then select the VirtIO as your driver disk, click open, and import the corresponding system driver from the amd64 directory:

nodisk

I'm using a Windows Server 2019 image, so I imported the 2k19 driver. After importing, select the imported driver and click Next:

nodisk

nodisk

Now you should be able to see the hard disk. Select it and continue with the installation steps as in the previous tutorial until the system installation is complete and you reach the desktop.

3. Installing Drivers via virtio-win-guest-tools

Once successfully installed and at the desktop, you still need to manually install the drivers.

Open the VirtIO driver's CD drive directory. At the bottom, there's a virtio-win-guest-tools program that will install the required VirtIO drivers, including the VirtIO network card driver:

wk

wk

wk

After clicking install, the network card driver will be installed. For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

4. Installing Network Card Driver (Alternative)

After successful installation and reaching the desktop, you may still need to manually install the network card driver to connect to the network:

  1. Open Control PanelDevice Manager
  2. Find the Ethernet Controller, right-click and select Update Driver
  3. Select Browse my computer for driver software (R)
  4. Browse to the VirtIO driver's CD drive directory
  5. Open the NetKVM folder
  6. Select the driver folder corresponding to your current system version (like the above operation, I would choose the 2k19 folder with amd64 drivers)
  7. Confirm the installation, and after completion, the VirtIO network card driver will be successfully loaded

wk

wk

wk

For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

5. Unmounting the CD Drive

In the ProxmoxVE web interface, manually click on the corresponding CD in the Hardware section, select Remove, and then restart the virtual machine. This way, you can use it directly:

wk

',97),K=[L];function H($,Y,j,X,J,Q){return o(),i("div",null,K)}const oe=t(G,[["render",H]]);export{te as __pageData,oe as default}; diff --git a/assets/en_guide_pve_pve_windows.md.vqwXYaPa.js b/assets/en_guide_pve_pve_windows.md.vqwXYaPa.js new file mode 100644 index 0000000000..ec7e5480fb --- /dev/null +++ b/assets/en_guide_pve_pve_windows.md.vqwXYaPa.js @@ -0,0 +1,2 @@ +import{_ as t}from"./chunks/wk7.BpuwpIoq.js";import{_ as o,c as i,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const a="/assets/dlwiniso.BxXucu9m.png",r="/assets/dlwiniso1.CQyxWlSu.png",c="/assets/general.BkOp2iK4.png",d="/assets/os.CX7bMEp5.png",l="/assets/system.C_AmkiPg.png",p="/assets/disks.BJniy5pO.png",h="/assets/cpu.DedcVQ_T.png",g="/assets/memory.CH7Gxf76.png",m="/assets/network.DPXM5W42.png",u="/assets/finish.Cf6DgPp1.png",w="/assets/start.vjgB4hml.png",k="/assets/gic1.XkdPXihx.png",_="/assets/gic2.s5VB7-xp.png",f="/assets/gic3.2zLznATL.png",v="/assets/gic4.CX3t8C19.png",I="/assets/gic5.pjwHWuhn.png",y="/assets/gic6.BnmyenL0.png",b="/assets/gic7.ZYHWzF5W.png",C="/assets/gic8.BwCbmRgC.png",O="/assets/gic9.62-9wTBo.png",S="/assets/net1.CUyp8ayS.png",x="/assets/net2.BP2m5XnQ.png",V="/assets/net3.BJFg7Me5.png",D="/assets/net4.CANZtcPE.png",P="/assets/virtio.CUVhk14O.png",N="/assets/lower2.SPGPKJ4N.png",q="/assets/lower1.DFw6c1iw.png",B="/assets/nodisk.CH47I8Tu.png",M="/assets/nodisk1.gZ09o2py.png",T="/assets/nodisk2.Do6XEKMW.png",U="/assets/nodisk3.1vBQc75S.png",W="/assets/nodisk4.CJjHGgtp.png",A="/assets/wk4.K5XvE6uQ.png",E="/assets/wk5.BEJ5BAWW.png",z="/assets/wk6.D9MKwk3w.png",F="/assets/wk1.BGnwsbrE.png",G="/assets/wk2.BasdNK2d.png",H="/assets/wk3.CWstwLHH.png",Z=JSON.parse('{"title":"Setting Up Windows Visual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_windows.md","filePath":"en/guide/pve/pve_windows.md","lastUpdated":1747984962000}'),K={name:"en/guide/pve/pve_windows.md"};function L(X,e,R,J,j,Q){return n(),i("div",null,e[0]||(e[0]=[s('

Setting Up Windows Visual Machine

Using ISO Image with VirtIO for VM Setup

1. Download the Image

Before installation, you need to download the image file via local(pve) --> ISO images --> Download from URL

For the download link (URL:), you can use files from: https://github.com/ILLKX/Windows-VirtIO

Enter win.iso as the File Name:

download

Click Download. After downloading is complete, you can see the file size of win.iso on the current page, confirming it's in ISO format.

downloaded

2. Setting Up the Template

Click Create VM in the top right corner of the page.

In the General window, select mypool for Resource Pool:, enter win for Name, then click Next.

general

In the OS window, select win.iso for ISO image. For Guest OS, select Microsoft Windows as the Type and choose the appropriate Version for your ISO. For example, if you downloaded Windows 2022, select 11/2022, then click Next.

OS

In the System window, select VirtIO-GPU for Graphic card, q35 for Machine, VirtIO SCSI for SCSI Controller, and Default (SeaBIOS) for BIOS, then click Next.

system

In the Disk window, select Write Back for Cache, enter your desired disk size in Disk size (GiB) (generally not less than 20), and choose the storage location in Storage. In this example, only the system disk local is available, so local is selected. Then click Next.

disk

In the CPU window, enter the number of cores needed in Cores, then click Next.

cpu

In the Memory window, enter the desired memory size in Memory (MiB), then click Next.

memory

In the Network window, select vmbr1 for Bridge, VirtIO (paravirtualized) for Model, uncheck Firewall, then click Next.

Network

In the Confirm window, click Finish.

finish

3. Graphical Installation Configuration

Click on the template you've set up on the left, click Start in the upper right corner to start the virtual machine, then click Console to enter the VNC interface and wait for the operating system to boot.

console

In the VNC, click Next, then Install now, then I don't have a product key, check Accept license, click Next, and then select Custom installation.

win0win1win2win3win4

If the image comes with VirtIO drivers, you should be able to see the available system storage disk and its size. Select it and click Next.

win5win6

Wait for the system to install. It may restart automatically several times and could take more than 10 minutes.

win7

After installation is complete, you'll be asked to set a password during first login.

win8

Once setup is complete, there's a pop-up box on the left side of the NOVNC page. Click the first button, then follow the login prompt by pressing Ctrl+Alt+last button to enter the login page.

4. Network Initialization

Since the PVE is set up with a static network through this project, you need to manually modify the bound IP address after logging in, rather than using DHCP.

Right-click in the bottom right corner of the desktop and select Open Network and Internet settings. In the settings page that appears, click Change adapter options. win9

In the Network Connections, select Ethernet and click Change settings of this connection. win10

In the popup window, select Internet Protocol Version 4 (TCP/IPv4) and click Properties. win11

In the new dialog box, select Use the following IP address and enter: IP address(I): 172.16.1.xxx (replace xxx with your desired IP, I used 100 for convenience as my vmid is 100) Subnet mask(U): 255.255.255.0 Default gateway(D): 172.16.1.1

Then select Use the following DNS server addresses and enter:

8.8.8.8
+144.144.144.144

Click OK in the bottom right corner, and make sure Validate settings upon exit is NOT checked.

win12

Click OK and Yes for any other dialog boxes, and your virtual machine will now have network connectivity.

5. Unmounting the CD Drive

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Using ISO Images without VirtIO for VM Installation

1. Download Images

For Windows images without VirtIO, you can use:

https://down.idc.wiki/ISOS/Windows/

For VirtIO ISO images, you can use:

https://down.idc.wiki/ISOS/Toolkit/

or

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

Alternatively, you can download just the MSI package, package it into an ISO format locally, and then upload it to ProxmoxVE.

This way, the package is smaller. The official package contains support for all Windows images and is about 500MB, while a self-packaged one is around 5MB.

2. VirtIO Import

Note that in ProxmoxVE version 8.x and later, you can select VirtIO boot loading by default in the OS section, as shown in the image:

virtio

In lower versions of ProxmoxVE, such as 7.x and 6.x, you cannot select VirtIO boot loading by default in the OS section:

lower

You need to manually add CD/DVD Drive by clicking Add in the Hardware section and selecting the downloaded VirtIO ISO file:

lower

Then proceed as usual until you reach:

nodisk

At this point, you can't find the hard disk. You need to select Load Driver:

nodisk

Then select the VirtIO as your driver disk, click open, and import the corresponding system driver from the amd64 directory:

nodisk

I'm using a Windows Server 2019 image, so I imported the 2k19 driver. After importing, select the imported driver and click Next:

nodisk

nodisk

Now you should be able to see the hard disk. Select it and continue with the installation steps as in the previous tutorial until the system installation is complete and you reach the desktop.

3. Installing Drivers via virtio-win-guest-tools

Once successfully installed and at the desktop, you still need to manually install the drivers.

Open the VirtIO driver's CD drive directory. At the bottom, there's a virtio-win-guest-tools program that will install the required VirtIO drivers, including the VirtIO network card driver:

wk

wk

wk

After clicking install, the network card driver will be installed. For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

4. Installing Network Card Driver (Alternative)

After successful installation and reaching the desktop, you may still need to manually install the network card driver to connect to the network:

  1. Open Control PanelDevice Manager
  2. Find the Ethernet Controller, right-click and select Update Driver
  3. Select Browse my computer for driver software (R)
  4. Browse to the VirtIO driver's CD drive directory
  5. Open the NetKVM folder
  6. Select the driver folder corresponding to your current system version (like the above operation, I would choose the 2k19 folder with amd64 drivers)
  7. Confirm the installation, and after completion, the VirtIO network card driver will be successfully loaded

wk

wk

wk

For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

5. Unmounting the CD Drive

In the ProxmoxVE web interface, manually click on the corresponding CD in the Hardware section, select Remove, and then restart the virtual machine. This way, you can use it directly:

wk

',97)]))}const ee=o(K,[["render",L]]);export{Z as __pageData,ee as default}; diff --git a/assets/en_guide_pve_pve_windows.md.vqwXYaPa.lean.js b/assets/en_guide_pve_pve_windows.md.vqwXYaPa.lean.js new file mode 100644 index 0000000000..20fc2c32fd --- /dev/null +++ b/assets/en_guide_pve_pve_windows.md.vqwXYaPa.lean.js @@ -0,0 +1 @@ +import{_ as t}from"./chunks/wk7.BpuwpIoq.js";import{_ as o,c as i,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const a="/assets/dlwiniso.BxXucu9m.png",r="/assets/dlwiniso1.CQyxWlSu.png",c="/assets/general.BkOp2iK4.png",d="/assets/os.CX7bMEp5.png",l="/assets/system.C_AmkiPg.png",p="/assets/disks.BJniy5pO.png",h="/assets/cpu.DedcVQ_T.png",g="/assets/memory.CH7Gxf76.png",m="/assets/network.DPXM5W42.png",u="/assets/finish.Cf6DgPp1.png",w="/assets/start.vjgB4hml.png",k="/assets/gic1.XkdPXihx.png",_="/assets/gic2.s5VB7-xp.png",f="/assets/gic3.2zLznATL.png",v="/assets/gic4.CX3t8C19.png",I="/assets/gic5.pjwHWuhn.png",y="/assets/gic6.BnmyenL0.png",b="/assets/gic7.ZYHWzF5W.png",C="/assets/gic8.BwCbmRgC.png",O="/assets/gic9.62-9wTBo.png",S="/assets/net1.CUyp8ayS.png",x="/assets/net2.BP2m5XnQ.png",V="/assets/net3.BJFg7Me5.png",D="/assets/net4.CANZtcPE.png",P="/assets/virtio.CUVhk14O.png",N="/assets/lower2.SPGPKJ4N.png",q="/assets/lower1.DFw6c1iw.png",B="/assets/nodisk.CH47I8Tu.png",M="/assets/nodisk1.gZ09o2py.png",T="/assets/nodisk2.Do6XEKMW.png",U="/assets/nodisk3.1vBQc75S.png",W="/assets/nodisk4.CJjHGgtp.png",A="/assets/wk4.K5XvE6uQ.png",E="/assets/wk5.BEJ5BAWW.png",z="/assets/wk6.D9MKwk3w.png",F="/assets/wk1.BGnwsbrE.png",G="/assets/wk2.BasdNK2d.png",H="/assets/wk3.CWstwLHH.png",Z=JSON.parse('{"title":"Setting Up Windows Visual Machine","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/guide/pve/pve_windows.md","filePath":"en/guide/pve/pve_windows.md","lastUpdated":1747984962000}'),K={name:"en/guide/pve/pve_windows.md"};function L(X,e,R,J,j,Q){return n(),i("div",null,e[0]||(e[0]=[s("",97)]))}const ee=o(K,[["render",L]]);export{Z as __pageData,ee as default}; diff --git a/assets/en_incomplete_bashvm.md.DWaL7zdf.js b/assets/en_incomplete_bashvm.md.DWaL7zdf.js new file mode 100644 index 0000000000..d10ad9f83d --- /dev/null +++ b/assets/en_incomplete_bashvm.md.DWaL7zdf.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,ag as r}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/bashvm.md","filePath":"en/incomplete/bashvm.md","lastUpdated":1747984962000}'),s={name:"en/incomplete/bashvm.md"};function n(i,a,p,h,d,l){return o(),t("div",null,a[0]||(a[0]=[r('

Repo

https://github.com/babywhale321/bashvm

https://bashvm.com/

Description

If you want to go deeper into how to open a VM and how to forward ports, then this program will start completely from the bottom and teach you step by step how to open a VM!

Disadvantages

Very tedious and time consuming, not as fast as other programs to set up a network and open a VM

',7)]))}const b=e(s,[["render",n]]);export{c as __pageData,b as default}; diff --git a/assets/en_incomplete_bashvm.md.DWaL7zdf.lean.js b/assets/en_incomplete_bashvm.md.DWaL7zdf.lean.js new file mode 100644 index 0000000000..73b39a519b --- /dev/null +++ b/assets/en_incomplete_bashvm.md.DWaL7zdf.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o,ag as r}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/bashvm.md","filePath":"en/incomplete/bashvm.md","lastUpdated":1747984962000}'),s={name:"en/incomplete/bashvm.md"};function n(i,a,p,h,d,l){return o(),t("div",null,a[0]||(a[0]=[r("",7)]))}const b=e(s,[["render",n]]);export{c as __pageData,b as default}; diff --git a/assets/en_incomplete_bashvm.md.fce6926b.js b/assets/en_incomplete_bashvm.md.fce6926b.js deleted file mode 100644 index 652fd97584..0000000000 --- a/assets/en_incomplete_bashvm.md.fce6926b.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as o}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/bashvm.md","filePath":"en/incomplete/bashvm.md","lastUpdated":1747972048000}'),s={name:"en/incomplete/bashvm.md"},r=o('

Repo

https://github.com/babywhale321/bashvm

https://bashvm.com/

Description

If you want to go deeper into how to open a VM and how to forward ports, then this program will start completely from the bottom and teach you step by step how to open a VM!

Disadvantages

Very tedious and time consuming, not as fast as other programs to set up a network and open a VM

',7),n=[r];function i(h,p,d,c,l,m){return e(),t("div",null,n)}const u=a(s,[["render",i]]);export{f as __pageData,u as default}; diff --git a/assets/en_incomplete_bashvm.md.fce6926b.lean.js b/assets/en_incomplete_bashvm.md.fce6926b.lean.js deleted file mode 100644 index 652fd97584..0000000000 --- a/assets/en_incomplete_bashvm.md.fce6926b.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as o}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/bashvm.md","filePath":"en/incomplete/bashvm.md","lastUpdated":1747972048000}'),s={name:"en/incomplete/bashvm.md"},r=o('

Repo

https://github.com/babywhale321/bashvm

https://bashvm.com/

Description

If you want to go deeper into how to open a VM and how to forward ports, then this program will start completely from the bottom and teach you step by step how to open a VM!

Disadvantages

Very tedious and time consuming, not as fast as other programs to set up a network and open a VM

',7),n=[r];function i(h,p,d,c,l,m){return e(),t("div",null,n)}const u=a(s,[["render",i]]);export{f as __pageData,u as default}; diff --git a/assets/en_incomplete_cockpit.md.DKGXpcw0.js b/assets/en_incomplete_cockpit.md.DKGXpcw0.js new file mode 100644 index 0000000000..f695147303 --- /dev/null +++ b/assets/en_incomplete_cockpit.md.DKGXpcw0.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/cockpit.md","filePath":"en/incomplete/cockpit.md","lastUpdated":1747984962000}'),l={name:"en/incomplete/cockpit.md"};function n(h,s,p,o,r,c){return t(),i("div",null,s[0]||(s[0]=[e('

Repo

hits

https://github.com/oneclickvirt/cockpit

Installation

Supported Systems: Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

Install only with Podman containers

shell
bash install.sh --ct

Install only with virtual machines

shell
bash install.sh --vm

Panel Mount Only

shell
bash install.sh

Both container and VM dependencies are installed

shell
bash install.sh --all

Disadvantages

The network is self-configuring, the mirrors are self-importing, the ports are self-mapped, and there is just one more GUI interface than the command line.

Thanks

https://cockpit-project.org/running.html

',18)]))}const g=a(l,[["render",n]]);export{k as __pageData,g as default}; diff --git a/assets/en_incomplete_cockpit.md.DKGXpcw0.lean.js b/assets/en_incomplete_cockpit.md.DKGXpcw0.lean.js new file mode 100644 index 0000000000..521be6cbe6 --- /dev/null +++ b/assets/en_incomplete_cockpit.md.DKGXpcw0.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/cockpit.md","filePath":"en/incomplete/cockpit.md","lastUpdated":1747984962000}'),l={name:"en/incomplete/cockpit.md"};function n(h,s,p,o,r,c){return t(),i("div",null,s[0]||(s[0]=[e("",18)]))}const g=a(l,[["render",n]]);export{k as __pageData,g as default}; diff --git a/assets/en_incomplete_cockpit.md.a60c11d2.js b/assets/en_incomplete_cockpit.md.a60c11d2.js deleted file mode 100644 index f01cc79f4d..0000000000 --- a/assets/en_incomplete_cockpit.md.a60c11d2.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as e,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/cockpit.md","filePath":"en/incomplete/cockpit.md","lastUpdated":1747972048000}'),t={name:"en/incomplete/cockpit.md"},n=l('

Repo

hits

https://github.com/oneclickvirt/cockpit

Installation

Supported Systems: Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

Install only with Podman containers

shell
bash install.sh --ct

Install only with virtual machines

shell
bash install.sh --vm

Panel Mount Only

shell
bash install.sh

Both container and VM dependencies are installed

shell
bash install.sh --all

Disadvantages

The network is self-configuring, the mirrors are self-importing, the ports are self-mapped, and there is just one more GUI interface than the command line.

Thanks

https://cockpit-project.org/running.html

',18),o=[n];function p(c,r,i,h,d,C){return a(),e("div",null,o)}const u=s(t,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/en_incomplete_cockpit.md.a60c11d2.lean.js b/assets/en_incomplete_cockpit.md.a60c11d2.lean.js deleted file mode 100644 index f01cc79f4d..0000000000 --- a/assets/en_incomplete_cockpit.md.a60c11d2.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as e,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/cockpit.md","filePath":"en/incomplete/cockpit.md","lastUpdated":1747972048000}'),t={name:"en/incomplete/cockpit.md"},n=l('

Repo

hits

https://github.com/oneclickvirt/cockpit

Installation

Supported Systems: Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

Install only with Podman containers

shell
bash install.sh --ct

Install only with virtual machines

shell
bash install.sh --vm

Panel Mount Only

shell
bash install.sh

Both container and VM dependencies are installed

shell
bash install.sh --all

Disadvantages

The network is self-configuring, the mirrors are self-importing, the ports are self-mapped, and there is just one more GUI interface than the command line.

Thanks

https://cockpit-project.org/running.html

',18),o=[n];function p(c,r,i,h,d,C){return a(),e("div",null,o)}const u=s(t,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/en_incomplete_convoy.md.ClbXbvA3.js b/assets/en_incomplete_convoy.md.ClbXbvA3.js new file mode 100644 index 0000000000..3a9f14c670 --- /dev/null +++ b/assets/en_incomplete_convoy.md.ClbXbvA3.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/convoy.md","filePath":"en/incomplete/convoy.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/convoy.md"};function o(l,a,r,p,h,c){return s(),e("div",null,a[0]||(a[0]=[i('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

One-click installation of convoy panel

Prerequisites for installation:

  • PVE is installed, but not the same node(not the same machine)
  • System is debian 11
  • CPU at least 2 cores, hard disk at least 20G, memory at least 4G (memory covers swap)

I don't guarantee that this script is error-free, it's just for my own amusement.

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',13)]))}const m=t(n,[["render",o]]);export{d as __pageData,m as default}; diff --git a/assets/en_incomplete_convoy.md.ClbXbvA3.lean.js b/assets/en_incomplete_convoy.md.ClbXbvA3.lean.js new file mode 100644 index 0000000000..8959afdc04 --- /dev/null +++ b/assets/en_incomplete_convoy.md.ClbXbvA3.lean.js @@ -0,0 +1 @@ +import{_ as t,c as e,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/convoy.md","filePath":"en/incomplete/convoy.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/convoy.md"};function o(l,a,r,p,h,c){return s(),e("div",null,a[0]||(a[0]=[i("",13)]))}const m=t(n,[["render",o]]);export{d as __pageData,m as default}; diff --git a/assets/en_incomplete_convoy.md.ccd54afd.js b/assets/en_incomplete_convoy.md.ccd54afd.js deleted file mode 100644 index e0a64e1257..0000000000 --- a/assets/en_incomplete_convoy.md.ccd54afd.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as s,R as o}from"./chunks/framework.70afa331.js";const v=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/convoy.md","filePath":"en/incomplete/convoy.md","lastUpdated":1747972048000}'),t={name:"en/incomplete/convoy.md"},n=o('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

One-click installation of convoy panel

Prerequisites for installation:

  • PVE is installed, but not the same node(not the same machine)
  • System is debian 11
  • CPU at least 2 cores, hard disk at least 20G, memory at least 4G (memory covers swap)

I don't guarantee that this script is error-free, it's just for my own amusement.

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',13),l=[n];function p(r,c,i,h,y,m){return e(),s("div",null,l)}const C=a(t,[["render",p]]);export{v as __pageData,C as default}; diff --git a/assets/en_incomplete_convoy.md.ccd54afd.lean.js b/assets/en_incomplete_convoy.md.ccd54afd.lean.js deleted file mode 100644 index e0a64e1257..0000000000 --- a/assets/en_incomplete_convoy.md.ccd54afd.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as s,R as o}from"./chunks/framework.70afa331.js";const v=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/convoy.md","filePath":"en/incomplete/convoy.md","lastUpdated":1747972048000}'),t={name:"en/incomplete/convoy.md"},n=o('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

One-click installation of convoy panel

Prerequisites for installation:

  • PVE is installed, but not the same node(not the same machine)
  • System is debian 11
  • CPU at least 2 cores, hard disk at least 20G, memory at least 4G (memory covers swap)

I don't guarantee that this script is error-free, it's just for my own amusement.

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',13),l=[n];function p(r,c,i,h,y,m){return e(),s("div",null,l)}const C=a(t,[["render",p]]);export{v as __pageData,C as default}; diff --git a/assets/en_incomplete_index.md.675215c6.js b/assets/en_incomplete_index.md.B8q1NrDT.js similarity index 87% rename from assets/en_incomplete_index.md.675215c6.js rename to assets/en_incomplete_index.md.B8q1NrDT.js index 97da95921f..f1b26b9a50 100644 --- a/assets/en_incomplete_index.md.675215c6.js +++ b/assets/en_incomplete_index.md.B8q1NrDT.js @@ -1 +1 @@ -import{_ as e,v as t,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse(`{"title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","description":"","frontmatter":{"layout":"home","title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","hero":{"name":"Other Virtualization Projects","text":"Some incomplete virtualization projects","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"View Projects →","link":"/en/incomplete/webvirtcloud"}]},"features":[{"title":"Notes","details":"Each item in this block has a corresponding drawback, and each item is not as easy to use as the previous ones, and has a certain learning cost."},{"title":"Degree of difficulty","details":"Based on the difficulty of using the program itself, sorted from easiest to hardest, the further back you go the less guidance you'll get with this guide."},{"title":"Project disadvantages","details":"Each project has some drawbacks that result in it not being considered a complete one-click project, and there are some operations that require manual execution of commands that cannot be one-clicked."}]},"headers":[],"relativePath":"en/incomplete/index.md","filePath":"en/incomplete/index.md","lastUpdated":1747972048000}`),a={name:"en/incomplete/index.md"};function o(n,s,r,c,l,d){return t(),i("div")}const p=e(a,[["render",o]]);export{m as __pageData,p as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse(`{"title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","description":"","frontmatter":{"layout":"home","title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","hero":{"name":"Other Virtualization Projects","text":"Some incomplete virtualization projects","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"View Projects →","link":"/en/incomplete/webvirtcloud"}]},"features":[{"title":"Notes","details":"Each item in this block has a corresponding drawback, and each item is not as easy to use as the previous ones, and has a certain learning cost."},{"title":"Degree of difficulty","details":"Based on the difficulty of using the program itself, sorted from easiest to hardest, the further back you go the less guidance you'll get with this guide."},{"title":"Project disadvantages","details":"Each project has some drawbacks that result in it not being considered a complete one-click project, and there are some operations that require manual execution of commands that cannot be one-clicked."}]},"headers":[],"relativePath":"en/incomplete/index.md","filePath":"en/incomplete/index.md","lastUpdated":1747984962000}`),i={name:"en/incomplete/index.md"};function o(n,r,s,c,l,d){return a(),t("div")}const p=e(i,[["render",o]]);export{m as __pageData,p as default}; diff --git a/assets/en_incomplete_index.md.675215c6.lean.js b/assets/en_incomplete_index.md.B8q1NrDT.lean.js similarity index 87% rename from assets/en_incomplete_index.md.675215c6.lean.js rename to assets/en_incomplete_index.md.B8q1NrDT.lean.js index 97da95921f..f1b26b9a50 100644 --- a/assets/en_incomplete_index.md.675215c6.lean.js +++ b/assets/en_incomplete_index.md.B8q1NrDT.lean.js @@ -1 +1 @@ -import{_ as e,v as t,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse(`{"title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","description":"","frontmatter":{"layout":"home","title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","hero":{"name":"Other Virtualization Projects","text":"Some incomplete virtualization projects","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"View Projects →","link":"/en/incomplete/webvirtcloud"}]},"features":[{"title":"Notes","details":"Each item in this block has a corresponding drawback, and each item is not as easy to use as the previous ones, and has a certain learning cost."},{"title":"Degree of difficulty","details":"Based on the difficulty of using the program itself, sorted from easiest to hardest, the further back you go the less guidance you'll get with this guide."},{"title":"Project disadvantages","details":"Each project has some drawbacks that result in it not being considered a complete one-click project, and there are some operations that require manual execution of commands that cannot be one-clicked."}]},"headers":[],"relativePath":"en/incomplete/index.md","filePath":"en/incomplete/index.md","lastUpdated":1747972048000}`),a={name:"en/incomplete/index.md"};function o(n,s,r,c,l,d){return t(),i("div")}const p=e(a,[["render",o]]);export{m as __pageData,p as default}; +import{_ as e,c as t,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse(`{"title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","description":"","frontmatter":{"layout":"home","title":"Other Virtualization Projects","titleTemplate":"Other Incomplete Virtualization Projects","hero":{"name":"Other Virtualization Projects","text":"Some incomplete virtualization projects","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"View Projects →","link":"/en/incomplete/webvirtcloud"}]},"features":[{"title":"Notes","details":"Each item in this block has a corresponding drawback, and each item is not as easy to use as the previous ones, and has a certain learning cost."},{"title":"Degree of difficulty","details":"Based on the difficulty of using the program itself, sorted from easiest to hardest, the further back you go the less guidance you'll get with this guide."},{"title":"Project disadvantages","details":"Each project has some drawbacks that result in it not being considered a complete one-click project, and there are some operations that require manual execution of commands that cannot be one-clicked."}]},"headers":[],"relativePath":"en/incomplete/index.md","filePath":"en/incomplete/index.md","lastUpdated":1747984962000}`),i={name:"en/incomplete/index.md"};function o(n,r,s,c,l,d){return a(),t("div")}const p=e(i,[["render",o]]);export{m as __pageData,p as default}; diff --git a/assets/en_incomplete_pterodactyl.md.CFqYcu_4.js b/assets/en_incomplete_pterodactyl.md.CFqYcu_4.js new file mode 100644 index 0000000000..d981ea9af5 --- /dev/null +++ b/assets/en_incomplete_pterodactyl.md.CFqYcu_4.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as a,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/pterodactyl.md","filePath":"en/incomplete/pterodactyl.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/pterodactyl.md"};function h(l,s,p,r,d,o){return a(),i("div",null,s[0]||(s[0]=[e('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

After further research, it was found that creating servers and binding users is too cumbersome compared to using native Docker directly, so further development is currently suspended.

Description

Currently supported systems:

OS TypeVersion RangeNotes
Ubuntu20.04 (recommended), 22.04, 24.04Supported
Debian11 (Bullseye), 12 (Bookworm)Supported

Panel

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

On the wings side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

This will generate a command to be executed on the wings side.

After executing the generated command, wait for more than 20 seconds to avoid issues caused by unfinished initialization processes. Then on the wings side, run:

shell
bash install_wings.sh

Then go to http://<your_ip>/admin/nodes and you should see your node has been automatically added and managed, with a green heartbeat.

Thanks

https://pterodactyl.io/

',23)]))}const g=t(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/en_incomplete_pterodactyl.md.CFqYcu_4.lean.js b/assets/en_incomplete_pterodactyl.md.CFqYcu_4.lean.js new file mode 100644 index 0000000000..19e33cfa87 --- /dev/null +++ b/assets/en_incomplete_pterodactyl.md.CFqYcu_4.lean.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as a,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/pterodactyl.md","filePath":"en/incomplete/pterodactyl.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/pterodactyl.md"};function h(l,s,p,r,d,o){return a(),i("div",null,s[0]||(s[0]=[e("",23)]))}const g=t(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/en_incomplete_pterodactyl.md.df0ba4ff.js b/assets/en_incomplete_pterodactyl.md.df0ba4ff.js deleted file mode 100644 index 6fc2cd89b7..0000000000 --- a/assets/en_incomplete_pterodactyl.md.df0ba4ff.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as t,R as e}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/pterodactyl.md","filePath":"en/incomplete/pterodactyl.md","lastUpdated":1747972048000}'),n={name:"en/incomplete/pterodactyl.md"},o=e('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

After further research, it was found that creating servers and binding users is too cumbersome compared to using native Docker directly, so further development is currently suspended.

Description

Currently supported systems:

OS TypeVersion RangeNotes
Ubuntu20.04 (recommended), 22.04, 24.04Supported
Debian11 (Bullseye), 12 (Bookworm)Supported

Panel

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

On the wings side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

This will generate a command to be executed on the wings side.

After executing the generated command, wait for more than 20 seconds to avoid issues caused by unfinished initialization processes. Then on the wings side, run:

shell
bash install_wings.sh

Then go to http://<your_ip>/admin/nodes and you should see your node has been automatically added and managed, with a green heartbeat.

Thanks

https://pterodactyl.io/

',23),l=[o];function p(r,c,i,d,h,y){return a(),t("div",null,l)}const u=s(n,[["render",p]]);export{m as __pageData,u as default}; diff --git a/assets/en_incomplete_pterodactyl.md.df0ba4ff.lean.js b/assets/en_incomplete_pterodactyl.md.df0ba4ff.lean.js deleted file mode 100644 index 6fc2cd89b7..0000000000 --- a/assets/en_incomplete_pterodactyl.md.df0ba4ff.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as t,R as e}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/pterodactyl.md","filePath":"en/incomplete/pterodactyl.md","lastUpdated":1747972048000}'),n={name:"en/incomplete/pterodactyl.md"},o=e('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

After further research, it was found that creating servers and binding users is too cumbersome compared to using native Docker directly, so further development is currently suspended.

Description

Currently supported systems:

OS TypeVersion RangeNotes
Ubuntu20.04 (recommended), 22.04, 24.04Supported
Debian11 (Bullseye), 12 (Bookworm)Supported

Panel

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

On the wings side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

This will generate a command to be executed on the wings side.

After executing the generated command, wait for more than 20 seconds to avoid issues caused by unfinished initialization processes. Then on the wings side, run:

shell
bash install_wings.sh

Then go to http://<your_ip>/admin/nodes and you should see your node has been automatically added and managed, with a green heartbeat.

Thanks

https://pterodactyl.io/

',23),l=[o];function p(r,c,i,d,h,y){return a(),t("div",null,l)}const u=s(n,[["render",p]]);export{m as __pageData,u as default}; diff --git a/assets/en_incomplete_virtfusion.md.C7tkSFJE.js b/assets/en_incomplete_virtfusion.md.C7tkSFJE.js new file mode 100644 index 0000000000..e74492a184 --- /dev/null +++ b/assets/en_incomplete_virtfusion.md.C7tkSFJE.js @@ -0,0 +1,7 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtfusion.md","filePath":"en/incomplete/virtfusion.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/virtfusion.md"};function e(h,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[l(`

Official Documents

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

One-click Installation

debian11

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

Disadvantages

Only one 30-day trial certificate per server per mailbox, no permanent free certificates

`,17)]))}const c=i(n,[["render",e]]);export{o as __pageData,c as default}; diff --git a/assets/en_incomplete_virtfusion.md.C7tkSFJE.lean.js b/assets/en_incomplete_virtfusion.md.C7tkSFJE.lean.js new file mode 100644 index 0000000000..12a2c4b16c --- /dev/null +++ b/assets/en_incomplete_virtfusion.md.C7tkSFJE.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtfusion.md","filePath":"en/incomplete/virtfusion.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/virtfusion.md"};function e(h,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[l("",17)]))}const c=i(n,[["render",e]]);export{o as __pageData,c as default}; diff --git a/assets/en_incomplete_virtfusion.md.e7f03a8b.js b/assets/en_incomplete_virtfusion.md.e7f03a8b.js deleted file mode 100644 index 5122fe216f..0000000000 --- a/assets/en_incomplete_virtfusion.md.e7f03a8b.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtfusion.md","filePath":"en/incomplete/virtfusion.md","lastUpdated":1747972048000}'),o={name:"en/incomplete/virtfusion.md"},p=n(`

Official Documents

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

One-click Installation

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

Disadvantages

Only one 30-day trial certificate per server per mailbox, no permanent free certificates

`,17),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const d=s(o,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/en_incomplete_virtfusion.md.e7f03a8b.lean.js b/assets/en_incomplete_virtfusion.md.e7f03a8b.lean.js deleted file mode 100644 index 5122fe216f..0000000000 --- a/assets/en_incomplete_virtfusion.md.e7f03a8b.lean.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtfusion.md","filePath":"en/incomplete/virtfusion.md","lastUpdated":1747972048000}'),o={name:"en/incomplete/virtfusion.md"},p=n(`

Official Documents

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

One-click Installation

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

Disadvantages

Only one 30-day trial certificate per server per mailbox, no permanent free certificates

`,17),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const d=s(o,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/en_incomplete_virtualizor-docker.md.449703b7.js b/assets/en_incomplete_virtualizor-docker.md.449703b7.js deleted file mode 100644 index 50f4fd591f..0000000000 --- a/assets/en_incomplete_virtualizor-docker.md.449703b7.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as i}from"./chunks/framework.70afa331.js";const v=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtualizor-docker.md","filePath":"en/incomplete/virtualizor-docker.md","lastUpdated":1747972048000}'),o={name:"en/incomplete/virtualizor-docker.md"},r=i('

Repo

https://github.com/ivstiv/virtualizor-docker

Description

The virtualizor opened in the docker

The certificate used is a trial certificate, valid for one day, and only the OpenVZ virtualization method is installed by default

Disadvantages

There is no community, so you have to figure it out on your own.

Ports for admin panel Don't look at the script's prompt messages, go with the repository instructions.

',8),s=[r];function n(d,c,p,l,h,u){return t(),a("div",null,s)}const f=e(o,[["render",n]]);export{v as __pageData,f as default}; diff --git a/assets/en_incomplete_virtualizor-docker.md.449703b7.lean.js b/assets/en_incomplete_virtualizor-docker.md.449703b7.lean.js deleted file mode 100644 index 50f4fd591f..0000000000 --- a/assets/en_incomplete_virtualizor-docker.md.449703b7.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as i}from"./chunks/framework.70afa331.js";const v=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtualizor-docker.md","filePath":"en/incomplete/virtualizor-docker.md","lastUpdated":1747972048000}'),o={name:"en/incomplete/virtualizor-docker.md"},r=i('

Repo

https://github.com/ivstiv/virtualizor-docker

Description

The virtualizor opened in the docker

The certificate used is a trial certificate, valid for one day, and only the OpenVZ virtualization method is installed by default

Disadvantages

There is no community, so you have to figure it out on your own.

Ports for admin panel Don't look at the script's prompt messages, go with the repository instructions.

',8),s=[r];function n(d,c,p,l,h,u){return t(),a("div",null,s)}const f=e(o,[["render",n]]);export{v as __pageData,f as default}; diff --git a/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.js b/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.js new file mode 100644 index 0000000000..73d1fb5ddd --- /dev/null +++ b/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.js @@ -0,0 +1 @@ +import{_ as t,c as a,o,ag as r}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtualizor-docker.md","filePath":"en/incomplete/virtualizor-docker.md","lastUpdated":1747984962000}'),i={name:"en/incomplete/virtualizor-docker.md"};function n(s,e,d,l,p,c){return o(),a("div",null,e[0]||(e[0]=[r('

Repo

https://github.com/ivstiv/virtualizor-docker

Description

The virtualizor opened in the docker

The certificate used is a trial certificate, valid for one day, and only the OpenVZ virtualization method is installed by default

Disadvantages

There is no community, so you have to figure it out on your own.

Ports for admin panel Don't look at the script's prompt messages, go with the repository instructions.

',8)]))}const m=t(i,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.lean.js b/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.lean.js new file mode 100644 index 0000000000..3f25bc7bb5 --- /dev/null +++ b/assets/en_incomplete_virtualizor-docker.md.CKtWMSs2.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o,ag as r}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/virtualizor-docker.md","filePath":"en/incomplete/virtualizor-docker.md","lastUpdated":1747984962000}'),i={name:"en/incomplete/virtualizor-docker.md"};function n(s,e,d,l,p,c){return o(),a("div",null,e[0]||(e[0]=[r("",8)]))}const m=t(i,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.js b/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.js new file mode 100644 index 0000000000..77064d88a7 --- /dev/null +++ b/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.js @@ -0,0 +1,45 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const n="/assets/wv1.8ARiSJ9x.png",g=JSON.parse('{"title":"WebVirtCloud Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud.md","filePath":"en/incomplete/webvirtcloud.md","lastUpdated":1747984962000}'),l={name:"en/incomplete/webvirtcloud.md"};function p(h,s,r,o,k,d){return t(),a("div",null,s[0]||(s[0]=[e(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Original project repository: https://github.com/webvirtcloud/webvirtcloud

1. Controller Installation

System Requirements

Minimum Requirements:

  • CPU: 1 core
  • Memory: 1 GB RAM
  • Storage: 10 GB free space
  • System: Debian11+, Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

Default Login Information

  • Username: admin@webvirt.cloud
  • Password: admin

Panel Access

  • User Panel: https://192-168-0-114.nip.io
  • Admin Backend: https://192-168-0-114.nip.io/admin

Note: Replace 192.168.0.114 with your public IP to get the actual accessible address.

Installation Command

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
+&& chmod +x install_webvirt_cloud.sh \\
+&& bash install_webvirt_cloud.sh

TIP

The execution process may be stuck in the clone repository has not been moving, at this time, press ctrl + c to exit the implementation, re-execution of the installation script on the line, the Department of Docker installation is stuck in the stage of the build project.

2. Compute Node Installation

Important: Hypervisor and Controller cannot be installed on the same virtual machine, otherwise network conflicts will occur.

System Requirements

Recommended Configuration:

  • CPU: 2 cores
  • Memory: 4 GB RAM
  • Storage: 40 GB free space
  • System: AlmaLinux8+, RockyLinux8+

Additional Notes:

  • Higher configurations are recommended for actual use; the test environment is only sufficient for running 4 minimal virtual machines.
  • Servers with KVM nested virtualization support are recommended. If VM-x/AMD-V/Hyper-V is not enabled, it will automatically switch to QEMU using TCG emulation to set up virtual machines, though performance will be reduced.
  • The installation skips environment checks and uses binary files directly, so no dependencies need to be installed.

Environment Check

Check if the server supports KVM nested virtualization:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

Select hardware individual test

Compute Node Installation Steps

  1. Download the installation script:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    +&& chmod +x install_hypervisor.sh
  2. Execute installation (replace with your Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    Replace x.x.x.x with the actual IP address of your Controller.

  3. Node Management in Panel
    After execution, there will be prompts for information needed in the Controller panel.
    In the panel, the Hostname to be entered is the current compute node's IPv4 address, and you need to enter the Token to identify the node.

NetworkManager Version Issue

During installation, you may encounter the following error:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
+Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
+Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

Solution: Restart the server and re-execute the installation command.

Installation Time Note

  • The entire process takes approximately 10-25 minutes.
  • Most of the time is spent downloading finnix-125.iso to /var/lib/libvirt/isos/finnix-125.iso.
  • This part cannot be accelerated, so it's recommended to use tmux or screen to prevent interruption.

Adding Compute Node to Control Panel

After installation, a Token will be generated for adding the compute node in the control panel (Admin panel):

Path: Admin Panel > Computers > Add Computer

  • HostName should be filled with the compute node's public IPv4 address
  • Token should be filled with the token key obtained on the compute node

3. Public IPv4 Port Mapping

3.1 Automatic Mapping

Automatic mapping features:

  • Automatic Monitoring: Real-time monitoring of virtual machine status changes, automatically applying or cleaning up port mapping rules
  • Intelligent Port Allocation: Automatically calculating and allocating non-conflicting ports based on VM IP addresses
  • Rule Persistence: Using firewall-cmd to ensure port mapping rules remain effective after host restart
  • Mapping Records: Automatically maintaining mapping information records for easy viewing and management
  • Conflict Prevention: Intelligently detecting and avoiding port conflicts, ensuring each VM has unique port mappings

Installation Method

  1. Download the script to a temporary directory:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. Add execution permission:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. Run the installer:

    bash
    /tmp/vm_port_mapping_setup.sh

The script will automatically complete the following operations:

  • Copy itself to the system directory /usr/local/sbin/vm_port_mapping_daemon.sh
  • Create a systemd service unit file
  • Enable and start the service

Port Mapping Rules

The daemon will assign the following ports for each virtual machine:

  1. SSH Port:

    • Calculation formula: (Last segment of IP) × 100 + 22 + 10000
    • Example: For IP address 192.168.33.114, the mapped SSH port is 114×100+22+10000 = 21422
  2. Extra Ports:

    • 10 additional ports are allocated for each VM
    • Starting port: 20000 + (Last segment of IP) × 100
    • Ending port: Starting port + 9
    • Example: For IP address 192.168.33.114, extra port range is 20000+(114×100) to 20000+(114×100)+9

If the calculated port is already occupied, the program will automatically find the next available port to ensure no conflicts occur.

Mapping File

All port mapping information is saved in the /etc/vm_port_mapping/mapping.txt file, in the format:

VM name IP address MAC address SSH mapped port Extra ports start Extra ports end

For example:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

Service Management

  • Check service status:

    bash
    systemctl status vm-port-mapping
  • Start service:

    bash
    systemctl start vm-port-mapping
  • Stop service:

    bash
    systemctl stop vm-port-mapping
  • Disable auto-start:

    bash
    systemctl disable vm-port-mapping
  • View logs:

    bash
    journalctl -u vm-port-mapping
    +# or
    +cat /var/log/vm_port_mapping.log
  • Manually trigger rule update:

    bash
    systemctl restart vm-port-mapping

Common Issues

Port mapping not working

Check the following:

  • Confirm the service is running: systemctl status vm-port-mapping
  • Check the log file: cat /var/log/vm_port_mapping.log
  • Ensure the firewall service is normal: systemctl status firewalld
  • Verify VM network interface configuration: virsh domiflist VM-name
Manually adding mapping rules

Usually, manual addition of rules is not needed, but if necessary:

  1. Stop the service:

    bash
    systemctl stop vm-port-mapping
  2. Edit the mapping file:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. Start the service:

    bash
    systemctl start vm-port-mapping
Cleaning all rules
bash
systemctl stop vm-port-mapping
+grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
+  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
+  for ((port=port_start; port<=port_end; port++)); do
+    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
+  done
+done
+firewall-cmd --reload
Security Recommendations
  • Regularly check mapping files and logs to ensure there are no unauthorized mappings
  • Do not manually modify files in the /etc/vm_port_mapping/ directory unless you fully understand the impact
  • Make sure the firewalld service is running properly so that rules can be correctly persisted

Uninstallation Method

To uninstall this service:

bash
systemctl stop vm-port-mapping
+systemctl disable vm-port-mapping
+rm -f /etc/systemd/system/vm-port-mapping.service
+rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
+rm -rf /etc/vm_port_mapping
+systemctl daemon-reload

3.2 Manual Mapping

Assume your virtual machine is shown in the user control panel as

wv1

and the host machine command ip a | head -n 15 result is

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    inet 127.0.0.1/8 scope host lo
+       valid_lft forever preferred_lft forever
+    inet6 ::1/128 scope host
+       valid_lft forever preferred_lft forever
+2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
+    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
+    altname enp0s3
+    inet your_public_IPv4_address/corresponding_subnet_mask scope global noprefixroute ens3
+       valid_lft forever preferred_lft forever
+    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
+       valid_lft forever preferred_lft forever
+    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
+       valid_lft forever preferred_lft forever

It's evident that the public IPv4 address is bound to the ens3 interface, so we'll use ens3 in the following commands.

To map the current VM's port 22 to the public IPv4's port 3322, use:

shell
# Add DNAT rule: Forward public 3322 traffic to host local 192.168.33.130:22
+iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
+# Add POSTROUTING: Local NAT masquerading for normal return connections
+iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
+# Need to allow INPUT port 3322 through (firewalld is enabled by default)
+iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

This way, the internal virtual machine is mapped out and can be remotely logged in directly.

4. Troubleshooting

Compute Node Addition Error Troubleshooting

Execute on the Controller:

shell
telnet <node ip> 8884

Execute on the compute node:

shell
systemctl status webvirtcompute
+systemctl status libvirtd
+systemctl status prometheus
+systemctl status prometheus-libvirt-exporter

If none of the above reveals the problem, then you need to execute on the Controller:

shell
docker exec -it webvirtcloud-backend /bin/sh
+vi webvirtcloud/settings/production.py

Change DEBUG=False to DEBUG=True, save the file, then execute in the container:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

Then exit the container and execute:

shell
docker restart webvirtcloud-backend
+sleep 3
+docker logs webvirtcloud-backend -f

Then trigger the error in the frontend, and you'll see the corresponding error in the real-time loaded logs.

Docker Containers Not Auto-Restarting After Controller Reboot

If Docker containers don't automatically restart after system reboot, execute:

bash
docker start $(docker ps -a -q)

5. Drawbacks

System images are hard-coded; you can't use your own custom images, nor export them for use.

This is not the same project as https://github.com/retspen/webvirtcloud, don't confuse them.

Acknowledgements

https://webvirt.cloud/

`,101)]))}const F=i(l,[["render",p]]);export{g as __pageData,F as default}; diff --git a/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.lean.js b/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.lean.js new file mode 100644 index 0000000000..c97e4f5902 --- /dev/null +++ b/assets/en_incomplete_webvirtcloud.md.DfzbkCBK.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const n="/assets/wv1.8ARiSJ9x.png",g=JSON.parse('{"title":"WebVirtCloud Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud.md","filePath":"en/incomplete/webvirtcloud.md","lastUpdated":1747984962000}'),l={name:"en/incomplete/webvirtcloud.md"};function p(h,s,r,o,k,d){return t(),a("div",null,s[0]||(s[0]=[e("",101)]))}const F=i(l,[["render",p]]);export{g as __pageData,F as default}; diff --git a/assets/en_incomplete_webvirtcloud.md.a6e9dff8.js b/assets/en_incomplete_webvirtcloud.md.a6e9dff8.js deleted file mode 100644 index f6b8b64d74..0000000000 --- a/assets/en_incomplete_webvirtcloud.md.a6e9dff8.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const o="/assets/wv1.5ac4a026.png",D=JSON.parse('{"title":"WebVirtCloud Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud.md","filePath":"en/incomplete/webvirtcloud.md","lastUpdated":1747972048000}'),e={name:"en/incomplete/webvirtcloud.md"},t=l(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Original project repository: https://github.com/webvirtcloud/webvirtcloud

1. Controller Installation

System Requirements

Minimum Requirements:

  • CPU: 1 core
  • Memory: 1 GB RAM
  • Storage: 10 GB free space
  • System: Debian11+, Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

Default Login Information

  • Username: admin@webvirt.cloud
  • Password: admin

Panel Access

  • User Panel: https://192-168-0-114.nip.io
  • Admin Backend: https://192-168-0-114.nip.io/admin

Note: Replace 192.168.0.114 with your public IP to get the actual accessible address.

Installation Command

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

TIP

The execution process may be stuck in the clone repository has not been moving, at this time, press ctrl + c to exit the implementation, re-execution of the installation script on the line, the Department of Docker installation is stuck in the stage of the build project.

2. Compute Node Installation

Important: Hypervisor and Controller cannot be installed on the same virtual machine, otherwise network conflicts will occur.

System Requirements

Recommended Configuration:

  • CPU: 2 cores
  • Memory: 4 GB RAM
  • Storage: 40 GB free space
  • System: AlmaLinux8+, RockyLinux8+

Additional Notes:

  • Higher configurations are recommended for actual use; the test environment is only sufficient for running 4 minimal virtual machines.
  • Servers with KVM nested virtualization support are recommended. If VM-x/AMD-V/Hyper-V is not enabled, it will automatically switch to QEMU using TCG emulation to set up virtual machines, though performance will be reduced.
  • The installation skips environment checks and uses binary files directly, so no dependencies need to be installed.

Environment Check

Check if the server supports KVM nested virtualization:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

Select hardware individual test

Compute Node Installation Steps

  1. Download the installation script:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh
  2. Execute installation (replace with your Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    Replace x.x.x.x with the actual IP address of your Controller.

  3. Node Management in Panel
    After execution, there will be prompts for information needed in the Controller panel.
    In the panel, the Hostname to be entered is the current compute node's IPv4 address, and you need to enter the Token to identify the node.

NetworkManager Version Issue

During installation, you may encounter the following error:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

Solution: Restart the server and re-execute the installation command.

Installation Time Note

  • The entire process takes approximately 10-25 minutes.
  • Most of the time is spent downloading finnix-125.iso to /var/lib/libvirt/isos/finnix-125.iso.
  • This part cannot be accelerated, so it's recommended to use tmux or screen to prevent interruption.

Adding Compute Node to Control Panel

After installation, a Token will be generated for adding the compute node in the control panel (Admin panel):

Path: Admin Panel > Computers > Add Computer

  • HostName should be filled with the compute node's public IPv4 address
  • Token should be filled with the token key obtained on the compute node

3. Public IPv4 Port Mapping

3.1 Automatic Mapping

Automatic mapping features:

  • Automatic Monitoring: Real-time monitoring of virtual machine status changes, automatically applying or cleaning up port mapping rules
  • Intelligent Port Allocation: Automatically calculating and allocating non-conflicting ports based on VM IP addresses
  • Rule Persistence: Using firewall-cmd to ensure port mapping rules remain effective after host restart
  • Mapping Records: Automatically maintaining mapping information records for easy viewing and management
  • Conflict Prevention: Intelligently detecting and avoiding port conflicts, ensuring each VM has unique port mappings

Installation Method

  1. Download the script to a temporary directory:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. Add execution permission:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. Run the installer:

    bash
    /tmp/vm_port_mapping_setup.sh

The script will automatically complete the following operations:

  • Copy itself to the system directory /usr/local/sbin/vm_port_mapping_daemon.sh
  • Create a systemd service unit file
  • Enable and start the service

Port Mapping Rules

The daemon will assign the following ports for each virtual machine:

  1. SSH Port:

    • Calculation formula: (Last segment of IP) × 100 + 22 + 10000
    • Example: For IP address 192.168.33.114, the mapped SSH port is 114×100+22+10000 = 21422
  2. Extra Ports:

    • 10 additional ports are allocated for each VM
    • Starting port: 20000 + (Last segment of IP) × 100
    • Ending port: Starting port + 9
    • Example: For IP address 192.168.33.114, extra port range is 20000+(114×100) to 20000+(114×100)+9

If the calculated port is already occupied, the program will automatically find the next available port to ensure no conflicts occur.

Mapping File

All port mapping information is saved in the /etc/vm_port_mapping/mapping.txt file, in the format:

VM name IP address MAC address SSH mapped port Extra ports start Extra ports end

For example:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

Service Management

  • Check service status:

    bash
    systemctl status vm-port-mapping
  • Start service:

    bash
    systemctl start vm-port-mapping
  • Stop service:

    bash
    systemctl stop vm-port-mapping
  • Disable auto-start:

    bash
    systemctl disable vm-port-mapping
  • View logs:

    bash
    journalctl -u vm-port-mapping
    -# or
    -cat /var/log/vm_port_mapping.log
  • Manually trigger rule update:

    bash
    systemctl restart vm-port-mapping

Common Issues

Port mapping not working

Check the following:

  • Confirm the service is running: systemctl status vm-port-mapping
  • Check the log file: cat /var/log/vm_port_mapping.log
  • Ensure the firewall service is normal: systemctl status firewalld
  • Verify VM network interface configuration: virsh domiflist VM-name
Manually adding mapping rules

Usually, manual addition of rules is not needed, but if necessary:

  1. Stop the service:

    bash
    systemctl stop vm-port-mapping
  2. Edit the mapping file:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. Start the service:

    bash
    systemctl start vm-port-mapping
Cleaning all rules
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
Security Recommendations
  • Regularly check mapping files and logs to ensure there are no unauthorized mappings
  • Do not manually modify files in the /etc/vm_port_mapping/ directory unless you fully understand the impact
  • Make sure the firewalld service is running properly so that rules can be correctly persisted

Uninstallation Method

To uninstall this service:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 Manual Mapping

Assume your virtual machine is shown in the user control panel as

wv1

and the host machine command ip a | head -n 15 result is

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet your_public_IPv4_address/corresponding_subnet_mask scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

It's evident that the public IPv4 address is bound to the ens3 interface, so we'll use ens3 in the following commands.

To map the current VM's port 22 to the public IPv4's port 3322, use:

shell
# Add DNAT rule: Forward public 3322 traffic to host local 192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# Add POSTROUTING: Local NAT masquerading for normal return connections
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# Need to allow INPUT port 3322 through (firewalld is enabled by default)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

This way, the internal virtual machine is mapped out and can be remotely logged in directly.

4. Troubleshooting

Compute Node Addition Error Troubleshooting

Execute on the Controller:

shell
telnet <node ip> 8884

Execute on the compute node:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

If none of the above reveals the problem, then you need to execute on the Controller:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

Change DEBUG=False to DEBUG=True, save the file, then execute in the container:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

Then exit the container and execute:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

Then trigger the error in the frontend, and you'll see the corresponding error in the real-time loaded logs.

Docker Containers Not Auto-Restarting After Controller Reboot

If Docker containers don't automatically restart after system reboot, execute:

bash
docker start $(docker ps -a -q)

5. Drawbacks

System images are hard-coded; you can't use your own custom images, nor export them for use.

This is not the same project as https://github.com/retspen/webvirtcloud, don't confuse them.

Acknowledgements

https://webvirt.cloud/

`,101),p=[t];function r(c,i,C,y,d,A){return a(),n("div",null,p)}const u=s(e,[["render",r]]);export{D as __pageData,u as default}; diff --git a/assets/en_incomplete_webvirtcloud.md.a6e9dff8.lean.js b/assets/en_incomplete_webvirtcloud.md.a6e9dff8.lean.js deleted file mode 100644 index f6b8b64d74..0000000000 --- a/assets/en_incomplete_webvirtcloud.md.a6e9dff8.lean.js +++ /dev/null @@ -1,45 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const o="/assets/wv1.5ac4a026.png",D=JSON.parse('{"title":"WebVirtCloud Installation Guide","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud.md","filePath":"en/incomplete/webvirtcloud.md","lastUpdated":1747972048000}'),e={name:"en/incomplete/webvirtcloud.md"},t=l(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Original project repository: https://github.com/webvirtcloud/webvirtcloud

1. Controller Installation

System Requirements

Minimum Requirements:

  • CPU: 1 core
  • Memory: 1 GB RAM
  • Storage: 10 GB free space
  • System: Debian11+, Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

Default Login Information

  • Username: admin@webvirt.cloud
  • Password: admin

Panel Access

  • User Panel: https://192-168-0-114.nip.io
  • Admin Backend: https://192-168-0-114.nip.io/admin

Note: Replace 192.168.0.114 with your public IP to get the actual accessible address.

Installation Command

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

TIP

The execution process may be stuck in the clone repository has not been moving, at this time, press ctrl + c to exit the implementation, re-execution of the installation script on the line, the Department of Docker installation is stuck in the stage of the build project.

2. Compute Node Installation

Important: Hypervisor and Controller cannot be installed on the same virtual machine, otherwise network conflicts will occur.

System Requirements

Recommended Configuration:

  • CPU: 2 cores
  • Memory: 4 GB RAM
  • Storage: 40 GB free space
  • System: AlmaLinux8+, RockyLinux8+

Additional Notes:

  • Higher configurations are recommended for actual use; the test environment is only sufficient for running 4 minimal virtual machines.
  • Servers with KVM nested virtualization support are recommended. If VM-x/AMD-V/Hyper-V is not enabled, it will automatically switch to QEMU using TCG emulation to set up virtual machines, though performance will be reduced.
  • The installation skips environment checks and uses binary files directly, so no dependencies need to be installed.

Environment Check

Check if the server supports KVM nested virtualization:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

Select hardware individual test

Compute Node Installation Steps

  1. Download the installation script:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh
  2. Execute installation (replace with your Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    Replace x.x.x.x with the actual IP address of your Controller.

  3. Node Management in Panel
    After execution, there will be prompts for information needed in the Controller panel.
    In the panel, the Hostname to be entered is the current compute node's IPv4 address, and you need to enter the Token to identify the node.

NetworkManager Version Issue

During installation, you may encounter the following error:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

Solution: Restart the server and re-execute the installation command.

Installation Time Note

  • The entire process takes approximately 10-25 minutes.
  • Most of the time is spent downloading finnix-125.iso to /var/lib/libvirt/isos/finnix-125.iso.
  • This part cannot be accelerated, so it's recommended to use tmux or screen to prevent interruption.

Adding Compute Node to Control Panel

After installation, a Token will be generated for adding the compute node in the control panel (Admin panel):

Path: Admin Panel > Computers > Add Computer

  • HostName should be filled with the compute node's public IPv4 address
  • Token should be filled with the token key obtained on the compute node

3. Public IPv4 Port Mapping

3.1 Automatic Mapping

Automatic mapping features:

  • Automatic Monitoring: Real-time monitoring of virtual machine status changes, automatically applying or cleaning up port mapping rules
  • Intelligent Port Allocation: Automatically calculating and allocating non-conflicting ports based on VM IP addresses
  • Rule Persistence: Using firewall-cmd to ensure port mapping rules remain effective after host restart
  • Mapping Records: Automatically maintaining mapping information records for easy viewing and management
  • Conflict Prevention: Intelligently detecting and avoiding port conflicts, ensuring each VM has unique port mappings

Installation Method

  1. Download the script to a temporary directory:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. Add execution permission:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. Run the installer:

    bash
    /tmp/vm_port_mapping_setup.sh

The script will automatically complete the following operations:

  • Copy itself to the system directory /usr/local/sbin/vm_port_mapping_daemon.sh
  • Create a systemd service unit file
  • Enable and start the service

Port Mapping Rules

The daemon will assign the following ports for each virtual machine:

  1. SSH Port:

    • Calculation formula: (Last segment of IP) × 100 + 22 + 10000
    • Example: For IP address 192.168.33.114, the mapped SSH port is 114×100+22+10000 = 21422
  2. Extra Ports:

    • 10 additional ports are allocated for each VM
    • Starting port: 20000 + (Last segment of IP) × 100
    • Ending port: Starting port + 9
    • Example: For IP address 192.168.33.114, extra port range is 20000+(114×100) to 20000+(114×100)+9

If the calculated port is already occupied, the program will automatically find the next available port to ensure no conflicts occur.

Mapping File

All port mapping information is saved in the /etc/vm_port_mapping/mapping.txt file, in the format:

VM name IP address MAC address SSH mapped port Extra ports start Extra ports end

For example:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

Service Management

  • Check service status:

    bash
    systemctl status vm-port-mapping
  • Start service:

    bash
    systemctl start vm-port-mapping
  • Stop service:

    bash
    systemctl stop vm-port-mapping
  • Disable auto-start:

    bash
    systemctl disable vm-port-mapping
  • View logs:

    bash
    journalctl -u vm-port-mapping
    -# or
    -cat /var/log/vm_port_mapping.log
  • Manually trigger rule update:

    bash
    systemctl restart vm-port-mapping

Common Issues

Port mapping not working

Check the following:

  • Confirm the service is running: systemctl status vm-port-mapping
  • Check the log file: cat /var/log/vm_port_mapping.log
  • Ensure the firewall service is normal: systemctl status firewalld
  • Verify VM network interface configuration: virsh domiflist VM-name
Manually adding mapping rules

Usually, manual addition of rules is not needed, but if necessary:

  1. Stop the service:

    bash
    systemctl stop vm-port-mapping
  2. Edit the mapping file:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. Start the service:

    bash
    systemctl start vm-port-mapping
Cleaning all rules
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
Security Recommendations
  • Regularly check mapping files and logs to ensure there are no unauthorized mappings
  • Do not manually modify files in the /etc/vm_port_mapping/ directory unless you fully understand the impact
  • Make sure the firewalld service is running properly so that rules can be correctly persisted

Uninstallation Method

To uninstall this service:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 Manual Mapping

Assume your virtual machine is shown in the user control panel as

wv1

and the host machine command ip a | head -n 15 result is

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet your_public_IPv4_address/corresponding_subnet_mask scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

It's evident that the public IPv4 address is bound to the ens3 interface, so we'll use ens3 in the following commands.

To map the current VM's port 22 to the public IPv4's port 3322, use:

shell
# Add DNAT rule: Forward public 3322 traffic to host local 192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# Add POSTROUTING: Local NAT masquerading for normal return connections
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# Need to allow INPUT port 3322 through (firewalld is enabled by default)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

This way, the internal virtual machine is mapped out and can be remotely logged in directly.

4. Troubleshooting

Compute Node Addition Error Troubleshooting

Execute on the Controller:

shell
telnet <node ip> 8884

Execute on the compute node:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

If none of the above reveals the problem, then you need to execute on the Controller:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

Change DEBUG=False to DEBUG=True, save the file, then execute in the container:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

Then exit the container and execute:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

Then trigger the error in the frontend, and you'll see the corresponding error in the real-time loaded logs.

Docker Containers Not Auto-Restarting After Controller Reboot

If Docker containers don't automatically restart after system reboot, execute:

bash
docker start $(docker ps -a -q)

5. Drawbacks

System images are hard-coded; you can't use your own custom images, nor export them for use.

This is not the same project as https://github.com/retspen/webvirtcloud, don't confuse them.

Acknowledgements

https://webvirt.cloud/

`,101),p=[t];function r(c,i,C,y,d,A){return a(),n("div",null,p)}const u=s(e,[["render",r]]);export{D as __pageData,u as default}; diff --git a/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.js b/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.js deleted file mode 100644 index 2c2a9ba327..0000000000 --- a/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.js +++ /dev/null @@ -1,5 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const o="/assets/vcr1.30d933ab.jpg",n="/assets/vcr2.9b30a319.jpg",r="/assets/vcr3.0aa5a564.jpg",l="/assets/vcr4.18a1487e.jpg",i="/assets/vcr5.97deb479.jpg",c="/assets/vcr6.e706123b.jpg",p="/assets/vcr7.43c60335.jpg",d="/assets/vcr8.1bf1f353.jpg",m="/assets/vcr9.b5afa4b4.jpg",h="/assets/vcr10.548c566e.jpg",u="/assets/vcr11.58ce8ace.jpg",g="/assets/vcr12.3aa69b2a.jpg",v="/assets/vcr13.fcbcc557.jpg",b="/assets/vcr14.7009c833.jpg",q=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud_retspen.md","filePath":"en/incomplete/webvirtcloud_retspen.md","lastUpdated":1747972048000}'),y={name:"en/incomplete/webvirtcloud_retspen.md"},_=a(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository::https://github.com/retspen/webvirtcloud

Controller Node and Computer Node Installation

  • Supported Systems: Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • Recommended system: Debian12+, Ubuntu22.04+.
  • Lower versions of the system will automatically compile the new version of python installation package before deployment, so it is recommended to use a new system without compiling directly installed!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

After installation is complete, open the public IP address to access the login page.

The default login username and password are both admin. Make sure to change them after logging in.

Creating a Linux Virtual Machine

After entering the control panel and changing the admin password, you need to manually configure a compute node.

vcr1

Select the type as Local, and name it local.

vcr2

After creation, click the eye icon to enter the view.

vcr3

Under the Storage section, add a storage entry. Choose the type Dir and name it local. If you need to use an ISO for system boot, you’ll need to create a storage of type ISO. If not, just follow this guide and create only the Dir type.

vcr4

vcr5

After creation, download the appropriate qcow2 image for the system using the repository below:

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

In the example, a Debian 12 qcow2 image is used:

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

Return to the instance page to create a new instance.

vcr6

Select local as the compute node.

vcr7

The default chipset is fine; changing it is optional.

vcr8

You can use predefined sizes for the virtual machine or customize it, depending on your preference.

vcr9

Note: the instance name must not duplicate the system name. For example, you cannot use debian12 as the instance name in this case.

vcr10

After successful creation, do not power it on immediately.

vcr11

You need to modify the disk settings first.

vcr12

Change the disk file to debian12.qcow2, which matches the qcow2 image you previously downloaded.

vcr13

Once confirmed and configured correctly, return to the power page and turn on the VM.

vcr14

The default login for the image is:

  • Username: root
  • Password: password or oneclickvirt

Disadvantages

Networking is not auto-configured — not as smart as the previous project — you still need to configure it manually.

',45),C=[_];function f(w,A,D,k,F,j){return t(),s("div",null,C)}const B=e(y,[["render",f]]);export{q as __pageData,B as default}; diff --git a/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.lean.js b/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.lean.js deleted file mode 100644 index 2c2a9ba327..0000000000 --- a/assets/en_incomplete_webvirtcloud_retspen.md.8ec2f567.lean.js +++ /dev/null @@ -1,5 +0,0 @@ -import{_ as e,v as t,b as s,R as a}from"./chunks/framework.70afa331.js";const o="/assets/vcr1.30d933ab.jpg",n="/assets/vcr2.9b30a319.jpg",r="/assets/vcr3.0aa5a564.jpg",l="/assets/vcr4.18a1487e.jpg",i="/assets/vcr5.97deb479.jpg",c="/assets/vcr6.e706123b.jpg",p="/assets/vcr7.43c60335.jpg",d="/assets/vcr8.1bf1f353.jpg",m="/assets/vcr9.b5afa4b4.jpg",h="/assets/vcr10.548c566e.jpg",u="/assets/vcr11.58ce8ace.jpg",g="/assets/vcr12.3aa69b2a.jpg",v="/assets/vcr13.fcbcc557.jpg",b="/assets/vcr14.7009c833.jpg",q=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud_retspen.md","filePath":"en/incomplete/webvirtcloud_retspen.md","lastUpdated":1747972048000}'),y={name:"en/incomplete/webvirtcloud_retspen.md"},_=a(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository::https://github.com/retspen/webvirtcloud

Controller Node and Computer Node Installation

  • Supported Systems: Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • Recommended system: Debian12+, Ubuntu22.04+.
  • Lower versions of the system will automatically compile the new version of python installation package before deployment, so it is recommended to use a new system without compiling directly installed!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

After installation is complete, open the public IP address to access the login page.

The default login username and password are both admin. Make sure to change them after logging in.

Creating a Linux Virtual Machine

After entering the control panel and changing the admin password, you need to manually configure a compute node.

vcr1

Select the type as Local, and name it local.

vcr2

After creation, click the eye icon to enter the view.

vcr3

Under the Storage section, add a storage entry. Choose the type Dir and name it local. If you need to use an ISO for system boot, you’ll need to create a storage of type ISO. If not, just follow this guide and create only the Dir type.

vcr4

vcr5

After creation, download the appropriate qcow2 image for the system using the repository below:

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

In the example, a Debian 12 qcow2 image is used:

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

Return to the instance page to create a new instance.

vcr6

Select local as the compute node.

vcr7

The default chipset is fine; changing it is optional.

vcr8

You can use predefined sizes for the virtual machine or customize it, depending on your preference.

vcr9

Note: the instance name must not duplicate the system name. For example, you cannot use debian12 as the instance name in this case.

vcr10

After successful creation, do not power it on immediately.

vcr11

You need to modify the disk settings first.

vcr12

Change the disk file to debian12.qcow2, which matches the qcow2 image you previously downloaded.

vcr13

Once confirmed and configured correctly, return to the power page and turn on the VM.

vcr14

The default login for the image is:

  • Username: root
  • Password: password or oneclickvirt

Disadvantages

Networking is not auto-configured — not as smart as the previous project — you still need to configure it manually.

',45),C=[_];function f(w,A,D,k,F,j){return t(),s("div",null,C)}const B=e(y,[["render",f]]);export{q as __pageData,B as default}; diff --git a/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.js b/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.js new file mode 100644 index 0000000000..a2d2c8e49b --- /dev/null +++ b/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.js @@ -0,0 +1,5 @@ +import{_ as t,c as s,o as i,ag as a}from"./chunks/framework.CSeR4K32.js";const n="/assets/vcr1.NRLOOynQ.jpg",o="/assets/vcr2.DC9j-Ib5.jpg",r="/assets/vcr3.Ea5Km6nQ.jpg",l="/assets/vcr4.B9DOiqQ8.jpg",p="/assets/vcr5.BajXu8XE.jpg",c="/assets/vcr6.CxN-b1o3.jpg",d="/assets/vcr7.D4aYKhIW.jpg",h="/assets/vcr8.ByRFpMlF.jpg",g="/assets/vcr9.B4apCqgi.jpg",m="/assets/vcr10.D8t6cQ5v.jpg",u="/assets/vcr11.Cz1VMbIx.jpg",k="/assets/vcr12.BNQe5j_u.jpg",v="/assets/vcr13.JV3PfcCZ.jpg",_="/assets/vcr14.Cjyr65Qp.jpg",x=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud_retspen.md","filePath":"en/incomplete/webvirtcloud_retspen.md","lastUpdated":1747984962000}'),b={name:"en/incomplete/webvirtcloud_retspen.md"};function y(f,e,F,C,w,B){return i(),s("div",null,e[0]||(e[0]=[a(`

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository::https://github.com/retspen/webvirtcloud

Controller Node and Computer Node Installation

  • Supported Systems: Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • Recommended system: Debian12+, Ubuntu22.04+.
  • Lower versions of the system will automatically compile the new version of python installation package before deployment, so it is recommended to use a new system without compiling directly installed!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
+&& chmod +x install_webvirt_cloud_retspen.sh \\
+&& bash install_webvirt_cloud_retspen.sh

After installation is complete, open the public IP address to access the login page.

The default login username and password are both admin. Make sure to change them after logging in.

Creating a Linux Virtual Machine

After entering the control panel and changing the admin password, you need to manually configure a compute node.

vcr1

Select the type as Local, and name it local.

vcr2

After creation, click the eye icon to enter the view.

vcr3

Under the Storage section, add a storage entry. Choose the type Dir and name it local. If you need to use an ISO for system boot, you’ll need to create a storage of type ISO. If not, just follow this guide and create only the Dir type.

vcr4

vcr5

After creation, download the appropriate qcow2 image for the system using the repository below:

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

In the example, a Debian 12 qcow2 image is used:

shell
cd /var/lib/libvirt/images
+wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
+chmod 777 debian12.qcow2

Return to the instance page to create a new instance.

vcr6

Select local as the compute node.

vcr7

The default chipset is fine; changing it is optional.

vcr8

You can use predefined sizes for the virtual machine or customize it, depending on your preference.

vcr9

Note: the instance name must not duplicate the system name. For example, you cannot use debian12 as the instance name in this case.

vcr10

After successful creation, do not power it on immediately.

vcr11

You need to modify the disk settings first.

vcr12

Change the disk file to debian12.qcow2, which matches the qcow2 image you previously downloaded.

vcr13

Once confirmed and configured correctly, return to the power page and turn on the VM.

vcr14

The default login for the image is:

  • Username: root
  • Password: password or oneclickvirt

Disadvantages

Networking is not auto-configured — not as smart as the previous project — you still need to configure it manually.

',45)]))}const E=t(b,[["render",y]]);export{x as __pageData,E as default}; diff --git a/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.lean.js b/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.lean.js new file mode 100644 index 0000000000..03098c035a --- /dev/null +++ b/assets/en_incomplete_webvirtcloud_retspen.md.CjZPDsE1.lean.js @@ -0,0 +1 @@ +import{_ as t,c as s,o as i,ag as a}from"./chunks/framework.CSeR4K32.js";const n="/assets/vcr1.NRLOOynQ.jpg",o="/assets/vcr2.DC9j-Ib5.jpg",r="/assets/vcr3.Ea5Km6nQ.jpg",l="/assets/vcr4.B9DOiqQ8.jpg",p="/assets/vcr5.BajXu8XE.jpg",c="/assets/vcr6.CxN-b1o3.jpg",d="/assets/vcr7.D4aYKhIW.jpg",h="/assets/vcr8.ByRFpMlF.jpg",g="/assets/vcr9.B4apCqgi.jpg",m="/assets/vcr10.D8t6cQ5v.jpg",u="/assets/vcr11.Cz1VMbIx.jpg",k="/assets/vcr12.BNQe5j_u.jpg",v="/assets/vcr13.JV3PfcCZ.jpg",_="/assets/vcr14.Cjyr65Qp.jpg",x=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtcloud_retspen.md","filePath":"en/incomplete/webvirtcloud_retspen.md","lastUpdated":1747984962000}'),b={name:"en/incomplete/webvirtcloud_retspen.md"};function y(f,e,F,C,w,B){return i(),s("div",null,e[0]||(e[0]=[a("",45)]))}const E=t(b,[["render",y]]);export{x as __pageData,E as default}; diff --git a/assets/en_incomplete_webvirtmgr.md.611aa9ab.js b/assets/en_incomplete_webvirtmgr.md.611aa9ab.js deleted file mode 100644 index 2de1f3799b..0000000000 --- a/assets/en_incomplete_webvirtmgr.md.611aa9ab.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as t,v as e,b as a,R as s}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtmgr.md","filePath":"en/incomplete/webvirtmgr.md","lastUpdated":1747972048000}'),n={name:"en/incomplete/webvirtmgr.md"},l=s(`

WebVirtMgr Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository: https://github.com/retspen/webvirtmgr

Control nodes and compute nodes installed at the same time

  • Supported systems: Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • The system will automatically compile python 2.7 installer and then deployed, there will be an error in the compilation process but do not pay attention to it, as long as the scripts are still running, it means that everything is fine!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

Disadvantages

The origin project is no longer maintained and is not recommended at all.

`,9),o=[l];function r(i,p,c,d,h,m){return e(),a("div",null,o)}const u=t(n,[["render",r]]);export{g as __pageData,u as default}; diff --git a/assets/en_incomplete_webvirtmgr.md.611aa9ab.lean.js b/assets/en_incomplete_webvirtmgr.md.611aa9ab.lean.js deleted file mode 100644 index 2de1f3799b..0000000000 --- a/assets/en_incomplete_webvirtmgr.md.611aa9ab.lean.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as t,v as e,b as a,R as s}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtmgr.md","filePath":"en/incomplete/webvirtmgr.md","lastUpdated":1747972048000}'),n={name:"en/incomplete/webvirtmgr.md"},l=s(`

WebVirtMgr Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository: https://github.com/retspen/webvirtmgr

Control nodes and compute nodes installed at the same time

  • Supported systems: Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • The system will automatically compile python 2.7 installer and then deployed, there will be an error in the compilation process but do not pay attention to it, as long as the scripts are still running, it means that everything is fine!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

Disadvantages

The origin project is no longer maintained and is not recommended at all.

`,9),o=[l];function r(i,p,c,d,h,m){return e(),a("div",null,o)}const u=t(n,[["render",r]]);export{g as __pageData,u as default}; diff --git a/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.js b/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.js new file mode 100644 index 0000000000..368e946daa --- /dev/null +++ b/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.js @@ -0,0 +1,3 @@ +import{_ as i,c as e,o as a,ag as s}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtmgr.md","filePath":"en/incomplete/webvirtmgr.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/webvirtmgr.md"};function l(r,t,o,h,p,d){return a(),e("div",null,t[0]||(t[0]=[s(`

WebVirtMgr Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository: https://github.com/retspen/webvirtmgr

Control nodes and compute nodes installed at the same time

  • Supported systems: Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • The system will automatically compile python 2.7 installer and then deployed, there will be an error in the compilation process but do not pay attention to it, as long as the scripts are still running, it means that everything is fine!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
+&& chmod +x install_webvirtmgr.sh \\
+&& bash install_webvirtmgr.sh

Disadvantages

The origin project is no longer maintained and is not recommended at all.

`,9)]))}const g=i(n,[["render",l]]);export{m as __pageData,g as default}; diff --git a/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.lean.js b/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.lean.js new file mode 100644 index 0000000000..3ad27a5d91 --- /dev/null +++ b/assets/en_incomplete_webvirtmgr.md.8Ub32E-h.lean.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as a,ag as s}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"en/incomplete/webvirtmgr.md","filePath":"en/incomplete/webvirtmgr.md","lastUpdated":1747984962000}'),n={name:"en/incomplete/webvirtmgr.md"};function l(r,t,o,h,p,d){return a(),e("div",null,t[0]||(t[0]=[s("",9)]))}const g=i(n,[["render",l]]);export{m as __pageData,g as default}; diff --git a/assets/en_index.md.83e2fa26.js b/assets/en_index.md.DhJzLyfV.js similarity index 91% rename from assets/en_index.md.83e2fa26.js rename to assets/en_index.md.DhJzLyfV.js index 5fceae024e..60d2bdfce5 100644 --- a/assets/en_index.md.83e2fa26.js +++ b/assets/en_index.md.DhJzLyfV.js @@ -1 +1 @@ -import{_ as t,v as e,b as a}from"./chunks/framework.70afa331.js";const m=JSON.parse(`{"title":"K'thun","titleTemplate":"One Click Virtualization","description":"","frontmatter":{"layout":"home","title":"K'thun","titleTemplate":"One Click Virtualization","tagline":"Open source, easy to use server virtualization project","hero":{"name":"One Click Virtualization","text":"Open source, easy to use server virtualization project","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Learn More →","link":"/en/guide/dashboard"}]},"features":[{"title":"One Click Use","details":"Supports one-click command installation and use, easy to create virtual machines or containers on X86_64 and ARM architecture servers"},{"title":"Based on mainstream systems development","details":"Based on long-term maintenance releases of Debian, Ubuntu, Centos, etc., there is always a way to virtualize containers or virtual machines, no matter what the system is."},{"title":"Port forwarding and IP assignment automation","details":"Self-contained internal and external port forwarding and automatic IP address allocation (including IPV6、IPV4), including TCP, UDP, VNC, RDP and other protocols, without manual management"},{"title":"Batch Virtualization","details":"Supports batch opening of containers or virtual machines using KVM, LXC, Docker virtualization"},{"title":"Multi-system and multi-environment support","details":"Open containers or virtual machines that support mainstream systems, including Linux, Windows, MacOS, Android as well as pure browser or desktop environments."},{"title":"Self-limiting abuse","details":"Some virtualized containers or VMs support the setting of masks and loading limits to avoid being used for abuse."},{"title":"FAQ","details":"All questions and problems that may arise during the program are answered."},{"title":"Development thanks","details":"Thanks to Evolution Host for supporting us with a DDoS protected VPS"}]},"headers":[],"relativePath":"en/index.md","filePath":"en/index.md","lastUpdated":1747972048000}`),n={name:"en/index.md"};function i(s,o,r,l,d,u){return e(),a("div")}const p=t(n,[["render",i]]);export{m as __pageData,p as default}; +import{_ as t,c as e,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse(`{"title":"K'thun","titleTemplate":"One Click Virtualization","description":"","frontmatter":{"layout":"home","title":"K'thun","titleTemplate":"One Click Virtualization","tagline":"Open source, easy to use server virtualization project","hero":{"name":"One Click Virtualization","text":"Open source, easy to use server virtualization project","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Learn More →","link":"/en/guide/dashboard"}]},"features":[{"title":"One Click Use","details":"Supports one-click command installation and use, easy to create virtual machines or containers on X86_64 and ARM architecture servers"},{"title":"Based on mainstream systems development","details":"Based on long-term maintenance releases of Debian, Ubuntu, Centos, etc., there is always a way to virtualize containers or virtual machines, no matter what the system is."},{"title":"Port forwarding and IP assignment automation","details":"Self-contained internal and external port forwarding and automatic IP address allocation (including IPV6、IPV4), including TCP, UDP, VNC, RDP and other protocols, without manual management"},{"title":"Batch Virtualization","details":"Supports batch opening of containers or virtual machines using KVM, LXC, Docker virtualization"},{"title":"Multi-system and multi-environment support","details":"Open containers or virtual machines that support mainstream systems, including Linux, Windows, MacOS, Android as well as pure browser or desktop environments."},{"title":"Self-limiting abuse","details":"Some virtualized containers or VMs support the setting of masks and loading limits to avoid being used for abuse."},{"title":"FAQ","details":"All questions and problems that may arise during the program are answered."},{"title":"Development thanks","details":"Thanks to Evolution Host for supporting us with a DDoS protected VPS"}]},"headers":[],"relativePath":"en/index.md","filePath":"en/index.md","lastUpdated":1747984962000}`),n={name:"en/index.md"};function i(o,s,r,l,d,u){return a(),e("div")}const p=t(n,[["render",i]]);export{m as __pageData,p as default}; diff --git a/assets/en_index.md.83e2fa26.lean.js b/assets/en_index.md.DhJzLyfV.lean.js similarity index 91% rename from assets/en_index.md.83e2fa26.lean.js rename to assets/en_index.md.DhJzLyfV.lean.js index 5fceae024e..60d2bdfce5 100644 --- a/assets/en_index.md.83e2fa26.lean.js +++ b/assets/en_index.md.DhJzLyfV.lean.js @@ -1 +1 @@ -import{_ as t,v as e,b as a}from"./chunks/framework.70afa331.js";const m=JSON.parse(`{"title":"K'thun","titleTemplate":"One Click Virtualization","description":"","frontmatter":{"layout":"home","title":"K'thun","titleTemplate":"One Click Virtualization","tagline":"Open source, easy to use server virtualization project","hero":{"name":"One Click Virtualization","text":"Open source, easy to use server virtualization project","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Learn More →","link":"/en/guide/dashboard"}]},"features":[{"title":"One Click Use","details":"Supports one-click command installation and use, easy to create virtual machines or containers on X86_64 and ARM architecture servers"},{"title":"Based on mainstream systems development","details":"Based on long-term maintenance releases of Debian, Ubuntu, Centos, etc., there is always a way to virtualize containers or virtual machines, no matter what the system is."},{"title":"Port forwarding and IP assignment automation","details":"Self-contained internal and external port forwarding and automatic IP address allocation (including IPV6、IPV4), including TCP, UDP, VNC, RDP and other protocols, without manual management"},{"title":"Batch Virtualization","details":"Supports batch opening of containers or virtual machines using KVM, LXC, Docker virtualization"},{"title":"Multi-system and multi-environment support","details":"Open containers or virtual machines that support mainstream systems, including Linux, Windows, MacOS, Android as well as pure browser or desktop environments."},{"title":"Self-limiting abuse","details":"Some virtualized containers or VMs support the setting of masks and loading limits to avoid being used for abuse."},{"title":"FAQ","details":"All questions and problems that may arise during the program are answered."},{"title":"Development thanks","details":"Thanks to Evolution Host for supporting us with a DDoS protected VPS"}]},"headers":[],"relativePath":"en/index.md","filePath":"en/index.md","lastUpdated":1747972048000}`),n={name:"en/index.md"};function i(s,o,r,l,d,u){return e(),a("div")}const p=t(n,[["render",i]]);export{m as __pageData,p as default}; +import{_ as t,c as e,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse(`{"title":"K'thun","titleTemplate":"One Click Virtualization","description":"","frontmatter":{"layout":"home","title":"K'thun","titleTemplate":"One Click Virtualization","tagline":"Open source, easy to use server virtualization project","hero":{"name":"One Click Virtualization","text":"Open source, easy to use server virtualization project","image":"https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"Learn More →","link":"/en/guide/dashboard"}]},"features":[{"title":"One Click Use","details":"Supports one-click command installation and use, easy to create virtual machines or containers on X86_64 and ARM architecture servers"},{"title":"Based on mainstream systems development","details":"Based on long-term maintenance releases of Debian, Ubuntu, Centos, etc., there is always a way to virtualize containers or virtual machines, no matter what the system is."},{"title":"Port forwarding and IP assignment automation","details":"Self-contained internal and external port forwarding and automatic IP address allocation (including IPV6、IPV4), including TCP, UDP, VNC, RDP and other protocols, without manual management"},{"title":"Batch Virtualization","details":"Supports batch opening of containers or virtual machines using KVM, LXC, Docker virtualization"},{"title":"Multi-system and multi-environment support","details":"Open containers or virtual machines that support mainstream systems, including Linux, Windows, MacOS, Android as well as pure browser or desktop environments."},{"title":"Self-limiting abuse","details":"Some virtualized containers or VMs support the setting of masks and loading limits to avoid being used for abuse."},{"title":"FAQ","details":"All questions and problems that may arise during the program are answered."},{"title":"Development thanks","details":"Thanks to Evolution Host for supporting us with a DDoS protected VPS"}]},"headers":[],"relativePath":"en/index.md","filePath":"en/index.md","lastUpdated":1747984962000}`),n={name:"en/index.md"};function i(o,s,r,l,d,u){return a(),e("div")}const p=t(n,[["render",i]]);export{m as __pageData,p as default}; diff --git a/assets/finish.0c3eac87.png b/assets/finish.Cf6DgPp1.png similarity index 100% rename from assets/finish.0c3eac87.png rename to assets/finish.Cf6DgPp1.png diff --git a/assets/general.ea03923c.png b/assets/general.BkOp2iK4.png similarity index 100% rename from assets/general.ea03923c.png rename to assets/general.BkOp2iK4.png diff --git a/assets/gic1.42bfd260.png b/assets/gic1.XkdPXihx.png similarity index 100% rename from assets/gic1.42bfd260.png rename to assets/gic1.XkdPXihx.png diff --git a/assets/gic2.ff78c941.png b/assets/gic2.s5VB7-xp.png similarity index 100% rename from assets/gic2.ff78c941.png rename to assets/gic2.s5VB7-xp.png diff --git a/assets/gic3.4a04cf3d.png b/assets/gic3.2zLznATL.png similarity index 100% rename from assets/gic3.4a04cf3d.png rename to assets/gic3.2zLznATL.png diff --git a/assets/gic4.e2343160.png b/assets/gic4.CX3t8C19.png similarity index 100% rename from assets/gic4.e2343160.png rename to assets/gic4.CX3t8C19.png diff --git a/assets/gic5.54522dff.png b/assets/gic5.pjwHWuhn.png similarity index 100% rename from assets/gic5.54522dff.png rename to assets/gic5.pjwHWuhn.png diff --git a/assets/gic6.97561122.png b/assets/gic6.BnmyenL0.png similarity index 100% rename from assets/gic6.97561122.png rename to assets/gic6.BnmyenL0.png diff --git a/assets/gic7.a8679083.png b/assets/gic7.ZYHWzF5W.png similarity index 100% rename from assets/gic7.a8679083.png rename to assets/gic7.ZYHWzF5W.png diff --git a/assets/gic8.fe7d0b3c.png b/assets/gic8.BwCbmRgC.png similarity index 100% rename from assets/gic8.fe7d0b3c.png rename to assets/gic8.BwCbmRgC.png diff --git a/assets/gic9.4cdf4daa.png b/assets/gic9.62-9wTBo.png similarity index 100% rename from assets/gic9.4cdf4daa.png rename to assets/gic9.62-9wTBo.png diff --git a/assets/guide_block_block_docker.md.5830a230.js b/assets/guide_block_block_docker.md.5830a230.js deleted file mode 100644 index bafa42cc45..0000000000 --- a/assets/guide_block_block_docker.md.5830a230.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as t,b as o,F as e,L as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"待开发,敬请期待","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_docker.md","filePath":"guide/block/block_docker.md","lastUpdated":1747972048000}'),c={name:"guide/block/block_docker.md"},r=e("h1",{id:"待开发-敬请期待",tabindex:"-1"},[s("待开发,敬请期待 "),e("a",{class:"header-anchor",href:"#待开发-敬请期待","aria-label":'Permalink to "待开发,敬请期待"'},"​")],-1),d=[r];function i(n,l,_,k,p,b){return t(),o("div",null,d)}const m=a(c,[["render",i]]);export{f as __pageData,m as default}; diff --git a/assets/guide_block_block_docker.md.5830a230.lean.js b/assets/guide_block_block_docker.md.5830a230.lean.js deleted file mode 100644 index bafa42cc45..0000000000 --- a/assets/guide_block_block_docker.md.5830a230.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as t,b as o,F as e,L as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"待开发,敬请期待","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_docker.md","filePath":"guide/block/block_docker.md","lastUpdated":1747972048000}'),c={name:"guide/block/block_docker.md"},r=e("h1",{id:"待开发-敬请期待",tabindex:"-1"},[s("待开发,敬请期待 "),e("a",{class:"header-anchor",href:"#待开发-敬请期待","aria-label":'Permalink to "待开发,敬请期待"'},"​")],-1),d=[r];function i(n,l,_,k,p,b){return t(),o("div",null,d)}const m=a(c,[["render",i]]);export{f as __pageData,m as default}; diff --git a/assets/guide_block_block_docker.md.C-tufkRV.js b/assets/guide_block_block_docker.md.C-tufkRV.js new file mode 100644 index 0000000000..42edbf9dfd --- /dev/null +++ b/assets/guide_block_block_docker.md.C-tufkRV.js @@ -0,0 +1 @@ +import{_ as o,c as t,o as r,j as a,a as c}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"待开发,敬请期待","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_docker.md","filePath":"guide/block/block_docker.md","lastUpdated":1747984962000}'),d={name:"guide/block/block_docker.md"};function l(s,e,n,i,k,p){return r(),t("div",null,e[0]||(e[0]=[a("h1",{id:"待开发-敬请期待",tabindex:"-1"},[c("待开发,敬请期待 "),a("a",{class:"header-anchor",href:"#待开发-敬请期待","aria-label":'Permalink to "待开发,敬请期待"'},"​")],-1)]))}const b=o(d,[["render",l]]);export{m as __pageData,b as default}; diff --git a/assets/guide_block_block_docker.md.C-tufkRV.lean.js b/assets/guide_block_block_docker.md.C-tufkRV.lean.js new file mode 100644 index 0000000000..42edbf9dfd --- /dev/null +++ b/assets/guide_block_block_docker.md.C-tufkRV.lean.js @@ -0,0 +1 @@ +import{_ as o,c as t,o as r,j as a,a as c}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"待开发,敬请期待","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_docker.md","filePath":"guide/block/block_docker.md","lastUpdated":1747984962000}'),d={name:"guide/block/block_docker.md"};function l(s,e,n,i,k,p){return r(),t("div",null,e[0]||(e[0]=[a("h1",{id:"待开发-敬请期待",tabindex:"-1"},[c("待开发,敬请期待 "),a("a",{class:"header-anchor",href:"#待开发-敬请期待","aria-label":'Permalink to "待开发,敬请期待"'},"​")],-1)]))}const b=o(d,[["render",l]]);export{m as __pageData,b as default}; diff --git a/assets/guide_block_block_incus.md.9da06b17.js b/assets/guide_block_block_incus.md.9da06b17.js deleted file mode 100644 index e7564c76c5..0000000000 --- a/assets/guide_block_block_incus.md.9da06b17.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_incus.md","filePath":"guide/block/block_incus.md","lastUpdated":1747972048000}'),o={name:"guide/block/block_incus.md"},p=n('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/guide_block_block_incus.md.9da06b17.lean.js b/assets/guide_block_block_incus.md.9da06b17.lean.js deleted file mode 100644 index e7564c76c5..0000000000 --- a/assets/guide_block_block_incus.md.9da06b17.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_incus.md","filePath":"guide/block/block_incus.md","lastUpdated":1747972048000}'),o={name:"guide/block/block_incus.md"},p=n('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/guide_block_block_incus.md.D3fB2bDD.js b/assets/guide_block_block_incus.md.D3fB2bDD.js new file mode 100644 index 0000000000..e4f8b8d7fa --- /dev/null +++ b/assets/guide_block_block_incus.md.D3fB2bDD.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_incus.md","filePath":"guide/block/block_incus.md","lastUpdated":1747984962000}'),l={name:"guide/block/block_incus.md"};function e(n,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13)]))}const F=i(l,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_block_block_incus.md.D3fB2bDD.lean.js b/assets/guide_block_block_incus.md.D3fB2bDD.lean.js new file mode 100644 index 0000000000..752ebcfddd --- /dev/null +++ b/assets/guide_block_block_incus.md.D3fB2bDD.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_incus.md","filePath":"guide/block/block_incus.md","lastUpdated":1747984962000}'),l={name:"guide/block/block_incus.md"};function e(n,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h("",13)]))}const F=i(l,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_block_block_iptables.md.56fd36c5.js b/assets/guide_block_block_iptables.md.56fd36c5.js deleted file mode 100644 index eb5abbc00f..0000000000 --- a/assets/guide_block_block_iptables.md.56fd36c5.js +++ /dev/null @@ -1,54 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"通过iptables屏蔽滥用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_iptables.md","filePath":"guide/block/block_iptables.md","lastUpdated":1747972048000}'),o={name:"guide/block/block_iptables.md"},p=l(`

通过iptables屏蔽滥用

iptables的基础使用说明

1. 启动 iptables

在大多数 Linux 发行版中,iptables 服务可以通过以下命令启动:

bash
sudo systemctl start iptables

2. 设置规则

在启动 iptables 后,可以设置相应的规则来屏蔽滥用流量。例如,以下命令将阻止来自特定IPV4地址的流量:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. 查询规则

设置完规则后,可以使用以下命令查看当前的 iptables 规则:

bash
sudo iptables -L

这将列出所有输入、输出和转发的规则。

4. 停止 iptables

如果需要停止 iptables 服务,可以使用以下命令:

bash
sudo systemctl stop iptables

5. 保存规则

为了确保在重启后规则依然生效,可以保存当前的规则:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. 恢复规则

在需要恢复规则时,可以使用以下命令:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. 其他常用命令

  • 列出规则(详细信息)

    bash
    sudo iptables -L -v
  • 删除特定规则

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • 清空所有规则

    bash
    sudo iptables -F

在宿主机上屏蔽滥用行为

屏蔽挖矿行为

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽BT行为

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽测速行为

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
`,30),e=[p];function t(c,r,i,C,u,A){return a(),n("div",null,e)}const D=s(o,[["render",t]]);export{y as __pageData,D as default}; diff --git a/assets/guide_block_block_iptables.md.56fd36c5.lean.js b/assets/guide_block_block_iptables.md.56fd36c5.lean.js deleted file mode 100644 index eb5abbc00f..0000000000 --- a/assets/guide_block_block_iptables.md.56fd36c5.lean.js +++ /dev/null @@ -1,54 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"通过iptables屏蔽滥用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_iptables.md","filePath":"guide/block/block_iptables.md","lastUpdated":1747972048000}'),o={name:"guide/block/block_iptables.md"},p=l(`

通过iptables屏蔽滥用

iptables的基础使用说明

1. 启动 iptables

在大多数 Linux 发行版中,iptables 服务可以通过以下命令启动:

bash
sudo systemctl start iptables

2. 设置规则

在启动 iptables 后,可以设置相应的规则来屏蔽滥用流量。例如,以下命令将阻止来自特定IPV4地址的流量:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. 查询规则

设置完规则后,可以使用以下命令查看当前的 iptables 规则:

bash
sudo iptables -L

这将列出所有输入、输出和转发的规则。

4. 停止 iptables

如果需要停止 iptables 服务,可以使用以下命令:

bash
sudo systemctl stop iptables

5. 保存规则

为了确保在重启后规则依然生效,可以保存当前的规则:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. 恢复规则

在需要恢复规则时,可以使用以下命令:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. 其他常用命令

  • 列出规则(详细信息)

    bash
    sudo iptables -L -v
  • 删除特定规则

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • 清空所有规则

    bash
    sudo iptables -F

在宿主机上屏蔽滥用行为

屏蔽挖矿行为

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽BT行为

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽测速行为

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "\${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
`,30),e=[p];function t(c,r,i,C,u,A){return a(),n("div",null,e)}const D=s(o,[["render",t]]);export{y as __pageData,D as default}; diff --git a/assets/guide_block_block_iptables.md.DkS3brgv.js b/assets/guide_block_block_iptables.md.DkS3brgv.js new file mode 100644 index 0000000000..3b31f6923f --- /dev/null +++ b/assets/guide_block_block_iptables.md.DkS3brgv.js @@ -0,0 +1,54 @@ +import{_ as a,c as n,o as i,ag as p}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"通过iptables屏蔽滥用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_iptables.md","filePath":"guide/block/block_iptables.md","lastUpdated":1747984962000}'),t={name:"guide/block/block_iptables.md"};function e(l,s,o,h,d,c){return i(),n("div",null,s[0]||(s[0]=[p(`

通过iptables屏蔽滥用

iptables的基础使用说明

1. 启动 iptables

在大多数 Linux 发行版中,iptables 服务可以通过以下命令启动:

bash
sudo systemctl start iptables

2. 设置规则

在启动 iptables 后,可以设置相应的规则来屏蔽滥用流量。例如,以下命令将阻止来自特定IPV4地址的流量:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. 查询规则

设置完规则后,可以使用以下命令查看当前的 iptables 规则:

bash
sudo iptables -L

这将列出所有输入、输出和转发的规则。

4. 停止 iptables

如果需要停止 iptables 服务,可以使用以下命令:

bash
sudo systemctl stop iptables

5. 保存规则

为了确保在重启后规则依然生效,可以保存当前的规则:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. 恢复规则

在需要恢复规则时,可以使用以下命令:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. 其他常用命令

  • 列出规则(详细信息)

    bash
    sudo iptables -L -v
  • 删除特定规则

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • 清空所有规则

    bash
    sudo iptables -F

在宿主机上屏蔽滥用行为

屏蔽挖矿行为

strings=(
+    "ethermine.com"
+    "antpool.one"
+    "antpool.com"
+    "pool.bar"
+    "get_peers"
+    "announce_peer"
+    "find_node"
+    "seed_hash"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

屏蔽BT行为

strings=(
+    "torrent"
+    ".torrent"
+    "peer_id="
+    "announce"
+    "info_hash"
+    "get_peers"
+    "find_node"
+    "BitTorrent"
+    "announce_peer"
+    "BitTorrent protocol"
+    "announce.php?passkey="
+    "magnet:"
+    "xunlei"
+    "sandai"
+    "Thunder"
+    "XLLiveUD"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

屏蔽测速行为

strings=(
+    ".speed"
+    "speed."
+    ".speed."
+    "fast.com"
+    "speedtest.net"
+    "speedtest.com"
+    "speedtest.cn"
+    "test.ustc.edu.cn"
+    "10000.gd.cn"
+    "db.laomoe.com"
+    "jiyou.cloud"
+    "ovo.speedtestcustom.com"
+    "speed.cloudflare.com"
+    "speedtest"
+)
+
+for str in "\${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done
`,30)]))}const k=a(t,[["render",e]]);export{u as __pageData,k as default}; diff --git a/assets/guide_block_block_iptables.md.DkS3brgv.lean.js b/assets/guide_block_block_iptables.md.DkS3brgv.lean.js new file mode 100644 index 0000000000..681c819ed1 --- /dev/null +++ b/assets/guide_block_block_iptables.md.DkS3brgv.lean.js @@ -0,0 +1 @@ +import{_ as a,c as n,o as i,ag as p}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"通过iptables屏蔽滥用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_iptables.md","filePath":"guide/block/block_iptables.md","lastUpdated":1747984962000}'),t={name:"guide/block/block_iptables.md"};function e(l,s,o,h,d,c){return i(),n("div",null,s[0]||(s[0]=[p("",30)]))}const k=a(t,[["render",e]]);export{u as __pageData,k as default}; diff --git a/assets/guide_block_block_lxd.md.BrbV-k4o.js b/assets/guide_block_block_lxd.md.BrbV-k4o.js new file mode 100644 index 0000000000..e6399e588c --- /dev/null +++ b/assets/guide_block_block_lxd.md.BrbV-k4o.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as l,ag as t}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_lxd.md","filePath":"guide/block/block_lxd.md","lastUpdated":1747984962000}'),h={name:"guide/block/block_lxd.md"};function e(n,s,p,k,r,d){return l(),a("div",null,s[0]||(s[0]=[t('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13)]))}const F=i(h,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_block_block_lxd.md.BrbV-k4o.lean.js b/assets/guide_block_block_lxd.md.BrbV-k4o.lean.js new file mode 100644 index 0000000000..9e4661b0ed --- /dev/null +++ b/assets/guide_block_block_lxd.md.BrbV-k4o.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as l,ag as t}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_lxd.md","filePath":"guide/block/block_lxd.md","lastUpdated":1747984962000}'),h={name:"guide/block/block_lxd.md"};function e(n,s,p,k,r,d){return l(),a("div",null,s[0]||(s[0]=[t("",13)]))}const F=i(h,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_block_block_lxd.md.cf1b102e.js b/assets/guide_block_block_lxd.md.cf1b102e.js deleted file mode 100644 index 7c47efe8cd..0000000000 --- a/assets/guide_block_block_lxd.md.cf1b102e.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as l,b as a,R as o}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_lxd.md","filePath":"guide/block/block_lxd.md","lastUpdated":1747972048000}'),n={name:"guide/block/block_lxd.md"},p=o('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13),e=[p];function t(c,r,C,i,y,D){return l(),a("div",null,e)}const d=s(n,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/guide_block_block_lxd.md.cf1b102e.lean.js b/assets/guide_block_block_lxd.md.cf1b102e.lean.js deleted file mode 100644 index 7c47efe8cd..0000000000 --- a/assets/guide_block_block_lxd.md.cf1b102e.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as l,b as a,R as o}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"通过shell脚本屏蔽滥用行为","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_lxd.md","filePath":"guide/block/block_lxd.md","lastUpdated":1747972048000}'),n={name:"guide/block/block_lxd.md"},p=o('

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
',13),e=[p];function t(c,r,C,i,y,D){return l(),a("div",null,e)}const d=s(n,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/guide_block_block_pve.md.0b046fe8.js b/assets/guide_block_block_pve.md.0b046fe8.js deleted file mode 100644 index 8c2abd908e..0000000000 --- a/assets/guide_block_block_pve.md.0b046fe8.js +++ /dev/null @@ -1,4 +0,0 @@ -import{_ as s,v as e,b as a,R as t}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"通过设置防火墙限制虚拟机使用的IP避免盗用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_pve.md","filePath":"guide/block/block_pve.md","lastUpdated":1747972048000}'),l={name:"guide/block/block_pve.md"},o=t(`

通过设置防火墙限制虚拟机使用的IP避免盗用

在PVE的宿主机下创建以下文件

shell
/etc/pve/firewall/<VMID>.fw
-
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID>替换为虚拟机的VMID数字,<net0>替换为网络设备中对应的别名(一般不用修改,除非你限制的IPV6),xxx.xxx.xxx.xxx替换为公网IP地址,注意此IP对应前面的网络设备。

这里的意思是net0只能使用xxx.xxx.xxx.xxx这个IP,如果使用其他的IP数据将会被丢弃,从而达到限制虚拟机只能使用此IP的目的。

这里可以有多个IP,一旦启用此规则该VM就无法使用除此之外的任何IP,如果你没有写IPv6地址则代表该VM无法使用IPv6地址。

TIP

本设置仅推荐在开设非NAT全端口映射的独立IP的虚拟机时使用,否则可能导致奇奇怪怪的问题造成服务器没网。

该方法不适合开设任何NAT虚拟机/容器的PVE上使用。

`,8),p=[o];function n(c,i,x,r,d,P){return e(),a("div",null,p)}const g=s(l,[["render",n]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_block_block_pve.md.0b046fe8.lean.js b/assets/guide_block_block_pve.md.0b046fe8.lean.js deleted file mode 100644 index 8c2abd908e..0000000000 --- a/assets/guide_block_block_pve.md.0b046fe8.lean.js +++ /dev/null @@ -1,4 +0,0 @@ -import{_ as s,v as e,b as a,R as t}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"通过设置防火墙限制虚拟机使用的IP避免盗用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_pve.md","filePath":"guide/block/block_pve.md","lastUpdated":1747972048000}'),l={name:"guide/block/block_pve.md"},o=t(`

通过设置防火墙限制虚拟机使用的IP避免盗用

在PVE的宿主机下创建以下文件

shell
/etc/pve/firewall/<VMID>.fw
-
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID>替换为虚拟机的VMID数字,<net0>替换为网络设备中对应的别名(一般不用修改,除非你限制的IPV6),xxx.xxx.xxx.xxx替换为公网IP地址,注意此IP对应前面的网络设备。

这里的意思是net0只能使用xxx.xxx.xxx.xxx这个IP,如果使用其他的IP数据将会被丢弃,从而达到限制虚拟机只能使用此IP的目的。

这里可以有多个IP,一旦启用此规则该VM就无法使用除此之外的任何IP,如果你没有写IPv6地址则代表该VM无法使用IPv6地址。

TIP

本设置仅推荐在开设非NAT全端口映射的独立IP的虚拟机时使用,否则可能导致奇奇怪怪的问题造成服务器没网。

该方法不适合开设任何NAT虚拟机/容器的PVE上使用。

`,8),p=[o];function n(c,i,x,r,d,P){return e(),a("div",null,p)}const g=s(l,[["render",n]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_block_block_pve.md.BntEIKAB.js b/assets/guide_block_block_pve.md.BntEIKAB.js new file mode 100644 index 0000000000..cc34393e05 --- /dev/null +++ b/assets/guide_block_block_pve.md.BntEIKAB.js @@ -0,0 +1,4 @@ +import{_ as a,c as e,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"通过设置防火墙限制虚拟机使用的IP避免盗用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_pve.md","filePath":"guide/block/block_pve.md","lastUpdated":1747984962000}'),l={name:"guide/block/block_pve.md"};function p(n,s,o,c,d,r){return t(),e("div",null,s[0]||(s[0]=[i(`

通过设置防火墙限制虚拟机使用的IP避免盗用

在PVE的宿主机下创建以下文件

shell
/etc/pve/firewall/<VMID>.fw
+
+[IPSET ipfilter-<net0>]
+xxx.xxx.xxx.xxx

<VMID>替换为虚拟机的VMID数字,<net0>替换为网络设备中对应的别名(一般不用修改,除非你限制的IPV6),xxx.xxx.xxx.xxx替换为公网IP地址,注意此IP对应前面的网络设备。

这里的意思是net0只能使用xxx.xxx.xxx.xxx这个IP,如果使用其他的IP数据将会被丢弃,从而达到限制虚拟机只能使用此IP的目的。

这里可以有多个IP,一旦启用此规则该VM就无法使用除此之外的任何IP,如果你没有写IPv6地址则代表该VM无法使用IPv6地址。

TIP

本设置仅推荐在开设非NAT全端口映射的独立IP的虚拟机时使用,否则可能导致奇奇怪怪的问题造成服务器没网。

该方法不适合开设任何NAT虚拟机/容器的PVE上使用。

`,8)]))}const k=a(l,[["render",p]]);export{h as __pageData,k as default}; diff --git a/assets/guide_block_block_pve.md.BntEIKAB.lean.js b/assets/guide_block_block_pve.md.BntEIKAB.lean.js new file mode 100644 index 0000000000..020d990051 --- /dev/null +++ b/assets/guide_block_block_pve.md.BntEIKAB.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"通过设置防火墙限制虚拟机使用的IP避免盗用","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/block/block_pve.md","filePath":"guide/block/block_pve.md","lastUpdated":1747984962000}'),l={name:"guide/block/block_pve.md"};function p(n,s,o,c,d,r){return t(),e("div",null,s[0]||(s[0]=[i("",8)]))}const k=a(l,[["render",p]]);export{h as __pageData,k as default}; diff --git a/assets/guide_dashboard.md.7c9eeb09.js b/assets/guide_dashboard.md.7c9eeb09.js deleted file mode 100644 index 66517fe066..0000000000 --- a/assets/guide_dashboard.md.7c9eeb09.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as e,b as a,R as r}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/dashboard.md","filePath":"guide/dashboard.md","lastUpdated":1747972048000}'),i={name:"guide/dashboard.md"},l=r('

准备工作

需要虚拟化出服务器,你需要:

  1. 一台可以连接公网的服务器( VPS 或 Dedicated Server),最好能完美访问 Github 的 RAW 页面,部分项目部分组件可能未使用 CDN 加速

TIP

如果您位于中国大陆,访问 Github 有困难,请注意配套脚本和项目是否有说明已使用 CDN 加速

  1. 本地可以稳定连接SSH,如果不能稳定连接,请使用screen命令创建窗口后,在窗口内执行命令

TIP

不会用screen命令的,自行查找相关教程学习,或者用tmux替代也行

  1. 确保服务器的系统和硬件满足对应项目的要求,详见对应项目说明

本文档将以VPS作为范例,且该VPS纯净,无原生环境问题,如有必要请重装系统保证初始环境的纯净

WARNING

PVE项目可能造成宿主机出现问题,如果你不会看Bug和修复系统,那么不建议你在生产环境中使用,使用PVE相关脚本请确保宿主机随时可重装系统

项目仓库

欢迎Star和Fork,所有资源均开源,无非开源部分,转载以及使用请写上来源于本站,谢谢

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',23),s=[l];function o(c,h,p,n,d,b){return e(),a("div",null,s)}const g=t(i,[["render",o]]);export{m as __pageData,g as default}; diff --git a/assets/guide_dashboard.md.7c9eeb09.lean.js b/assets/guide_dashboard.md.7c9eeb09.lean.js deleted file mode 100644 index 66517fe066..0000000000 --- a/assets/guide_dashboard.md.7c9eeb09.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as e,b as a,R as r}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/dashboard.md","filePath":"guide/dashboard.md","lastUpdated":1747972048000}'),i={name:"guide/dashboard.md"},l=r('

准备工作

需要虚拟化出服务器,你需要:

  1. 一台可以连接公网的服务器( VPS 或 Dedicated Server),最好能完美访问 Github 的 RAW 页面,部分项目部分组件可能未使用 CDN 加速

TIP

如果您位于中国大陆,访问 Github 有困难,请注意配套脚本和项目是否有说明已使用 CDN 加速

  1. 本地可以稳定连接SSH,如果不能稳定连接,请使用screen命令创建窗口后,在窗口内执行命令

TIP

不会用screen命令的,自行查找相关教程学习,或者用tmux替代也行

  1. 确保服务器的系统和硬件满足对应项目的要求,详见对应项目说明

本文档将以VPS作为范例,且该VPS纯净,无原生环境问题,如有必要请重装系统保证初始环境的纯净

WARNING

PVE项目可能造成宿主机出现问题,如果你不会看Bug和修复系统,那么不建议你在生产环境中使用,使用PVE相关脚本请确保宿主机随时可重装系统

项目仓库

欢迎Star和Fork,所有资源均开源,无非开源部分,转载以及使用请写上来源于本站,谢谢

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',23),s=[l];function o(c,h,p,n,d,b){return e(),a("div",null,s)}const g=t(i,[["render",o]]);export{m as __pageData,g as default}; diff --git a/assets/guide_dashboard.md.D2bjCnlL.js b/assets/guide_dashboard.md.D2bjCnlL.js new file mode 100644 index 0000000000..872bf6b626 --- /dev/null +++ b/assets/guide_dashboard.md.D2bjCnlL.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,ag as i}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/dashboard.md","filePath":"guide/dashboard.md","lastUpdated":1747984962000}'),l={name:"guide/dashboard.md"};function s(o,t,c,p,h,n){return r(),a("div",null,t[0]||(t[0]=[i('

准备工作

需要虚拟化出服务器,你需要:

  1. 一台可以连接公网的服务器( VPS 或 Dedicated Server),最好能完美访问 Github 的 RAW 页面,部分项目部分组件可能未使用 CDN 加速

TIP

如果您位于中国大陆,访问 Github 有困难,请注意配套脚本和项目是否有说明已使用 CDN 加速

  1. 本地可以稳定连接SSH,如果不能稳定连接,请使用screen命令创建窗口后,在窗口内执行命令

TIP

不会用screen命令的,自行查找相关教程学习,或者用tmux替代也行

  1. 确保服务器的系统和硬件满足对应项目的要求,详见对应项目说明

本文档将以VPS作为范例,且该VPS纯净,无原生环境问题,如有必要请重装系统保证初始环境的纯净

WARNING

PVE项目可能造成宿主机出现问题,如果你不会看Bug和修复系统,那么不建议你在生产环境中使用,使用PVE相关脚本请确保宿主机随时可重装系统

项目仓库

欢迎Star和Fork,所有资源均开源,无非开源部分,转载以及使用请写上来源于本站,谢谢

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

',23)]))}const u=e(l,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/guide_dashboard.md.D2bjCnlL.lean.js b/assets/guide_dashboard.md.D2bjCnlL.lean.js new file mode 100644 index 0000000000..9dd7c3cce3 --- /dev/null +++ b/assets/guide_dashboard.md.D2bjCnlL.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r,ag as i}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/dashboard.md","filePath":"guide/dashboard.md","lastUpdated":1747984962000}'),l={name:"guide/dashboard.md"};function s(o,t,c,p,h,n){return r(),a("div",null,t[0]||(t[0]=[i("",23)]))}const u=e(l,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/guide_dashboardq.md.02164389.js b/assets/guide_dashboardq.md.02164389.js deleted file mode 100644 index 4605af8c91..0000000000 --- a/assets/guide_dashboardq.md.02164389.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as t}from"./chunks/framework.70afa331.js";const p="/assets/wechat.e3b2e06e.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/dashboardq.md","filePath":"guide/dashboardq.md","lastUpdated":1747972048000}'),o={name:"guide/dashboardq.md"},n=t('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8),c=[n];function i(l,r,d,h,b,f){return s(),e("div",null,c)}const g=a(o,[["render",i]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_dashboardq.md.02164389.lean.js b/assets/guide_dashboardq.md.02164389.lean.js deleted file mode 100644 index 4605af8c91..0000000000 --- a/assets/guide_dashboardq.md.02164389.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as t}from"./chunks/framework.70afa331.js";const p="/assets/wechat.e3b2e06e.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/dashboardq.md","filePath":"guide/dashboardq.md","lastUpdated":1747972048000}'),o={name:"guide/dashboardq.md"},n=t('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8),c=[n];function i(l,r,d,h,b,f){return s(),e("div",null,c)}const g=a(o,[["render",i]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_dashboardq.md.DGJ9X51L.js b/assets/guide_dashboardq.md.DGJ9X51L.js new file mode 100644 index 0000000000..c95f9212cf --- /dev/null +++ b/assets/guide_dashboardq.md.DGJ9X51L.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const p="/assets/wechat.BhfskdFa.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/dashboardq.md","filePath":"guide/dashboardq.md","lastUpdated":1747984962000}'),o={name:"guide/dashboardq.md"};function d(n,a,c,l,r,h){return t(),s("div",null,a[0]||(a[0]=[i('

Give me a cup of coffee.

https://ko-fi.com/spiritlhl

WeChat

WeChat

USDT-TRC20

bash
TNqjaPYAmDsm9pbpLY79pixE8z1ce3Zj1B

USDT-Polygon/Matic

bash
0xb81b44cb00f9e6e084f85e5da604ec479e7ffab6
',8)]))}const g=e(o,[["render",d]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_dashboardq.md.DGJ9X51L.lean.js b/assets/guide_dashboardq.md.DGJ9X51L.lean.js new file mode 100644 index 0000000000..ef75c2e31f --- /dev/null +++ b/assets/guide_dashboardq.md.DGJ9X51L.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const p="/assets/wechat.BhfskdFa.jpg",_=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/dashboardq.md","filePath":"guide/dashboardq.md","lastUpdated":1747984962000}'),o={name:"guide/dashboardq.md"};function d(n,a,c,l,r,h){return t(),s("div",null,a[0]||(a[0]=[i("",8)]))}const g=e(o,[["render",d]]);export{_ as __pageData,g as default}; diff --git a/assets/guide_docker_docker_android.md.DyBMNwLg.js b/assets/guide_docker_docker_android.md.DyBMNwLg.js new file mode 100644 index 0000000000..c30c7613e1 --- /dev/null +++ b/assets/guide_docker_docker_android.md.DyBMNwLg.js @@ -0,0 +1,6 @@ +import{_ as i,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"在Docker中开设Android虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_android.md","filePath":"guide/docker/docker_android.md","lastUpdated":1747984962000}'),t={name:"guide/docker/docker_android.md"};function p(r,s,l,d,o,h){return e(),a("div",null,s[0]||(s[0]=[n(`

在Docker中开设Android虚拟机

一键开设

  • 自定义安卓版本
  • 自动创建带校验的web网站
  • 自动进行nginx安装和反向代理的配置,可选择是否绑定域名,默认回车不绑定使用80端口
  • 无需考虑宿主机是否支持嵌套虚拟化
  • 支持x86_64和ARM架构

宿主机的配置至少要有1核2G内存15G硬盘,否则开设可能会导致宿主机卡死

宿主机推荐 Ubuntu 系统,Debian 系统可能导致安卓屏幕白屏

安卓版本越新占用越大,以上的配置要求是最低版本安卓的配置要求 (个人测试到 12.0.0-latest 的tag可用,更高版本映射白屏了,自己测试哪个能用吧)

如果开设后,过了5分钟浏览器网页的登录验证还是一直失败,那么请查询安卓容器的日志,大概率安卓容器崩溃了,建议更换更低的安卓系统版本的容器进行安装

开设

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

命令执行后按照提示输入即可,注意选择版本输入的是序号,对应选项的数字序号,安装完毕后打开本机IPV4+80端口可登录

如果需要查询生成的安卓信息和web登录信息,执行cat /root/android_info可查询信息

默认的用户名 onea

默认密码 oneclick

远程的桌面点击H264 Converter跳转就是了

暂时只支持生成一个安卓容器,勿要重复生成,如需替换版本请执行后续命令删除后再次开设

暂时只支持开设后一直使用,不可重启服务器,重启后可能无法自重启映射成功,自测

删除

  • 删除容器
  • 删除容器对应镜像
  • 删除配置文件
docker rm -f android
+docker rmi $(docker images | grep "redroid" | awk '{print $3}')
+rm -rf /etc/nginx/sites-enabled/reverse-proxy
+rm -rf /etc/nginx/sites-available/reverse-proxy
+rm -rf /etc/nginx/passwd_scrcpy_web
+rm -rf /root/android_info
`,22)]))}const g=i(t,[["render",p]]);export{k as __pageData,g as default}; diff --git a/assets/guide_docker_docker_android.md.DyBMNwLg.lean.js b/assets/guide_docker_docker_android.md.DyBMNwLg.lean.js new file mode 100644 index 0000000000..6083a70e1d --- /dev/null +++ b/assets/guide_docker_docker_android.md.DyBMNwLg.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as e,ag as n}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"在Docker中开设Android虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_android.md","filePath":"guide/docker/docker_android.md","lastUpdated":1747984962000}'),t={name:"guide/docker/docker_android.md"};function p(r,s,l,d,o,h){return e(),a("div",null,s[0]||(s[0]=[n("",22)]))}const g=i(t,[["render",p]]);export{k as __pageData,g as default}; diff --git a/assets/guide_docker_docker_android.md.c556d7ea.js b/assets/guide_docker_docker_android.md.c556d7ea.js deleted file mode 100644 index a358258e84..0000000000 --- a/assets/guide_docker_docker_android.md.c556d7ea.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"在Docker中开设Android虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_android.md","filePath":"guide/docker/docker_android.md","lastUpdated":1747972048000}'),e={name:"guide/docker/docker_android.md"},p=o(`

在Docker中开设Android虚拟机

一键开设

  • 自定义安卓版本
  • 自动创建带校验的web网站
  • 自动进行nginx安装和反向代理的配置,可选择是否绑定域名,默认回车不绑定使用80端口
  • 无需考虑宿主机是否支持嵌套虚拟化
  • 支持x86_64和ARM架构

宿主机的配置至少要有1核2G内存15G硬盘,否则开设可能会导致宿主机卡死

宿主机推荐 Ubuntu 系统,Debian 系统可能导致安卓屏幕白屏

安卓版本越新占用越大,以上的配置要求是最低版本安卓的配置要求 (个人测试到 12.0.0-latest 的tag可用,更高版本映射白屏了,自己测试哪个能用吧)

如果开设后,过了5分钟浏览器网页的登录验证还是一直失败,那么请查询安卓容器的日志,大概率安卓容器崩溃了,建议更换更低的安卓系统版本的容器进行安装

开设

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

命令执行后按照提示输入即可,注意选择版本输入的是序号,对应选项的数字序号,安装完毕后打开本机IPV4+80端口可登录

如果需要查询生成的安卓信息和web登录信息,执行cat /root/android_info可查询信息

默认的用户名 onea

默认密码 oneclick

远程的桌面点击H264 Converter跳转就是了

暂时只支持生成一个安卓容器,勿要重复生成,如需替换版本请执行后续命令删除后再次开设

暂时只支持开设后一直使用,不可重启服务器,重启后可能无法自重启映射成功,自测

删除

  • 删除容器
  • 删除容器对应镜像
  • 删除配置文件
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
`,22),l=[p];function r(t,c,i,d,C,y){return a(),n("div",null,l)}const h=s(e,[["render",r]]);export{D as __pageData,h as default}; diff --git a/assets/guide_docker_docker_android.md.c556d7ea.lean.js b/assets/guide_docker_docker_android.md.c556d7ea.lean.js deleted file mode 100644 index a358258e84..0000000000 --- a/assets/guide_docker_docker_android.md.c556d7ea.lean.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"在Docker中开设Android虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_android.md","filePath":"guide/docker/docker_android.md","lastUpdated":1747972048000}'),e={name:"guide/docker/docker_android.md"},p=o(`

在Docker中开设Android虚拟机

一键开设

  • 自定义安卓版本
  • 自动创建带校验的web网站
  • 自动进行nginx安装和反向代理的配置,可选择是否绑定域名,默认回车不绑定使用80端口
  • 无需考虑宿主机是否支持嵌套虚拟化
  • 支持x86_64和ARM架构

宿主机的配置至少要有1核2G内存15G硬盘,否则开设可能会导致宿主机卡死

宿主机推荐 Ubuntu 系统,Debian 系统可能导致安卓屏幕白屏

安卓版本越新占用越大,以上的配置要求是最低版本安卓的配置要求 (个人测试到 12.0.0-latest 的tag可用,更高版本映射白屏了,自己测试哪个能用吧)

如果开设后,过了5分钟浏览器网页的登录验证还是一直失败,那么请查询安卓容器的日志,大概率安卓容器崩溃了,建议更换更低的安卓系统版本的容器进行安装

开设

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

命令执行后按照提示输入即可,注意选择版本输入的是序号,对应选项的数字序号,安装完毕后打开本机IPV4+80端口可登录

如果需要查询生成的安卓信息和web登录信息,执行cat /root/android_info可查询信息

默认的用户名 onea

默认密码 oneclick

远程的桌面点击H264 Converter跳转就是了

暂时只支持生成一个安卓容器,勿要重复生成,如需替换版本请执行后续命令删除后再次开设

暂时只支持开设后一直使用,不可重启服务器,重启后可能无法自重启映射成功,自测

删除

  • 删除容器
  • 删除容器对应镜像
  • 删除配置文件
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
`,22),l=[p];function r(t,c,i,d,C,y){return a(),n("div",null,l)}const h=s(e,[["render",r]]);export{D as __pageData,h as default}; diff --git a/assets/guide_docker_docker_build.md.DoAlFeWZ.js b/assets/guide_docker_docker_build.md.DoAlFeWZ.js new file mode 100644 index 0000000000..21e15646e6 --- /dev/null +++ b/assets/guide_docker_docker_build.md.DoAlFeWZ.js @@ -0,0 +1,24 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_build.md","filePath":"guide/docker/docker_build.md","lastUpdated":1747984962000}'),n={name:"guide/docker/docker_build.md"};function e(l,s,p,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h(`

前言

两种开设方式

单独开设

  • 只生成一个docker,这里有判断为国际服务器还是国内服务器,如果在国内服务器上开设,容器内的包管理源自动替换为清华源
  • 可配置绑定独立的IPV6地址,但需要先前使用本套脚本的环境安装命令安装的docker,且需要宿主机至少绑定了/112的IPV6子网
  • 支持x86_64和ARM架构的服务器

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

示例

运行支持的变量

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

目前system仅支持选择

  • alpine
  • debian
  • ubuntu
  • almalinux

默认不填则是debian

shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

以下为开设的示例容器的信息:

属性
容器名字test
SSH登录的用户名root
SSH登录的密码123456
CPU核数1
内存大小512MB
SSH端口25000
内外网映射端口一致的区间34975到35000
系统debian
是否绑定独立的IPV6地址N

相关操作

删除示例

shell
docker rm -f test
+rm -rf test
+ls

进入示例

shell
docker exec -it test /bin/bash

要退出容器就执行exit退出。

查询已开设的信息

shell
cat 容器名字

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

批量开设

  • 批量多次运行继承配置生成
  • 生成多个时为避免SSH连接中断建议在screen中执行
  • 支持x86_64和ARM架构的服务器

运行

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

查询批量开设的信息

shell
cat dclog

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

一行一个容器对应的信息,docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

卸载所有docker容器和镜像

以下命令卸载会忽略ndpresponder,以防止IPV6的配置失效

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
+docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
+rm -rf dclog
+ls

更新上述所有脚本

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/onedocker.sh
+rm -rf /root/create_docker.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

宿主机重启后重启所有容器

默认容器没有设置停止后自重启,需要执行以下命令启动所有停止的容器

docker start $(docker ps -aq)

宿主机重启后启动所有容器的SSH服务

由于容器本身没有守护进程,所以SSH服务无法自启动,需要执行以下命令启动所有容器的SSH进程

container_ids=$(docker ps -q)
+for container_id in $container_ids
+do
+    docker exec -it $container_id bash -c "service ssh start"
+    docker exec -it $container_id bash -c "service sshd restart"
+    docker exec -it $container_id sh -c "service ssh start"
+    docker exec -it $container_id sh -c "/usr/sbin/sshd"
+done
`,55)]))}const F=i(n,[["render",e]]);export{o as __pageData,F as default}; diff --git a/assets/guide_docker_docker_build.md.DoAlFeWZ.lean.js b/assets/guide_docker_docker_build.md.DoAlFeWZ.lean.js new file mode 100644 index 0000000000..7413eb6e31 --- /dev/null +++ b/assets/guide_docker_docker_build.md.DoAlFeWZ.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_build.md","filePath":"guide/docker/docker_build.md","lastUpdated":1747984962000}'),n={name:"guide/docker/docker_build.md"};function e(l,s,p,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h("",55)]))}const F=i(n,[["render",e]]);export{o as __pageData,F as default}; diff --git a/assets/guide_docker_docker_build.md.d0d61806.js b/assets/guide_docker_docker_build.md.d0d61806.js deleted file mode 100644 index 81ddf24f15..0000000000 --- a/assets/guide_docker_docker_build.md.d0d61806.js +++ /dev/null @@ -1,24 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_build.md","filePath":"guide/docker/docker_build.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_build.md"},p=l(`

前言

两种开设方式

单独开设

  • 只生成一个docker,这里有判断为国际服务器还是国内服务器,如果在国内服务器上开设,容器内的包管理源自动替换为清华源
  • 可配置绑定独立的IPV6地址,但需要先前使用本套脚本的环境安装命令安装的docker,且需要宿主机至少绑定了/112的IPV6子网
  • 支持x86_64和ARM架构的服务器

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

示例

运行支持的变量

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

目前system仅支持选择

  • alpine
  • debian
  • ubuntu
  • almalinux

默认不填则是debian

shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

以下为开设的示例容器的信息:

属性
容器名字test
SSH登录的用户名root
SSH登录的密码123456
CPU核数1
内存大小512MB
SSH端口25000
内外网映射端口一致的区间34975到35000
系统debian
是否绑定独立的IPV6地址N

相关操作

删除示例

shell
docker rm -f test
-rm -rf test
-ls

进入示例

shell
docker exec -it test /bin/bash

要退出容器就执行exit退出。

查询已开设的信息

shell
cat 容器名字

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

批量开设

  • 批量多次运行继承配置生成
  • 生成多个时为避免SSH连接中断建议在screen中执行
  • 支持x86_64和ARM架构的服务器

运行

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

查询批量开设的信息

shell
cat dclog

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

一行一个容器对应的信息,docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

卸载所有docker容器和镜像

以下命令卸载会忽略ndpresponder,以防止IPV6的配置失效

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

更新上述所有脚本

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

宿主机重启后重启所有容器

默认容器没有设置停止后自重启,需要执行以下命令启动所有停止的容器

docker start $(docker ps -aq)

宿主机重启后启动所有容器的SSH服务

由于容器本身没有守护进程,所以SSH服务无法自启动,需要执行以下命令启动所有容器的SSH进程

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
`,55),e=[p];function t(c,r,C,y,i,D){return a(),n("div",null,e)}const h=s(o,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_docker_docker_build.md.d0d61806.lean.js b/assets/guide_docker_docker_build.md.d0d61806.lean.js deleted file mode 100644 index 81ddf24f15..0000000000 --- a/assets/guide_docker_docker_build.md.d0d61806.lean.js +++ /dev/null @@ -1,24 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_build.md","filePath":"guide/docker/docker_build.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_build.md"},p=l(`

前言

两种开设方式

单独开设

  • 只生成一个docker,这里有判断为国际服务器还是国内服务器,如果在国内服务器上开设,容器内的包管理源自动替换为清华源
  • 可配置绑定独立的IPV6地址,但需要先前使用本套脚本的环境安装命令安装的docker,且需要宿主机至少绑定了/112的IPV6子网
  • 支持x86_64和ARM架构的服务器

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

示例

运行支持的变量

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

目前system仅支持选择

  • alpine
  • debian
  • ubuntu
  • almalinux

默认不填则是debian

shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

以下为开设的示例容器的信息:

属性
容器名字test
SSH登录的用户名root
SSH登录的密码123456
CPU核数1
内存大小512MB
SSH端口25000
内外网映射端口一致的区间34975到35000
系统debian
是否绑定独立的IPV6地址N

相关操作

删除示例

shell
docker rm -f test
-rm -rf test
-ls

进入示例

shell
docker exec -it test /bin/bash

要退出容器就执行exit退出。

查询已开设的信息

shell
cat 容器名字

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

批量开设

  • 批量多次运行继承配置生成
  • 生成多个时为避免SSH连接中断建议在screen中执行
  • 支持x86_64和ARM架构的服务器

运行

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

查询批量开设的信息

shell
cat dclog

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

一行一个容器对应的信息,docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

卸载所有docker容器和镜像

以下命令卸载会忽略ndpresponder,以防止IPV6的配置失效

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

更新上述所有脚本

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

宿主机重启后重启所有容器

默认容器没有设置停止后自重启,需要执行以下命令启动所有停止的容器

docker start $(docker ps -aq)

宿主机重启后启动所有容器的SSH服务

由于容器本身没有守护进程,所以SSH服务无法自启动,需要执行以下命令启动所有容器的SSH进程

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
`,55),e=[p];function t(c,r,C,y,i,D){return a(),n("div",null,e)}const h=s(o,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_docker_docker_custom.md.01bd0eed.js b/assets/guide_docker_docker_custom.md.01bd0eed.js deleted file mode 100644 index 2be1e10f7a..0000000000 --- a/assets/guide_docker_docker_custom.md.01bd0eed.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as l,R as o}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"使用Docker一键安装某些容器的脚本","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_custom.md","filePath":"guide/docker/docker_custom.md","lastUpdated":1747972048000}'),p={name:"guide/docker/docker_custom.md"},n=o(`

使用Docker一键安装某些容器的脚本

每个容器都有对应的配置要求,自行查看,内存不够的用https://github.com/spiritLHLS/addswap

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

开设虚拟内存补足也行

注意,以下脚本使用前务必使用本套教程中的环境安装脚本进行前期环境安装

一键开设Firefox浏览器的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 可选是否开启VNC端口,默认不开启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 不支持声音映射,无论是WEB端还是VNC端都无法传输声音

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码1G硬盘

开设

如果未设置自定义密码,开设后默认的密码是oneclick

默认的web端口是3003,开设后打开本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

删除

修改以下端口号3003为你实际的端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3003"
-docker stop firefox_\${PORT}
-docker rm -f firefox_\${PORT}
-rm -rf /usr/local/bin/firefox_\${PORT}
-docker rmi jlesage/firefox

一键开设Chrome浏览器的容器

  • 已设置崩溃自启
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射

宿主机需要至少1核2G内存10G硬盘,开设的容器大小将占用起码1G硬盘

首次安装过程中最好在screen中挂起执行,避免长时间运行SSH连接断开

开设

如果未设置自定义用户名,开设后默认的用户名是oneclick

如果未设置自定义密码,开设后默认的密码是oneclick

默认的http端口是3004,开设后打开http://本机IPV4:端口即可

默认的https端口是3005,开设后打开https://本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

删除

修改以下端口号3004为你实际的http端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3004"
-docker stop chromium_\${PORT}
-docker rm -f chromium_\${PORT}
-rm -rf /usr/local/bin/config_\${PORT}
-rm -rf /usr/local/bin/password_\${PORT}
-docker rmi lscr.io/linuxserver/chromium

注意事项

  • nginx,caddy等https映射的时候要映射3004的端口,不要映射3005端口
  • 部署以后安静的等待15分钟,不然中文库没安装全,会出现不可预料的错误
  • 进入远程桌面浏览器以后点击左侧的设置->点开输入法进行设置,不然没法输入中文

图片

一键开设Desktop的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置用户名和密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射,WEB端可传输声音

完整的Linux桌面,可以在上面使用浏览器

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码3.2G硬盘

开设

开设后默认的用户名是onew,密码是oneclick,默认的内存最大占用是2GB

默认的http协议的web端口是3004,默认的https协议的web端口是3005,开设后打开对应协议的本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

删除

执行

shell
docker ps -a

查询name的前缀是webtop的容器,记录容器的ID用

shell
docker rm -f 容器的ID

删除所有关联的容器后可用

shell
docker rmi lscr.io/linuxserver/webtop

删除对应镜像

一键安装guacamole

一个网页端连接SSH或RDP等协议控制服务器的玩意

网址:http://你的IPV4地址:80/guacamole

默认用户: guacadmin

默认密码: guacadmin

安装完毕登录后自行修改

宿主机的配置至少要有1核2G内存10G硬盘,否则开设可能会导致宿主机卡死!

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

一键开设RustDesk的容器

  • 已设置崩溃自启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 传输质量看你的服务器和各端之间的连通性和延迟

一个跨端的远控中继端(非客户端),支持双向控制

宿主机需要至少1核1G内存10G硬盘,对带宽的需求极低

开设

安装后客户端在这里找 https://github.com/rustdesk/rustdesk/releases/latest

在设置中设置中继服务器的IP即可,支持 Android、Windows、Linux、浏览器 端,支持电脑远控手机

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onerustdesk.sh -o onerustdesk.sh && chmod +x onerustdesk.sh && bash onerustdesk.sh

删除

删除容器

shell
docker rm -f hbbs
-docker rm -f hbbr

删除对应镜像

shell
docker rmi rustdesk/rustdesk-server
`,71),e=[n];function t(c,r,C,y,i,D){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_docker_docker_custom.md.01bd0eed.lean.js b/assets/guide_docker_docker_custom.md.01bd0eed.lean.js deleted file mode 100644 index 2be1e10f7a..0000000000 --- a/assets/guide_docker_docker_custom.md.01bd0eed.lean.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as l,R as o}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"使用Docker一键安装某些容器的脚本","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_custom.md","filePath":"guide/docker/docker_custom.md","lastUpdated":1747972048000}'),p={name:"guide/docker/docker_custom.md"},n=o(`

使用Docker一键安装某些容器的脚本

每个容器都有对应的配置要求,自行查看,内存不够的用https://github.com/spiritLHLS/addswap

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

开设虚拟内存补足也行

注意,以下脚本使用前务必使用本套教程中的环境安装脚本进行前期环境安装

一键开设Firefox浏览器的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 可选是否开启VNC端口,默认不开启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 不支持声音映射,无论是WEB端还是VNC端都无法传输声音

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码1G硬盘

开设

如果未设置自定义密码,开设后默认的密码是oneclick

默认的web端口是3003,开设后打开本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

删除

修改以下端口号3003为你实际的端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3003"
-docker stop firefox_\${PORT}
-docker rm -f firefox_\${PORT}
-rm -rf /usr/local/bin/firefox_\${PORT}
-docker rmi jlesage/firefox

一键开设Chrome浏览器的容器

  • 已设置崩溃自启
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射

宿主机需要至少1核2G内存10G硬盘,开设的容器大小将占用起码1G硬盘

首次安装过程中最好在screen中挂起执行,避免长时间运行SSH连接断开

开设

如果未设置自定义用户名,开设后默认的用户名是oneclick

如果未设置自定义密码,开设后默认的密码是oneclick

默认的http端口是3004,开设后打开http://本机IPV4:端口即可

默认的https端口是3005,开设后打开https://本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

删除

修改以下端口号3004为你实际的http端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3004"
-docker stop chromium_\${PORT}
-docker rm -f chromium_\${PORT}
-rm -rf /usr/local/bin/config_\${PORT}
-rm -rf /usr/local/bin/password_\${PORT}
-docker rmi lscr.io/linuxserver/chromium

注意事项

  • nginx,caddy等https映射的时候要映射3004的端口,不要映射3005端口
  • 部署以后安静的等待15分钟,不然中文库没安装全,会出现不可预料的错误
  • 进入远程桌面浏览器以后点击左侧的设置->点开输入法进行设置,不然没法输入中文

图片

一键开设Desktop的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置用户名和密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射,WEB端可传输声音

完整的Linux桌面,可以在上面使用浏览器

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码3.2G硬盘

开设

开设后默认的用户名是onew,密码是oneclick,默认的内存最大占用是2GB

默认的http协议的web端口是3004,默认的https协议的web端口是3005,开设后打开对应协议的本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

删除

执行

shell
docker ps -a

查询name的前缀是webtop的容器,记录容器的ID用

shell
docker rm -f 容器的ID

删除所有关联的容器后可用

shell
docker rmi lscr.io/linuxserver/webtop

删除对应镜像

一键安装guacamole

一个网页端连接SSH或RDP等协议控制服务器的玩意

网址:http://你的IPV4地址:80/guacamole

默认用户: guacadmin

默认密码: guacadmin

安装完毕登录后自行修改

宿主机的配置至少要有1核2G内存10G硬盘,否则开设可能会导致宿主机卡死!

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

一键开设RustDesk的容器

  • 已设置崩溃自启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 传输质量看你的服务器和各端之间的连通性和延迟

一个跨端的远控中继端(非客户端),支持双向控制

宿主机需要至少1核1G内存10G硬盘,对带宽的需求极低

开设

安装后客户端在这里找 https://github.com/rustdesk/rustdesk/releases/latest

在设置中设置中继服务器的IP即可,支持 Android、Windows、Linux、浏览器 端,支持电脑远控手机

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onerustdesk.sh -o onerustdesk.sh && chmod +x onerustdesk.sh && bash onerustdesk.sh

删除

删除容器

shell
docker rm -f hbbs
-docker rm -f hbbr

删除对应镜像

shell
docker rmi rustdesk/rustdesk-server
`,71),e=[n];function t(c,r,C,y,i,D){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_docker_docker_custom.md.uaKETGnt.js b/assets/guide_docker_docker_custom.md.uaKETGnt.js new file mode 100644 index 0000000000..2df2159bbc --- /dev/null +++ b/assets/guide_docker_docker_custom.md.uaKETGnt.js @@ -0,0 +1,11 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"使用Docker一键安装某些容器的脚本","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_custom.md","filePath":"guide/docker/docker_custom.md","lastUpdated":1747984962000}'),e={name:"guide/docker/docker_custom.md"};function l(p,s,n,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h(`

使用Docker一键安装某些容器的脚本

每个容器都有对应的配置要求,自行查看,内存不够的用https://github.com/spiritLHLS/addswap

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

开设虚拟内存补足也行

注意,以下脚本使用前务必使用本套教程中的环境安装脚本进行前期环境安装

一键开设Firefox浏览器的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 可选是否开启VNC端口,默认不开启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 不支持声音映射,无论是WEB端还是VNC端都无法传输声音

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码1G硬盘

开设

如果未设置自定义密码,开设后默认的密码是oneclick

默认的web端口是3003,开设后打开本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

删除

修改以下端口号3003为你实际的端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3003"
+docker stop firefox_\${PORT}
+docker rm -f firefox_\${PORT}
+rm -rf /usr/local/bin/firefox_\${PORT}
+docker rmi jlesage/firefox

一键开设Chrome浏览器的容器

  • 已设置崩溃自启
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射

宿主机需要至少1核2G内存10G硬盘,开设的容器大小将占用起码1G硬盘

首次安装过程中最好在screen中挂起执行,避免长时间运行SSH连接断开

开设

如果未设置自定义用户名,开设后默认的用户名是oneclick

如果未设置自定义密码,开设后默认的密码是oneclick

默认的http端口是3004,开设后打开http://本机IPV4:端口即可

默认的https端口是3005,开设后打开https://本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

删除

修改以下端口号3004为你实际的http端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3004"
+docker stop chromium_\${PORT}
+docker rm -f chromium_\${PORT}
+rm -rf /usr/local/bin/config_\${PORT}
+rm -rf /usr/local/bin/password_\${PORT}
+docker rmi lscr.io/linuxserver/chromium

注意事项

  • nginx,caddy等https映射的时候要映射3004的端口,不要映射3005端口
  • 部署以后安静的等待15分钟,不然中文库没安装全,会出现不可预料的错误
  • 进入远程桌面浏览器以后点击左侧的设置->点开输入法进行设置,不然没法输入中文

图片

一键开设Desktop的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置用户名和密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射,WEB端可传输声音

完整的Linux桌面,可以在上面使用浏览器

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码3.2G硬盘

开设

开设后默认的用户名是onew,密码是oneclick,默认的内存最大占用是2GB

默认的http协议的web端口是3004,默认的https协议的web端口是3005,开设后打开对应协议的本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

删除

执行

shell
docker ps -a

查询name的前缀是webtop的容器,记录容器的ID用

shell
docker rm -f 容器的ID

删除所有关联的容器后可用

shell
docker rmi lscr.io/linuxserver/webtop

删除对应镜像

一键安装guacamole

一个网页端连接SSH或RDP等协议控制服务器的玩意

网址:http://你的IPV4地址:80/guacamole

默认用户: guacadmin

默认密码: guacadmin

安装完毕登录后自行修改

宿主机的配置至少要有1核2G内存10G硬盘,否则开设可能会导致宿主机卡死!

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

一键开设RustDesk的容器

  • 已设置崩溃自启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 传输质量看你的服务器和各端之间的连通性和延迟

一个跨端的远控中继端(非客户端),支持双向控制

宿主机需要至少1核1G内存10G硬盘,对带宽的需求极低

开设

安装后客户端在这里找 https://github.com/rustdesk/rustdesk/releases/latest

在设置中设置中继服务器的IP即可,支持 Android、Windows、Linux、浏览器 端,支持电脑远控手机

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onerustdesk.sh -o onerustdesk.sh && chmod +x onerustdesk.sh && bash onerustdesk.sh

删除

删除容器

shell
docker rm -f hbbs
+docker rm -f hbbr

删除对应镜像

shell
docker rmi rustdesk/rustdesk-server
`,71)]))}const F=i(e,[["render",l]]);export{c as __pageData,F as default}; diff --git a/assets/guide_docker_docker_custom.md.uaKETGnt.lean.js b/assets/guide_docker_docker_custom.md.uaKETGnt.lean.js new file mode 100644 index 0000000000..d58bcd158d --- /dev/null +++ b/assets/guide_docker_docker_custom.md.uaKETGnt.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"使用Docker一键安装某些容器的脚本","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_custom.md","filePath":"guide/docker/docker_custom.md","lastUpdated":1747984962000}'),e={name:"guide/docker/docker_custom.md"};function l(p,s,n,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h("",71)]))}const F=i(e,[["render",l]]);export{c as __pageData,F as default}; diff --git a/assets/guide_docker_docker_install.md.69dee249.js b/assets/guide_docker_docker_install.md.69dee249.js deleted file mode 100644 index 069c37a208..0000000000 --- a/assets/guide_docker_docker_install.md.69dee249.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_install.md","filePath":"guide/docker/docker_install.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_install.md"},n=p('

前言

支持开设 Docker 虚拟化的各系统,含 Linux、Android、Windows 系统

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

开设虚拟内存

TIP

内存开点swap免得机器炸了

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

环境安装

  • 检测系统环境,安装对应组件
  • 安装docker和docker-compose,这里有判断为国际服务器还是国内服务器,自动安装对应源的docker
  • 下载默认需要的一些配置脚本,设置默认的网络配置
  • 检测如果存在IPV6地址,检测其是否大于或等于/112,如果符合条件,则配置docker的ipv6的网络
  • 如果上述条件都符合,创建ndpresponder的docker和radvd,使得IPV6的分配支持ndp广播和自动分配
  • 支持x86_64和ARM架构的服务器

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

bash dockerinstall.sh

TIP

环境安装过程中可能要求你重启服务器后再次执行脚本,详见脚本运行后的说明

',20),e=[n];function t(c,r,C,i,d,y){return a(),l("div",null,e)}const h=s(o,[["render",t]]);export{D as __pageData,h as default}; diff --git a/assets/guide_docker_docker_install.md.69dee249.lean.js b/assets/guide_docker_docker_install.md.69dee249.lean.js deleted file mode 100644 index 069c37a208..0000000000 --- a/assets/guide_docker_docker_install.md.69dee249.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_install.md","filePath":"guide/docker/docker_install.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_install.md"},n=p('

前言

支持开设 Docker 虚拟化的各系统,含 Linux、Android、Windows 系统

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

开设虚拟内存

TIP

内存开点swap免得机器炸了

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

环境安装

  • 检测系统环境,安装对应组件
  • 安装docker和docker-compose,这里有判断为国际服务器还是国内服务器,自动安装对应源的docker
  • 下载默认需要的一些配置脚本,设置默认的网络配置
  • 检测如果存在IPV6地址,检测其是否大于或等于/112,如果符合条件,则配置docker的ipv6的网络
  • 如果上述条件都符合,创建ndpresponder的docker和radvd,使得IPV6的分配支持ndp广播和自动分配
  • 支持x86_64和ARM架构的服务器

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

bash dockerinstall.sh

TIP

环境安装过程中可能要求你重启服务器后再次执行脚本,详见脚本运行后的说明

',20),e=[n];function t(c,r,C,i,d,y){return a(),l("div",null,e)}const h=s(o,[["render",t]]);export{D as __pageData,h as default}; diff --git a/assets/guide_docker_docker_install.md.DkBio7r4.js b/assets/guide_docker_docker_install.md.DkBio7r4.js new file mode 100644 index 0000000000..b379b669e4 --- /dev/null +++ b/assets/guide_docker_docker_install.md.DkBio7r4.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_install.md","filePath":"guide/docker/docker_install.md","lastUpdated":1747984962000}'),h={name:"guide/docker/docker_install.md"};function p(e,s,n,k,d,r){return t(),a("div",null,s[0]||(s[0]=[l('

前言

支持开设 Docker 虚拟化的各系统,含 Linux、Android、Windows 系统

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

开设虚拟内存

TIP

内存开点swap免得机器炸了

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

环境安装

  • 检测系统环境,安装对应组件
  • 安装docker和docker-compose,这里有判断为国际服务器还是国内服务器,自动安装对应源的docker
  • 下载默认需要的一些配置脚本,设置默认的网络配置
  • 检测如果存在IPV6地址,检测其是否大于或等于/112,如果符合条件,则配置docker的ipv6的网络
  • 如果上述条件都符合,创建ndpresponder的docker和radvd,使得IPV6的分配支持ndp广播和自动分配
  • 支持x86_64和ARM架构的服务器

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

bash dockerinstall.sh

TIP

环境安装过程中可能要求你重启服务器后再次执行脚本,详见脚本运行后的说明

',20)]))}const F=i(h,[["render",p]]);export{o as __pageData,F as default}; diff --git a/assets/guide_docker_docker_install.md.DkBio7r4.lean.js b/assets/guide_docker_docker_install.md.DkBio7r4.lean.js new file mode 100644 index 0000000000..a08a8754be --- /dev/null +++ b/assets/guide_docker_docker_install.md.DkBio7r4.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_install.md","filePath":"guide/docker/docker_install.md","lastUpdated":1747984962000}'),h={name:"guide/docker/docker_install.md"};function p(e,s,n,k,d,r){return t(),a("div",null,s[0]||(s[0]=[l("",20)]))}const F=i(h,[["render",p]]);export{o as __pageData,F as default}; diff --git a/assets/guide_docker_docker_macos.md.7497eb24.js b/assets/guide_docker_docker_macos.md.7497eb24.js deleted file mode 100644 index c5ab1ccc10..0000000000 --- a/assets/guide_docker_docker_macos.md.7497eb24.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as o,R as r}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"在Docker中开设Macos虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_macos.md","filePath":"guide/docker/docker_macos.md","lastUpdated":1747972048000}'),c={name:"guide/docker/docker_macos.md"},t=r('

在Docker中开设Macos虚拟机

通过dockur开设

原始项目

https://github.com/dockur/macos

通过OSX开设

原始项目

https://github.com/sickcodes/Docker-OSX

',7),s=[t];function d(i,h,n,k,u,l){return a(),o("div",null,s)}const _=e(c,[["render",d]]);export{m as __pageData,_ as default}; diff --git a/assets/guide_docker_docker_macos.md.7497eb24.lean.js b/assets/guide_docker_docker_macos.md.7497eb24.lean.js deleted file mode 100644 index c5ab1ccc10..0000000000 --- a/assets/guide_docker_docker_macos.md.7497eb24.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as o,R as r}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"在Docker中开设Macos虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_macos.md","filePath":"guide/docker/docker_macos.md","lastUpdated":1747972048000}'),c={name:"guide/docker/docker_macos.md"},t=r('

在Docker中开设Macos虚拟机

通过dockur开设

原始项目

https://github.com/dockur/macos

通过OSX开设

原始项目

https://github.com/sickcodes/Docker-OSX

',7),s=[t];function d(i,h,n,k,u,l){return a(),o("div",null,s)}const _=e(c,[["render",d]]);export{m as __pageData,_ as default}; diff --git a/assets/guide_docker_docker_macos.md.B-ddHhbN.js b/assets/guide_docker_docker_macos.md.B-ddHhbN.js new file mode 100644 index 0000000000..7ed9895f94 --- /dev/null +++ b/assets/guide_docker_docker_macos.md.B-ddHhbN.js @@ -0,0 +1 @@ +import{_ as a,c as o,o as r,ag as t}from"./chunks/framework.CSeR4K32.js";const _=JSON.parse('{"title":"在Docker中开设Macos虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_macos.md","filePath":"guide/docker/docker_macos.md","lastUpdated":1747984962000}'),c={name:"guide/docker/docker_macos.md"};function s(d,e,i,n,k,h){return r(),o("div",null,e[0]||(e[0]=[t('

在Docker中开设Macos虚拟机

通过dockur开设

原始项目

https://github.com/dockur/macos

通过OSX开设

原始项目

https://github.com/sickcodes/Docker-OSX

',7)]))}const p=a(c,[["render",s]]);export{_ as __pageData,p as default}; diff --git a/assets/guide_docker_docker_macos.md.B-ddHhbN.lean.js b/assets/guide_docker_docker_macos.md.B-ddHhbN.lean.js new file mode 100644 index 0000000000..949b6ed5a7 --- /dev/null +++ b/assets/guide_docker_docker_macos.md.B-ddHhbN.lean.js @@ -0,0 +1 @@ +import{_ as a,c as o,o as r,ag as t}from"./chunks/framework.CSeR4K32.js";const _=JSON.parse('{"title":"在Docker中开设Macos虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_macos.md","filePath":"guide/docker/docker_macos.md","lastUpdated":1747984962000}'),c={name:"guide/docker/docker_macos.md"};function s(d,e,i,n,k,h){return r(),o("div",null,e[0]||(e[0]=[t("",7)]))}const p=a(c,[["render",s]]);export{_ as __pageData,p as default}; diff --git a/assets/guide_docker_docker_precheck.md.78609506.js b/assets/guide_docker_docker_precheck.md.78609506.js deleted file mode 100644 index d49dd58c5b..0000000000 --- a/assets/guide_docker_docker_precheck.md.78609506.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as r,b as o,R as a}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_precheck.md","filePath":"guide/docker/docker_precheck.md","lastUpdated":1747972048000}'),c={name:"guide/docker/docker_precheck.md"},t=a('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

WARNING

如果宿主机带IPV6网络的话,安装会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/docker

项目特点

通过docker批量或单独开设NAT服务器(Bulk or individual NAT server provisioning via docker)

默认使用debian系统可选alpine系统,每个容器自带1个外网ssh端口,25个内外网一致端口,可选择是否绑定IPV6地址

默认创建的是非特权容器,且不挂载与宿主机的docker的守护进程之间的通信,所以宿主机创建的docker虚拟化的NAT服务器内无法再嵌套虚拟化docker

默认安装并启用lxcfs,使得在容器内的查询资源时CPU和内存使用的是配置的视图而不是宿主机的视图

由于大部分云服务器是ext4文件系统,docker默认的存储引擎是overlayfs2,即便宿主机的文件系统是xfs,默认也不会启用pquota选项,所以默认共享宿主机硬盘,无法限制每个容器的磁盘大小

配置要求

系统可安装docker即可用,网络能连接Github的raw界面就能用,硬件配置只要不拉跨就行,空闲硬盘有3G就行

(如果需要绑定IPV6地址,那么请保证使用本套脚本的环境预设脚本进行环境安装,需要它自动预设部分设置)

如果硬件资源只是好了一点,需要限制更多东西并需要限制硬盘大小,可使用incus分区的脚本批量开LXC虚拟化的容器

如果硬件非常好资源很多,可使用PVE分区的脚本批量开KVM虚拟化的虚拟机

推荐在开设NAT服务器前先增加部分SWAP虚拟内存,避免突发的内存占用导致宿主机卡死

',17),d=[t];function s(p,i,n,l,h,k){return r(),o("div",null,d)}const f=e(c,[["render",s]]);export{_ as __pageData,f as default}; diff --git a/assets/guide_docker_docker_precheck.md.78609506.lean.js b/assets/guide_docker_docker_precheck.md.78609506.lean.js deleted file mode 100644 index d49dd58c5b..0000000000 --- a/assets/guide_docker_docker_precheck.md.78609506.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as r,b as o,R as a}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_precheck.md","filePath":"guide/docker/docker_precheck.md","lastUpdated":1747972048000}'),c={name:"guide/docker/docker_precheck.md"},t=a('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

WARNING

如果宿主机带IPV6网络的话,安装会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/docker

项目特点

通过docker批量或单独开设NAT服务器(Bulk or individual NAT server provisioning via docker)

默认使用debian系统可选alpine系统,每个容器自带1个外网ssh端口,25个内外网一致端口,可选择是否绑定IPV6地址

默认创建的是非特权容器,且不挂载与宿主机的docker的守护进程之间的通信,所以宿主机创建的docker虚拟化的NAT服务器内无法再嵌套虚拟化docker

默认安装并启用lxcfs,使得在容器内的查询资源时CPU和内存使用的是配置的视图而不是宿主机的视图

由于大部分云服务器是ext4文件系统,docker默认的存储引擎是overlayfs2,即便宿主机的文件系统是xfs,默认也不会启用pquota选项,所以默认共享宿主机硬盘,无法限制每个容器的磁盘大小

配置要求

系统可安装docker即可用,网络能连接Github的raw界面就能用,硬件配置只要不拉跨就行,空闲硬盘有3G就行

(如果需要绑定IPV6地址,那么请保证使用本套脚本的环境预设脚本进行环境安装,需要它自动预设部分设置)

如果硬件资源只是好了一点,需要限制更多东西并需要限制硬盘大小,可使用incus分区的脚本批量开LXC虚拟化的容器

如果硬件非常好资源很多,可使用PVE分区的脚本批量开KVM虚拟化的虚拟机

推荐在开设NAT服务器前先增加部分SWAP虚拟内存,避免突发的内存占用导致宿主机卡死

',17),d=[t];function s(p,i,n,l,h,k){return r(),o("div",null,d)}const f=e(c,[["render",s]]);export{_ as __pageData,f as default}; diff --git a/assets/guide_docker_docker_precheck.md.Dgik3VYv.js b/assets/guide_docker_docker_precheck.md.Dgik3VYv.js new file mode 100644 index 0000000000..59609422b5 --- /dev/null +++ b/assets/guide_docker_docker_precheck.md.Dgik3VYv.js @@ -0,0 +1 @@ +import{_ as r,c as o,o as a,ag as c}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_precheck.md","filePath":"guide/docker/docker_precheck.md","lastUpdated":1747984962000}'),t={name:"guide/docker/docker_precheck.md"};function d(p,e,i,s,n,l){return a(),o("div",null,e[0]||(e[0]=[c('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

WARNING

如果宿主机带IPV6网络的话,安装会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/docker

项目特点

通过docker批量或单独开设NAT服务器(Bulk or individual NAT server provisioning via docker)

默认使用debian系统可选alpine系统,每个容器自带1个外网ssh端口,25个内外网一致端口,可选择是否绑定IPV6地址

默认创建的是非特权容器,且不挂载与宿主机的docker的守护进程之间的通信,所以宿主机创建的docker虚拟化的NAT服务器内无法再嵌套虚拟化docker

默认安装并启用lxcfs,使得在容器内的查询资源时CPU和内存使用的是配置的视图而不是宿主机的视图

由于大部分云服务器是ext4文件系统,docker默认的存储引擎是overlayfs2,即便宿主机的文件系统是xfs,默认也不会启用pquota选项,所以默认共享宿主机硬盘,无法限制每个容器的磁盘大小

配置要求

系统可安装docker即可用,网络能连接Github的raw界面就能用,硬件配置只要不拉跨就行,空闲硬盘有3G就行

(如果需要绑定IPV6地址,那么请保证使用本套脚本的环境预设脚本进行环境安装,需要它自动预设部分设置)

如果硬件资源只是好了一点,需要限制更多东西并需要限制硬盘大小,可使用incus分区的脚本批量开LXC虚拟化的容器

如果硬件非常好资源很多,可使用PVE分区的脚本批量开KVM虚拟化的虚拟机

推荐在开设NAT服务器前先增加部分SWAP虚拟内存,避免突发的内存占用导致宿主机卡死

',17)]))}const _=r(t,[["render",d]]);export{h as __pageData,_ as default}; diff --git a/assets/guide_docker_docker_precheck.md.Dgik3VYv.lean.js b/assets/guide_docker_docker_precheck.md.Dgik3VYv.lean.js new file mode 100644 index 0000000000..ac8dfc3425 --- /dev/null +++ b/assets/guide_docker_docker_precheck.md.Dgik3VYv.lean.js @@ -0,0 +1 @@ +import{_ as r,c as o,o as a,ag as c}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_precheck.md","filePath":"guide/docker/docker_precheck.md","lastUpdated":1747984962000}'),t={name:"guide/docker/docker_precheck.md"};function d(p,e,i,s,n,l){return a(),o("div",null,e[0]||(e[0]=[c("",17)]))}const _=r(t,[["render",d]]);export{h as __pageData,_ as default}; diff --git a/assets/guide_docker_docker_qa.md.94f80b81.js b/assets/guide_docker_docker_qa.md.94f80b81.js deleted file mode 100644 index a176ea1175..0000000000 --- a/assets/guide_docker_docker_qa.md.94f80b81.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as l}from"./chunks/framework.70afa331.js";const k=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_qa.md","filePath":"guide/docker/docker_qa.md","lastUpdated":1747972048000}'),n={name:"guide/docker/docker_qa.md"},p=l('

解惑

常见的一些docker命令

查询某个容器的实时占用

docker stats 容器名字

进入某个容器

docker exec -it 容器名字 /bin/bash

清理 Docker 缓存,清理未使用的资源,包括镜像、容器、网络等

docker system prune -a

卸载所有docker的镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

查看对应容器日志

docker logs 容器名字或ID

查看docker整体的disk占用

docker system df

查看所有容器

docker ps -a

查看所有镜像

docker images

删除某个特定容器

docker rm -f 容器名字或ID

删除某个特定镜像

docker rmi 镜像名字或ID
',22),o=[p];function t(c,i,d,r,g,h){return s(),e("div",null,o)}const C=a(n,[["render",t]]);export{k as __pageData,C as default}; diff --git a/assets/guide_docker_docker_qa.md.94f80b81.lean.js b/assets/guide_docker_docker_qa.md.94f80b81.lean.js deleted file mode 100644 index a176ea1175..0000000000 --- a/assets/guide_docker_docker_qa.md.94f80b81.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as s,b as e,R as l}from"./chunks/framework.70afa331.js";const k=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_qa.md","filePath":"guide/docker/docker_qa.md","lastUpdated":1747972048000}'),n={name:"guide/docker/docker_qa.md"},p=l('

解惑

常见的一些docker命令

查询某个容器的实时占用

docker stats 容器名字

进入某个容器

docker exec -it 容器名字 /bin/bash

清理 Docker 缓存,清理未使用的资源,包括镜像、容器、网络等

docker system prune -a

卸载所有docker的镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

查看对应容器日志

docker logs 容器名字或ID

查看docker整体的disk占用

docker system df

查看所有容器

docker ps -a

查看所有镜像

docker images

删除某个特定容器

docker rm -f 容器名字或ID

删除某个特定镜像

docker rmi 镜像名字或ID
',22),o=[p];function t(c,i,d,r,g,h){return s(),e("div",null,o)}const C=a(n,[["render",t]]);export{k as __pageData,C as default}; diff --git a/assets/guide_docker_docker_qa.md.BAZeywiq.js b/assets/guide_docker_docker_qa.md.BAZeywiq.js new file mode 100644 index 0000000000..134a9202f5 --- /dev/null +++ b/assets/guide_docker_docker_qa.md.BAZeywiq.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_qa.md","filePath":"guide/docker/docker_qa.md","lastUpdated":1747984962000}'),i={name:"guide/docker/docker_qa.md"};function n(d,a,c,o,l,r){return t(),s("div",null,a[0]||(a[0]=[p('

解惑

常见的一些docker命令

查询某个容器的实时占用

docker stats 容器名字

进入某个容器

docker exec -it 容器名字 /bin/bash

清理 Docker 缓存,清理未使用的资源,包括镜像、容器、网络等

docker system prune -a

卸载所有docker的镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

查看对应容器日志

docker logs 容器名字或ID

查看docker整体的disk占用

docker system df

查看所有容器

docker ps -a

查看所有镜像

docker images

删除某个特定容器

docker rm -f 容器名字或ID

删除某个特定镜像

docker rmi 镜像名字或ID
',22)]))}const u=e(i,[["render",n]]);export{g as __pageData,u as default}; diff --git a/assets/guide_docker_docker_qa.md.BAZeywiq.lean.js b/assets/guide_docker_docker_qa.md.BAZeywiq.lean.js new file mode 100644 index 0000000000..9e0e530b32 --- /dev/null +++ b/assets/guide_docker_docker_qa.md.BAZeywiq.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_qa.md","filePath":"guide/docker/docker_qa.md","lastUpdated":1747984962000}'),i={name:"guide/docker/docker_qa.md"};function n(d,a,c,o,l,r){return t(),s("div",null,a[0]||(a[0]=[p("",22)]))}const u=e(i,[["render",n]]);export{g as __pageData,u as default}; diff --git a/assets/guide_docker_docker_thanks.md.4049eaf0.js b/assets/guide_docker_docker_thanks.md.4049eaf0.js deleted file mode 100644 index d6b30ed25f..0000000000 --- a/assets/guide_docker_docker_thanks.md.4049eaf0.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/docker/docker_thanks.md","filePath":"guide/docker/docker_thanks.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_thanks.md"},n=a('

致谢

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/rustdesk/rustdesk

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 和 @CoiaPrant 提供的Docker指导

',21),h=[n];function p(c,s,i,l,u,d){return e(),t("div",null,h)}const b=r(o,[["render",p]]);export{m as __pageData,b as default}; diff --git a/assets/guide_docker_docker_thanks.md.4049eaf0.lean.js b/assets/guide_docker_docker_thanks.md.4049eaf0.lean.js deleted file mode 100644 index d6b30ed25f..0000000000 --- a/assets/guide_docker_docker_thanks.md.4049eaf0.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as a}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/docker/docker_thanks.md","filePath":"guide/docker/docker_thanks.md","lastUpdated":1747972048000}'),o={name:"guide/docker/docker_thanks.md"},n=a('

致谢

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/rustdesk/rustdesk

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 和 @CoiaPrant 提供的Docker指导

',21),h=[n];function p(c,s,i,l,u,d){return e(),t("div",null,h)}const b=r(o,[["render",p]]);export{m as __pageData,b as default}; diff --git a/assets/guide_docker_docker_thanks.md.CMHMSDTy.js b/assets/guide_docker_docker_thanks.md.CMHMSDTy.js new file mode 100644 index 0000000000..591e4137e5 --- /dev/null +++ b/assets/guide_docker_docker_thanks.md.CMHMSDTy.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/docker/docker_thanks.md","filePath":"guide/docker/docker_thanks.md","lastUpdated":1747984962000}'),n={name:"guide/docker/docker_thanks.md"};function p(h,r,c,i,s,l){return a(),t("div",null,r[0]||(r[0]=[o('

致谢

https://hub.docker.com/_/debian

https://hub.docker.com/r/redroid/redroid

https://github.com/NetrisTV/ws-scrcpy

https://guacamole.apache.org/doc/gug/introduction.html

https://blog.imoeq.com/oracle-arm-run-android-by-docker

https://blog.imoeq.com/scrcpy-run-a-android-web-page

https://github.com/NetrisTV/ws-scrcpy

https://www.howtoforge.com/how-to-install-apache-guacamole-as-docker-container-on-ubuntu/

https://releases.hashicorp.com/vagrant/

https://github.com/hashicorp/vagrant/

https://app.vagrantup.com/peru

https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1

https://forum.garudalinux.org/t/error-while-attempting-to-create-a-virtual-machine-with-virt-manager/18534/4

https://github.com/jlesage/docker-firefox

https://github.com/linuxserver/docker-webtop

https://github.com/rustdesk/rustdesk

https://github.com/yoursunny/ndpresponder

https://github.com/linuxserver/docker-chromium

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 和 @CoiaPrant 提供的Docker指导

',21)]))}const d=e(n,[["render",p]]);export{g as __pageData,d as default}; diff --git a/assets/guide_docker_docker_thanks.md.CMHMSDTy.lean.js b/assets/guide_docker_docker_thanks.md.CMHMSDTy.lean.js new file mode 100644 index 0000000000..6acbbabac5 --- /dev/null +++ b/assets/guide_docker_docker_thanks.md.CMHMSDTy.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/docker/docker_thanks.md","filePath":"guide/docker/docker_thanks.md","lastUpdated":1747984962000}'),n={name:"guide/docker/docker_thanks.md"};function p(h,r,c,i,s,l){return a(),t("div",null,r[0]||(r[0]=[o("",21)]))}const d=e(n,[["render",p]]);export{g as __pageData,d as default}; diff --git a/assets/guide_docker_docker_windows.md.9011d893.js b/assets/guide_docker_docker_windows.md.9011d893.js deleted file mode 100644 index 77bea01d0d..0000000000 --- a/assets/guide_docker_docker_windows.md.9011d893.js +++ /dev/null @@ -1,26 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"在Docker中开设Windows系统虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_windows.md","filePath":"guide/docker/docker_windows.md","lastUpdated":1747972048000}'),l={name:"guide/docker/docker_windows.md"},p=o(`

在Docker中开设Windows系统虚拟机

一键开设(通过vagrant)

  • 共享宿主机所有资源(CPU、内存、硬盘),基于docker所以只占用系统的大小,适合多开
  • 共享IP,做了docker的NAT映射,可选择是否映射到外网或仅内网
  • 设置的win系统默认最多占用为1核2G内存50G硬盘,实际占用看使用情况
  • 无需iptables进行NAT映射,删除容器时自动删除了端口的映射,方便维护
  • 需要考虑宿主机是否支持嵌套虚拟化,暂时只支持X86_64架构的系统

宿主机需要支持嵌套虚拟化,且暂时只支持X86_64架构的系统,否则不可开设

执行

egrep -c '(vmx|svm)' /proc/cpuinfo

结果需要大于或等于1,不能为0

然后需要先设置docker切换使用v1版cgroup启动

sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

如果执行都无报错,执行reboot重启系统以使得设置生效

支持的镜像

使用的自建的镜像:https://hub.docker.com/r/spiritlhl/wds

镜像名字镜像大小
1020G
202217.5G
201917G

创建出的容器大小会比镜像大小大一丢丢,但不多

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

使用方法

开设前务必在screen窗口中执行,避免SSH长期链接造成掉线卡死

./onewindows.sh 容器名字 系统版本 RDP的端口 是否为外网映射(留空则默认是N,可选Y)

开设前需要确认宿主机至少有镜像大小的两倍大小加10G硬盘的大小,因为docker在创建容器时得先将镜像拉到本地再创建

创建过程中,硬盘占用峰值为宿主机系统+镜像大小+容器大小

比如开设容器名字为test,占用最低的Windows 2019系统的容器,映射外网RDP端口为13389,设置为外网映射(映射到你的服务器外网IPV4地址)

./onewindows.sh test 2019 13389 Y

开设后默认的用户名是Administratorvagrant

默认的密码是vagrant

如果你选择开设映射的外网端口,务必登录后修改对应账户的密码(两个账户都可能有,自行尝试),否则可能被人爆破滥用

删除

需要删除对应镜像和容器,先执行docker ps -adocker images查询镜像是spiritlhl/wds的ID,然后对应使用

docker rm -f 容器的ID
-docker rmi 镜像的ID

删除后可开设别的版本的windows容器

(在宿主机上使用Docker安装Windows系统,好像绕过了某些商家不允许DD成Win系统的TOS限制)

手动开设(通过 Dockur 项目)

本项目支持在宿主机不支持嵌套虚拟化的情况下,使用 QEMU 进行虚拟机创建。

原始项目地址

注意事项:

  • 原始项目仅为启动器,不包含 Windows 镜像;

  • 使用时需下载镜像文件,在境内网络环境下首次启动容器需约 4 小时(含镜像下载和安装);

  • 默认要求宿主机具备以下最低硬件资源(可通过修改脚本进行调整):

    • CPU:至少 4 核
    • 内存:至少 4G
    • 硬盘:至少 64G

如需魔改启动脚本以减少资源占用或调整其他参数,可参考以下文章:

对于 x86_64 架构用户

提供一个已魔改的启动器(单文件版本),方便自行构建 Windows 镜像。该版本将系统文件和镜像直接写入 Docker 写入层中,无需额外挂载镜像文件

下载链接: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

导入 Docker 镜像:

bash
docker load -i builder.tar

使用自定义 Windows ISO 镜像启动容器

首先从以下地址下载 Windows ISO 镜像: https://down.idc.wiki/ISOS/Windows/

启动容器示例命令:

bash
docker run -it -d \\
-  -e RAM_SIZE="8G" \\
-  -e CPU_CORES="4" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  -v "$(pwd)/Windows镜像文件.iso:/boot.iso" \\
-  --stop-timeout 120 \\
-  windows:builder

使用内置镜像(推荐快速部署)

我们也提供一个已集成系统镜像和配置的成品镜像,特点如下:

  • 镜像大小约 26G(包含系统镜像与默认配置);
  • 已集成自动磁盘扩容与开机任务;
  • 下载后导入 Docker 即可使用;
  • 注意:合并下载路径需要约 60G 空间。

下载与合并切片

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

启动容器

bash
docker load -i win2022.tar
-docker run -it -d \\
-  -e RAM_SIZE="4G" \\
-  -e CPU_CORES="2" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  --stop-timeout 120 \\
-  windows:2022

注意事项

不建议在当前镜像基础上使用 docker commit 保存修改,因为写入层会不断叠加,导致二次生成的镜像体积可能超过 40G。

如需进行个性化配置或集成应用,请builder 镜像开始自行构建新镜像,以保持镜像整洁与可维护性。

`,58),e=[p];function t(r,c,i,d,C,y){return a(),n("div",null,e)}const h=s(l,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/guide_docker_docker_windows.md.9011d893.lean.js b/assets/guide_docker_docker_windows.md.9011d893.lean.js deleted file mode 100644 index 77bea01d0d..0000000000 --- a/assets/guide_docker_docker_windows.md.9011d893.lean.js +++ /dev/null @@ -1,26 +0,0 @@ -import{_ as s,v as a,b as n,R as o}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"在Docker中开设Windows系统虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_windows.md","filePath":"guide/docker/docker_windows.md","lastUpdated":1747972048000}'),l={name:"guide/docker/docker_windows.md"},p=o(`

在Docker中开设Windows系统虚拟机

一键开设(通过vagrant)

  • 共享宿主机所有资源(CPU、内存、硬盘),基于docker所以只占用系统的大小,适合多开
  • 共享IP,做了docker的NAT映射,可选择是否映射到外网或仅内网
  • 设置的win系统默认最多占用为1核2G内存50G硬盘,实际占用看使用情况
  • 无需iptables进行NAT映射,删除容器时自动删除了端口的映射,方便维护
  • 需要考虑宿主机是否支持嵌套虚拟化,暂时只支持X86_64架构的系统

宿主机需要支持嵌套虚拟化,且暂时只支持X86_64架构的系统,否则不可开设

执行

egrep -c '(vmx|svm)' /proc/cpuinfo

结果需要大于或等于1,不能为0

然后需要先设置docker切换使用v1版cgroup启动

sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

如果执行都无报错,执行reboot重启系统以使得设置生效

支持的镜像

使用的自建的镜像:https://hub.docker.com/r/spiritlhl/wds

镜像名字镜像大小
1020G
202217.5G
201917G

创建出的容器大小会比镜像大小大一丢丢,但不多

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

使用方法

开设前务必在screen窗口中执行,避免SSH长期链接造成掉线卡死

./onewindows.sh 容器名字 系统版本 RDP的端口 是否为外网映射(留空则默认是N,可选Y)

开设前需要确认宿主机至少有镜像大小的两倍大小加10G硬盘的大小,因为docker在创建容器时得先将镜像拉到本地再创建

创建过程中,硬盘占用峰值为宿主机系统+镜像大小+容器大小

比如开设容器名字为test,占用最低的Windows 2019系统的容器,映射外网RDP端口为13389,设置为外网映射(映射到你的服务器外网IPV4地址)

./onewindows.sh test 2019 13389 Y

开设后默认的用户名是Administratorvagrant

默认的密码是vagrant

如果你选择开设映射的外网端口,务必登录后修改对应账户的密码(两个账户都可能有,自行尝试),否则可能被人爆破滥用

删除

需要删除对应镜像和容器,先执行docker ps -adocker images查询镜像是spiritlhl/wds的ID,然后对应使用

docker rm -f 容器的ID
-docker rmi 镜像的ID

删除后可开设别的版本的windows容器

(在宿主机上使用Docker安装Windows系统,好像绕过了某些商家不允许DD成Win系统的TOS限制)

手动开设(通过 Dockur 项目)

本项目支持在宿主机不支持嵌套虚拟化的情况下,使用 QEMU 进行虚拟机创建。

原始项目地址

注意事项:

  • 原始项目仅为启动器,不包含 Windows 镜像;

  • 使用时需下载镜像文件,在境内网络环境下首次启动容器需约 4 小时(含镜像下载和安装);

  • 默认要求宿主机具备以下最低硬件资源(可通过修改脚本进行调整):

    • CPU:至少 4 核
    • 内存:至少 4G
    • 硬盘:至少 64G

如需魔改启动脚本以减少资源占用或调整其他参数,可参考以下文章:

对于 x86_64 架构用户

提供一个已魔改的启动器(单文件版本),方便自行构建 Windows 镜像。该版本将系统文件和镜像直接写入 Docker 写入层中,无需额外挂载镜像文件

下载链接: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

导入 Docker 镜像:

bash
docker load -i builder.tar

使用自定义 Windows ISO 镜像启动容器

首先从以下地址下载 Windows ISO 镜像: https://down.idc.wiki/ISOS/Windows/

启动容器示例命令:

bash
docker run -it -d \\
-  -e RAM_SIZE="8G" \\
-  -e CPU_CORES="4" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  -v "$(pwd)/Windows镜像文件.iso:/boot.iso" \\
-  --stop-timeout 120 \\
-  windows:builder

使用内置镜像(推荐快速部署)

我们也提供一个已集成系统镜像和配置的成品镜像,特点如下:

  • 镜像大小约 26G(包含系统镜像与默认配置);
  • 已集成自动磁盘扩容与开机任务;
  • 下载后导入 Docker 即可使用;
  • 注意:合并下载路径需要约 60G 空间。

下载与合并切片

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

启动容器

bash
docker load -i win2022.tar
-docker run -it -d \\
-  -e RAM_SIZE="4G" \\
-  -e CPU_CORES="2" \\
-  --name win2022 \\
-  -p 8006:8006 \\
-  --device=/dev/kvm \\
-  --device=/dev/net/tun \\
-  --cap-add NET_ADMIN \\
-  --stop-timeout 120 \\
-  windows:2022

注意事项

不建议在当前镜像基础上使用 docker commit 保存修改,因为写入层会不断叠加,导致二次生成的镜像体积可能超过 40G。

如需进行个性化配置或集成应用,请builder 镜像开始自行构建新镜像,以保持镜像整洁与可维护性。

`,58),e=[p];function t(r,c,i,d,C,y){return a(),n("div",null,e)}const h=s(l,[["render",t]]);export{A as __pageData,h as default}; diff --git a/assets/guide_docker_docker_windows.md.BAGQZpoB.js b/assets/guide_docker_docker_windows.md.BAGQZpoB.js new file mode 100644 index 0000000000..3ed4ad5f80 --- /dev/null +++ b/assets/guide_docker_docker_windows.md.BAGQZpoB.js @@ -0,0 +1,26 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"在Docker中开设Windows系统虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_windows.md","filePath":"guide/docker/docker_windows.md","lastUpdated":1747984962000}'),e={name:"guide/docker/docker_windows.md"};function p(l,s,h,d,r,o){return t(),a("div",null,s[0]||(s[0]=[n(`

在Docker中开设Windows系统虚拟机

一键开设(通过vagrant)

  • 共享宿主机所有资源(CPU、内存、硬盘),基于docker所以只占用系统的大小,适合多开
  • 共享IP,做了docker的NAT映射,可选择是否映射到外网或仅内网
  • 设置的win系统默认最多占用为1核2G内存50G硬盘,实际占用看使用情况
  • 无需iptables进行NAT映射,删除容器时自动删除了端口的映射,方便维护
  • 需要考虑宿主机是否支持嵌套虚拟化,暂时只支持X86_64架构的系统

宿主机需要支持嵌套虚拟化,且暂时只支持X86_64架构的系统,否则不可开设

执行

egrep -c '(vmx|svm)' /proc/cpuinfo

结果需要大于或等于1,不能为0

然后需要先设置docker切换使用v1版cgroup启动

sed -i 's/GRUB_CMDLINE_LINUX="\\(.*\\)"/GRUB_CMDLINE_LINUX="\\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
+update-grub
+ls

如果执行都无报错,执行reboot重启系统以使得设置生效

支持的镜像

使用的自建的镜像:https://hub.docker.com/r/spiritlhl/wds

镜像名字镜像大小
1020G
202217.5G
201917G

创建出的容器大小会比镜像大小大一丢丢,但不多

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

使用方法

开设前务必在screen窗口中执行,避免SSH长期链接造成掉线卡死

./onewindows.sh 容器名字 系统版本 RDP的端口 是否为外网映射(留空则默认是N,可选Y)

开设前需要确认宿主机至少有镜像大小的两倍大小加10G硬盘的大小,因为docker在创建容器时得先将镜像拉到本地再创建

创建过程中,硬盘占用峰值为宿主机系统+镜像大小+容器大小

比如开设容器名字为test,占用最低的Windows 2019系统的容器,映射外网RDP端口为13389,设置为外网映射(映射到你的服务器外网IPV4地址)

./onewindows.sh test 2019 13389 Y

开设后默认的用户名是Administratorvagrant

默认的密码是vagrant

如果你选择开设映射的外网端口,务必登录后修改对应账户的密码(两个账户都可能有,自行尝试),否则可能被人爆破滥用

删除

需要删除对应镜像和容器,先执行docker ps -adocker images查询镜像是spiritlhl/wds的ID,然后对应使用

docker rm -f 容器的ID
+docker rmi 镜像的ID

删除后可开设别的版本的windows容器

(在宿主机上使用Docker安装Windows系统,好像绕过了某些商家不允许DD成Win系统的TOS限制)

手动开设(通过 Dockur 项目)

本项目支持在宿主机不支持嵌套虚拟化的情况下,使用 QEMU 进行虚拟机创建。

原始项目地址

注意事项:

  • 原始项目仅为启动器,不包含 Windows 镜像;

  • 使用时需下载镜像文件,在境内网络环境下首次启动容器需约 4 小时(含镜像下载和安装);

  • 默认要求宿主机具备以下最低硬件资源(可通过修改脚本进行调整):

    • CPU:至少 4 核
    • 内存:至少 4G
    • 硬盘:至少 64G

如需魔改启动脚本以减少资源占用或调整其他参数,可参考以下文章:

对于 x86_64 架构用户

提供一个已魔改的启动器(单文件版本),方便自行构建 Windows 镜像。该版本将系统文件和镜像直接写入 Docker 写入层中,无需额外挂载镜像文件

下载链接: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

导入 Docker 镜像:

bash
docker load -i builder.tar

使用自定义 Windows ISO 镜像启动容器

首先从以下地址下载 Windows ISO 镜像: https://down.idc.wiki/ISOS/Windows/

启动容器示例命令:

bash
docker run -it -d \\
+  -e RAM_SIZE="8G" \\
+  -e CPU_CORES="4" \\
+  --name win2022 \\
+  -p 8006:8006 \\
+  --device=/dev/kvm \\
+  --device=/dev/net/tun \\
+  --cap-add NET_ADMIN \\
+  -v "$(pwd)/Windows镜像文件.iso:/boot.iso" \\
+  --stop-timeout 120 \\
+  windows:builder

使用内置镜像(推荐快速部署)

我们也提供一个已集成系统镜像和配置的成品镜像,特点如下:

  • 镜像大小约 26G(包含系统镜像与默认配置);
  • 已集成自动磁盘扩容与开机任务;
  • 下载后导入 Docker 即可使用;
  • 注意:合并下载路径需要约 60G 空间。

下载与合并切片

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
+chmod +x mergew.sh
+bash mergew.sh

启动容器

bash
docker load -i win2022.tar
+docker run -it -d \\
+  -e RAM_SIZE="4G" \\
+  -e CPU_CORES="2" \\
+  --name win2022 \\
+  -p 8006:8006 \\
+  --device=/dev/kvm \\
+  --device=/dev/net/tun \\
+  --cap-add NET_ADMIN \\
+  --stop-timeout 120 \\
+  windows:2022

注意事项

不建议在当前镜像基础上使用 docker commit 保存修改,因为写入层会不断叠加,导致二次生成的镜像体积可能超过 40G。

如需进行个性化配置或集成应用,请builder 镜像开始自行构建新镜像,以保持镜像整洁与可维护性。

`,58)]))}const g=i(e,[["render",p]]);export{c as __pageData,g as default}; diff --git a/assets/guide_docker_docker_windows.md.BAGQZpoB.lean.js b/assets/guide_docker_docker_windows.md.BAGQZpoB.lean.js new file mode 100644 index 0000000000..695875ac4e --- /dev/null +++ b/assets/guide_docker_docker_windows.md.BAGQZpoB.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"在Docker中开设Windows系统虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/docker/docker_windows.md","filePath":"guide/docker/docker_windows.md","lastUpdated":1747984962000}'),e={name:"guide/docker/docker_windows.md"};function p(l,s,h,d,r,o){return t(),a("div",null,s[0]||(s[0]=[n("",58)]))}const g=i(e,[["render",p]]);export{c as __pageData,g as default}; diff --git a/assets/guide_incus_incus_custom.md.Bm8HnEPC.js b/assets/guide_incus_incus_custom.md.Bm8HnEPC.js new file mode 100644 index 0000000000..4e2397da17 --- /dev/null +++ b/assets/guide_incus_incus_custom.md.Bm8HnEPC.js @@ -0,0 +1,80 @@ +import{_ as s,c as e,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxd1.CbGLa5s4.png",i="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",o="/assets/lxd4.CSfRHLxz.png",c="/assets/lxd5.WUJi0qzd.png",d="/assets/lxd6.Cnds779U.png",r="/assets/lxd7.EJ0s1ls2.png",h="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",b="/assets/lxd11.D6E5sVW2.png",v="/assets/lxd12.B9udKIzn.png",m="/assets/lxd13.Dwv7xBpz.png",k="/assets/lxd14.Whdz6cP-.png",f="/assets/lxd15.BjW7LbDr.png",y="/assets/lxd16.CgeIdYJ2.png",P="/assets/lxd17.CWPY1pea.png",_="/assets/lxd18.DqnpcYcL.png",w="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",C="/assets/lxd21.w-R0l00Y.png",I="/assets/lxd22.45M-VX6J.png",q="/assets/lxd23.CLaVW0qk.png",F=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_custom.md","filePath":"guide/incus/incus_custom.md","lastUpdated":1747984962000}'),V={name:"guide/incus/incus_custom.md"};function W(E,a,A,O,D,T){return n(),e("div",null,a[0]||(a[0]=[t(`

自定义

给incus启用官方的web面板进行控制

先查看 incus论坛活跃用户分享的第三方教程

不懂的部分见 给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
+systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如incus的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
+EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
+ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
+Client IPv4
+Server IPv6
+Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
+ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
+ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
+apt update -y
+
+# 安装 WireGuard 运行依赖
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# 安装 WireGuard 协议兼容的工具集合
+apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
+yum update -y
+
+# 安装额外包组件
+yum install -y epel-release 
+
+# 安装 WireGuard 运行依赖
+yum install -y net-tools
+
+# 安装 WireGuard 协议兼容的工具集合
+yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
+sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
+wg-quick up warp
+
+# 查看 IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# 查看 IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# 测试成功后断开 Warp 连接
+wg-quick down warp
+
+# 重新连接并设置进程守护,以便重启后自动生效
+systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',198)]))}const B=s(V,[["render",W]]);export{F as __pageData,B as default}; diff --git a/assets/guide_incus_incus_custom.md.Bm8HnEPC.lean.js b/assets/guide_incus_incus_custom.md.Bm8HnEPC.lean.js new file mode 100644 index 0000000000..59225c5ff9 --- /dev/null +++ b/assets/guide_incus_incus_custom.md.Bm8HnEPC.lean.js @@ -0,0 +1 @@ +import{_ as s,c as e,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxd1.CbGLa5s4.png",i="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",o="/assets/lxd4.CSfRHLxz.png",c="/assets/lxd5.WUJi0qzd.png",d="/assets/lxd6.Cnds779U.png",r="/assets/lxd7.EJ0s1ls2.png",h="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",b="/assets/lxd11.D6E5sVW2.png",v="/assets/lxd12.B9udKIzn.png",m="/assets/lxd13.Dwv7xBpz.png",k="/assets/lxd14.Whdz6cP-.png",f="/assets/lxd15.BjW7LbDr.png",y="/assets/lxd16.CgeIdYJ2.png",P="/assets/lxd17.CWPY1pea.png",_="/assets/lxd18.DqnpcYcL.png",w="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",C="/assets/lxd21.w-R0l00Y.png",I="/assets/lxd22.45M-VX6J.png",q="/assets/lxd23.CLaVW0qk.png",F=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_custom.md","filePath":"guide/incus/incus_custom.md","lastUpdated":1747984962000}'),V={name:"guide/incus/incus_custom.md"};function W(E,a,A,O,D,T){return n(),e("div",null,a[0]||(a[0]=[t("",198)]))}const B=s(V,[["render",W]]);export{F as __pageData,B as default}; diff --git a/assets/guide_incus_incus_custom.md.b1aba773.js b/assets/guide_incus_incus_custom.md.b1aba773.js deleted file mode 100644 index 583fa4354d..0000000000 --- a/assets/guide_incus_incus_custom.md.b1aba773.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const t="/assets/lxd1.78537e30.png",l="/assets/lxd2.da10b5ec.png",p="/assets/lxd3.917f56de.png",o="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",c="/assets/lxd6.572825bf.png",r="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",u="/assets/lxd9.00250a32.png",h="/assets/lxd10.a25a745c.png",C="/assets/lxd11.b83f953c.png",g="/assets/lxd12.0da335dd.png",y="/assets/lxd13.308fe0de.png",A="/assets/lxd14.8dbfdcd6.png",m="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",v="/assets/lxd17.d7ea65d8.png",f="/assets/lxd18.d6225daa.png",k="/assets/lxd19.69674669.png",D="/assets/lxd20.179fc6e1.png",P="/assets/lxd21.48123d6a.png",_="/assets/lxd22.4386597e.png",w="/assets/lxd23.c26427e3.png",U=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_custom.md","filePath":"guide/incus/incus_custom.md","lastUpdated":1747972048000}'),I={name:"guide/incus/incus_custom.md"},x=n(`

自定义

给incus启用官方的web面板进行控制

先查看 incus论坛活跃用户分享的第三方教程

不懂的部分见 给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如incus的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',198),q=[x];function V(E,W,O,F,S,G){return a(),e("div",null,q)}const K=s(I,[["render",V]]);export{U as __pageData,K as default}; diff --git a/assets/guide_incus_incus_custom.md.b1aba773.lean.js b/assets/guide_incus_incus_custom.md.b1aba773.lean.js deleted file mode 100644 index 583fa4354d..0000000000 --- a/assets/guide_incus_incus_custom.md.b1aba773.lean.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const t="/assets/lxd1.78537e30.png",l="/assets/lxd2.da10b5ec.png",p="/assets/lxd3.917f56de.png",o="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",c="/assets/lxd6.572825bf.png",r="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",u="/assets/lxd9.00250a32.png",h="/assets/lxd10.a25a745c.png",C="/assets/lxd11.b83f953c.png",g="/assets/lxd12.0da335dd.png",y="/assets/lxd13.308fe0de.png",A="/assets/lxd14.8dbfdcd6.png",m="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",v="/assets/lxd17.d7ea65d8.png",f="/assets/lxd18.d6225daa.png",k="/assets/lxd19.69674669.png",D="/assets/lxd20.179fc6e1.png",P="/assets/lxd21.48123d6a.png",_="/assets/lxd22.4386597e.png",w="/assets/lxd23.c26427e3.png",U=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_custom.md","filePath":"guide/incus/incus_custom.md","lastUpdated":1747972048000}'),I={name:"guide/incus/incus_custom.md"},x=n(`

自定义

给incus启用官方的web面板进行控制

先查看 incus论坛活跃用户分享的第三方教程

不懂的部分见 给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如incus的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',198),q=[x];function V(E,W,O,F,S,G){return a(),e("div",null,q)}const K=s(I,[["render",V]]);export{U as __pageData,K as default}; diff --git a/assets/guide_incus_incus_extra_config.md.91dfbfa5.js b/assets/guide_incus_incus_extra_config.md.91dfbfa5.js deleted file mode 100644 index 701df5875a..0000000000 --- a/assets/guide_incus_incus_extra_config.md.91dfbfa5.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_extra_config.md","filePath":"guide/incus/incus_extra_config.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_extra_config.md"},o=l(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为incus创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开incus宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

安装incus的官方可视化控制面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

`,33),e=[o];function t(c,r,C,i,y,D){return a(),n("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_incus_incus_extra_config.md.91dfbfa5.lean.js b/assets/guide_incus_incus_extra_config.md.91dfbfa5.lean.js deleted file mode 100644 index 701df5875a..0000000000 --- a/assets/guide_incus_incus_extra_config.md.91dfbfa5.lean.js +++ /dev/null @@ -1,11 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_extra_config.md","filePath":"guide/incus/incus_extra_config.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_extra_config.md"},o=l(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为incus创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开incus宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

安装incus的官方可视化控制面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

`,33),e=[o];function t(c,r,C,i,y,D){return a(),n("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.js b/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.js new file mode 100644 index 0000000000..e5ce057024 --- /dev/null +++ b/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.js @@ -0,0 +1,11 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const F=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_extra_config.md","filePath":"guide/incus/incus_extra_config.md","lastUpdated":1747984962000}'),e={name:"guide/incus/incus_extra_config.md"};function h(l,s,p,k,d,r){return t(),a("div",null,s[0]||(s[0]=[n(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为incus创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

一键安装开incus宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

安装incus的官方可视化控制面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
apt-get install -y incus-ui-canonical
+incus config set core.https_address [::]

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

`,33)]))}const o=i(e,[["render",h]]);export{F as __pageData,o as default}; diff --git a/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.lean.js b/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.lean.js new file mode 100644 index 0000000000..0567e289ca --- /dev/null +++ b/assets/guide_incus_incus_extra_config.md.AJ5M0HDo.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as n}from"./chunks/framework.CSeR4K32.js";const F=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_extra_config.md","filePath":"guide/incus/incus_extra_config.md","lastUpdated":1747984962000}'),e={name:"guide/incus/incus_extra_config.md"};function h(l,s,p,k,d,r){return t(),a("div",null,s[0]||(s[0]=[n("",33)]))}const o=i(e,[["render",h]]);export{F as __pageData,o as default}; diff --git a/assets/guide_incus_incus_install.md.BmXHRJpC.js b/assets/guide_incus_incus_install.md.BmXHRJpC.js new file mode 100644 index 0000000000..282281ccab --- /dev/null +++ b/assets/guide_incus_incus_install.md.BmXHRJpC.js @@ -0,0 +1,17 @@ +import{_ as i,c as a,o as n,ag as p}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"incus主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_install.md","filePath":"guide/incus/incus_install.md","lastUpdated":1747984962000}'),t={name:"guide/incus/incus_install.md"};function l(e,s,h,c,k,d){return n(),a("div",null,s[0]||(s[0]=[p(`

incus主体安装

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

一键安装

WARNING

如果是全新的服务器,务必保证curl命令可用且update无问题再执行本脚本。

  • 环境要求:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

shell
bash incus_install.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

TIP

执行过程中可能会要求手动重启加载存储类型到内核中,安装完毕执行到最后会自动进行服务器重启,首次完整安装完毕后的重启大概耗时400~500秒,请耐心等待

WARNING

如果你需要在一台服务器上开启超过200个INCUS容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装incus

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

sudo -i
+mkdir -p /etc/apt/keyrings/
+curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
+sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
+Enabled: yes
+Types: deb
+URIs: https://pkgs.zabbly.com/incus/stable
+Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
+Components: main
+Architectures: $(dpkg --print-architecture)
+Signed-By: /etc/apt/keyrings/zabbly.gpg
+EOF'
+apt-get update
+apt-get install incus -y
+incus -h

如果无异常,继续执行

incus admin init

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

incus -h
`,35)]))}const g=i(t,[["render",l]]);export{o as __pageData,g as default}; diff --git a/assets/guide_incus_incus_install.md.BmXHRJpC.lean.js b/assets/guide_incus_incus_install.md.BmXHRJpC.lean.js new file mode 100644 index 0000000000..27ab2506d5 --- /dev/null +++ b/assets/guide_incus_incus_install.md.BmXHRJpC.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as n,ag as p}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"incus主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_install.md","filePath":"guide/incus/incus_install.md","lastUpdated":1747984962000}'),t={name:"guide/incus/incus_install.md"};function l(e,s,h,c,k,d){return n(),a("div",null,s[0]||(s[0]=[p("",35)]))}const g=i(t,[["render",l]]);export{o as __pageData,g as default}; diff --git a/assets/guide_incus_incus_install.md.ba70a2a0.js b/assets/guide_incus_incus_install.md.ba70a2a0.js deleted file mode 100644 index 1ee597092b..0000000000 --- a/assets/guide_incus_incus_install.md.ba70a2a0.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"incus主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_install.md","filePath":"guide/incus/incus_install.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_install.md"},o=l(`

incus主体安装

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

一键安装

WARNING

如果是全新的服务器,务必保证curl命令可用且update无问题再执行本脚本。

  • 环境要求:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

shell
bash incus_install.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

TIP

执行过程中可能会要求手动重启加载存储类型到内核中,安装完毕执行到最后会自动进行服务器重启,首次完整安装完毕后的重启大概耗时400~500秒,请耐心等待

WARNING

如果你需要在一台服务器上开启超过200个INCUS容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装incus

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

如果无异常,继续执行

incus admin init

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

incus -h
`,35),e=[o];function t(c,r,i,C,y,A){return a(),n("div",null,e)}const d=s(p,[["render",t]]);export{u as __pageData,d as default}; diff --git a/assets/guide_incus_incus_install.md.ba70a2a0.lean.js b/assets/guide_incus_incus_install.md.ba70a2a0.lean.js deleted file mode 100644 index 1ee597092b..0000000000 --- a/assets/guide_incus_incus_install.md.ba70a2a0.lean.js +++ /dev/null @@ -1,17 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"incus主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_install.md","filePath":"guide/incus/incus_install.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_install.md"},o=l(`

incus主体安装

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

一键安装

WARNING

如果是全新的服务器,务必保证curl命令可用且update无问题再执行本脚本。

  • 环境要求:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

shell
bash incus_install.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

TIP

执行过程中可能会要求手动重启加载存储类型到内核中,安装完毕执行到最后会自动进行服务器重启,首次完整安装完毕后的重启大概耗时400~500秒,请耐心等待

WARNING

如果你需要在一台服务器上开启超过200个INCUS容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装incus

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo \${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

如果无异常,继续执行

incus admin init

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

incus -h
`,35),e=[o];function t(c,r,i,C,y,A){return a(),n("div",null,e)}const d=s(p,[["render",t]]);export{u as __pageData,d as default}; diff --git a/assets/guide_incus_incus_lxc.md.3de28e6b.js b/assets/guide_incus_incus_lxc.md.3de28e6b.js deleted file mode 100644 index f71e613ce1..0000000000 --- a/assets/guide_incus_incus_lxc.md.3de28e6b.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"在 Incus 中运行 LXC 容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_lxc.md","filePath":"guide/incus/incus_lxc.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_lxc.md"},o=n(`

在 Incus 中运行 LXC 容器

开设LXC容器可使用的镜像

这里展示一部分可使用的系统参数供你参考:

  • debian10,debian11,debian12
  • ubuntu18,ubuntu20,ubuntu22
  • centos8,centos9 (实际开设出来都是Stream版本)
  • alpine3.15,alpine3.16,alpine3.17,alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (都需要在GRUB中启用CGroupV1否则无法启动,详细介绍见常见问题答疑)
  • kali,archlinux
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载脚本

下载开机脚本是非必须的,如果你使用过一键安装incus的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian11,注意传入参数为系统名字+版本号

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

需要进入容器内部则执行

incus exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用incus命令

查看所有

bash
incus list

查看个例

bash
incus info 服务器名字

启动个例

bash
incus start 服务器名字

停止个例

bash
incus stop 服务器名字

删除个例

bash
incus delete -f 服务器名字

进入内部

bash
incus exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,95),e=[o];function t(c,r,C,i,y,A){return a(),l("div",null,e)}const d=s(p,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/guide_incus_incus_lxc.md.3de28e6b.lean.js b/assets/guide_incus_incus_lxc.md.3de28e6b.lean.js deleted file mode 100644 index f71e613ce1..0000000000 --- a/assets/guide_incus_incus_lxc.md.3de28e6b.lean.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"在 Incus 中运行 LXC 容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_lxc.md","filePath":"guide/incus/incus_lxc.md","lastUpdated":1747972048000}'),p={name:"guide/incus/incus_lxc.md"},o=n(`

在 Incus 中运行 LXC 容器

开设LXC容器可使用的镜像

这里展示一部分可使用的系统参数供你参考:

  • debian10,debian11,debian12
  • ubuntu18,ubuntu20,ubuntu22
  • centos8,centos9 (实际开设出来都是Stream版本)
  • alpine3.15,alpine3.16,alpine3.17,alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (都需要在GRUB中启用CGroupV1否则无法启动,详细介绍见常见问题答疑)
  • kali,archlinux
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载脚本

下载开机脚本是非必须的,如果你使用过一键安装incus的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian11,注意传入参数为系统名字+版本号

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

需要进入容器内部则执行

incus exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用incus命令

查看所有

bash
incus list

查看个例

bash
incus info 服务器名字

启动个例

bash
incus start 服务器名字

停止个例

bash
incus stop 服务器名字

删除个例

bash
incus delete -f 服务器名字

进入内部

bash
incus exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,95),e=[o];function t(c,r,C,i,y,A){return a(),l("div",null,e)}const d=s(p,[["render",t]]);export{h as __pageData,d as default}; diff --git a/assets/guide_incus_incus_lxc.md.CcPIDp5T.js b/assets/guide_incus_incus_lxc.md.CcPIDp5T.js new file mode 100644 index 0000000000..5712e85589 --- /dev/null +++ b/assets/guide_incus_incus_lxc.md.CcPIDp5T.js @@ -0,0 +1,25 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"在 Incus 中运行 LXC 容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_lxc.md","filePath":"guide/incus/incus_lxc.md","lastUpdated":1747984962000}'),n={name:"guide/incus/incus_lxc.md"};function l(p,s,e,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h(`

在 Incus 中运行 LXC 容器

开设LXC容器可使用的镜像

这里展示一部分可使用的系统参数供你参考:

  • debian10,debian11,debian12
  • ubuntu18,ubuntu20,ubuntu22
  • centos8,centos9 (实际开设出来都是Stream版本)
  • alpine3.15,alpine3.16,alpine3.17,alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (都需要在GRUB中启用CGroupV1否则无法启动,详细介绍见常见问题答疑)
  • kali,archlinux
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载脚本

下载开机脚本是非必须的,如果你使用过一键安装incus的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian11,注意传入参数为系统名字+版本号

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

需要进入容器内部则执行

incus exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
incus stop test
+incus delete test
+rm -rf test
+rm -rf test_v6
+ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
+2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用incus命令

查看所有

bash
incus list

查看个例

bash
incus info 服务器名字

启动个例

bash
incus start 服务器名字

停止个例

bash
incus stop 服务器名字

删除个例

bash
incus delete -f 服务器名字

进入内部

bash
incus exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,95)]))}const o=i(n,[["render",l]]);export{c as __pageData,o as default}; diff --git a/assets/guide_incus_incus_lxc.md.CcPIDp5T.lean.js b/assets/guide_incus_incus_lxc.md.CcPIDp5T.lean.js new file mode 100644 index 0000000000..5286543d78 --- /dev/null +++ b/assets/guide_incus_incus_lxc.md.CcPIDp5T.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"在 Incus 中运行 LXC 容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_lxc.md","filePath":"guide/incus/incus_lxc.md","lastUpdated":1747984962000}'),n={name:"guide/incus/incus_lxc.md"};function l(p,s,e,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h("",95)]))}const o=i(n,[["render",l]]);export{c as __pageData,o as default}; diff --git a/assets/guide_incus_incus_precheck.md.6bf5b424.js b/assets/guide_incus_incus_precheck.md.6bf5b424.js deleted file mode 100644 index 747a345f16..0000000000 --- a/assets/guide_incus_incus_precheck.md.6bf5b424.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as i,R as a}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_precheck.md","filePath":"guide/incus/incus_precheck.md","lastUpdated":1747972048000}'),c={name:"guide/incus/incus_precheck.md"},s=a('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/incus

要求

硬件要求:

  • 系统:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu24Debian12,别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换(优先级: btrfs > lvm > zfs > ceph > dir )

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加各种第三方镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像(含自修复镜像)

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',17),r=[s];function l(n,o,p,h,d,u){return t(),i("div",null,r)}const k=e(c,[["render",l]]);export{g as __pageData,k as default}; diff --git a/assets/guide_incus_incus_precheck.md.6bf5b424.lean.js b/assets/guide_incus_incus_precheck.md.6bf5b424.lean.js deleted file mode 100644 index 747a345f16..0000000000 --- a/assets/guide_incus_incus_precheck.md.6bf5b424.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as i,R as a}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_precheck.md","filePath":"guide/incus/incus_precheck.md","lastUpdated":1747972048000}'),c={name:"guide/incus/incus_precheck.md"},s=a('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/incus

要求

硬件要求:

  • 系统:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu24Debian12,别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换(优先级: btrfs > lvm > zfs > ceph > dir )

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加各种第三方镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像(含自修复镜像)

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',17),r=[s];function l(n,o,p,h,d,u){return t(),i("div",null,r)}const k=e(c,[["render",l]]);export{g as __pageData,k as default}; diff --git a/assets/guide_incus_incus_precheck.md.DTFAD1HQ.js b/assets/guide_incus_incus_precheck.md.DTFAD1HQ.js new file mode 100644 index 0000000000..890c905627 --- /dev/null +++ b/assets/guide_incus_incus_precheck.md.DTFAD1HQ.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as a,ag as c}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_precheck.md","filePath":"guide/incus/incus_precheck.md","lastUpdated":1747984962000}'),s={name:"guide/incus/incus_precheck.md"};function r(n,e,l,o,p,d){return a(),i("div",null,e[0]||(e[0]=[c('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/incus

要求

硬件要求:

  • 系统:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu24Debian12,别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换(优先级: btrfs > lvm > zfs > ceph > dir )

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加各种第三方镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像(含自修复镜像)

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
',17)]))}const b=t(s,[["render",r]]);export{u as __pageData,b as default}; diff --git a/assets/guide_incus_incus_precheck.md.DTFAD1HQ.lean.js b/assets/guide_incus_incus_precheck.md.DTFAD1HQ.lean.js new file mode 100644 index 0000000000..750f5a25db --- /dev/null +++ b/assets/guide_incus_incus_precheck.md.DTFAD1HQ.lean.js @@ -0,0 +1 @@ +import{_ as t,c as i,o as a,ag as c}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_precheck.md","filePath":"guide/incus/incus_precheck.md","lastUpdated":1747984962000}'),s={name:"guide/incus/incus_precheck.md"};function r(n,e,l,o,p,d){return a(),i("div",null,e[0]||(e[0]=[c("",17)]))}const b=t(s,[["render",r]]);export{u as __pageData,b as default}; diff --git a/assets/guide_incus_incus_qa.md.780b508f.js b/assets/guide_incus_incus_qa.md.780b508f.js deleted file mode 100644 index 3e4a223277..0000000000 --- a/assets/guide_incus_incus_qa.md.780b508f.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as s,R as t}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_qa.md","filePath":"guide/incus/incus_qa.md","lastUpdated":1747972048000}'),o={name:"guide/incus/incus_qa.md"},r=t('

解惑

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销款

',13),n=[r];function p(c,i,l,d,u,h){return e(),s("div",null,n)}const g=a(o,[["render",p]]);export{f as __pageData,g as default}; diff --git a/assets/guide_incus_incus_qa.md.780b508f.lean.js b/assets/guide_incus_incus_qa.md.780b508f.lean.js deleted file mode 100644 index 3e4a223277..0000000000 --- a/assets/guide_incus_incus_qa.md.780b508f.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as s,R as t}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_qa.md","filePath":"guide/incus/incus_qa.md","lastUpdated":1747972048000}'),o={name:"guide/incus/incus_qa.md"},r=t('

解惑

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销款

',13),n=[r];function p(c,i,l,d,u,h){return e(),s("div",null,n)}const g=a(o,[["render",p]]);export{f as __pageData,g as default}; diff --git a/assets/guide_incus_incus_qa.md.D2Pi0dJG.js b/assets/guide_incus_incus_qa.md.D2Pi0dJG.js new file mode 100644 index 0000000000..4245655420 --- /dev/null +++ b/assets/guide_incus_incus_qa.md.D2Pi0dJG.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_qa.md","filePath":"guide/incus/incus_qa.md","lastUpdated":1747984962000}'),p={name:"guide/incus/incus_qa.md"};function r(o,e,n,c,d,l){return s(),t("div",null,e[0]||(e[0]=[i('

解惑

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销款

',13)]))}const _=a(p,[["render",r]]);export{h as __pageData,_ as default}; diff --git a/assets/guide_incus_incus_qa.md.D2Pi0dJG.lean.js b/assets/guide_incus_incus_qa.md.D2Pi0dJG.lean.js new file mode 100644 index 0000000000..482fe1c89e --- /dev/null +++ b/assets/guide_incus_incus_qa.md.D2Pi0dJG.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.CSeR4K32.js";const h=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_qa.md","filePath":"guide/incus/incus_qa.md","lastUpdated":1747984962000}'),p={name:"guide/incus/incus_qa.md"};function r(o,e,n,c,d,l){return s(),t("div",null,e[0]||(e[0]=[i("",13)]))}const _=a(p,[["render",r]]);export{h as __pageData,_ as default}; diff --git a/assets/guide_incus_incus_thanks.md.4ec3421d.lean.js b/assets/guide_incus_incus_thanks.md.4ec3421d.lean.js deleted file mode 100644 index 1a6d063033..0000000000 --- a/assets/guide_incus_incus_thanks.md.4ec3421d.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as r,b as e,R as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/incus/incus_thanks.md","filePath":"guide/incus/incus_thanks.md","lastUpdated":1747972048000}'),n={name:"guide/incus/incus_thanks.md"},a=s('

致谢

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10),i=[a];function o(c,p,h,u,l,d){return r(),e("div",null,i)}const b=t(n,[["render",o]]);export{f as __pageData,b as default}; diff --git a/assets/guide_incus_incus_thanks.md.DJw_BEEC.js b/assets/guide_incus_incus_thanks.md.DJw_BEEC.js new file mode 100644 index 0000000000..fd997ec6b7 --- /dev/null +++ b/assets/guide_incus_incus_thanks.md.DJw_BEEC.js @@ -0,0 +1 @@ +import{_ as r,c as e,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/incus/incus_thanks.md","filePath":"guide/incus/incus_thanks.md","lastUpdated":1747984962000}'),a={name:"guide/incus/incus_thanks.md"};function o(i,t,c,p,u,l){return n(),e("div",null,t[0]||(t[0]=[s('

致谢

https://github.com/lxc/lxd

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://github.com/zabbly/incus

',10)]))}const g=r(a,[["render",o]]);export{d as __pageData,g as default}; diff --git a/assets/guide_incus_incus_thanks.md.DJw_BEEC.lean.js b/assets/guide_incus_incus_thanks.md.DJw_BEEC.lean.js new file mode 100644 index 0000000000..83347ad478 --- /dev/null +++ b/assets/guide_incus_incus_thanks.md.DJw_BEEC.lean.js @@ -0,0 +1 @@ +import{_ as r,c as e,o as n,ag as s}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/incus/incus_thanks.md","filePath":"guide/incus/incus_thanks.md","lastUpdated":1747984962000}'),a={name:"guide/incus/incus_thanks.md"};function o(i,t,c,p,u,l){return n(),e("div",null,t[0]||(t[0]=[s("",10)]))}const g=r(a,[["render",o]]);export{d as __pageData,g as default}; diff --git a/assets/guide_incus_incus_windows.md.5ba7b2ce.js b/assets/guide_incus_incus_windows.md.5ba7b2ce.js deleted file mode 100644 index cecb2a4511..0000000000 --- a/assets/guide_incus_incus_windows.md.5ba7b2ce.js +++ /dev/null @@ -1,28 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const p="/assets/win1.7d3fc058.png",o="/assets/win2.72bb0e48.jpg",e="/assets/win3.442eb15f.jpg",t="/assets/wintj.56bef513.jpg",c="/assets/wincf.76927350.jpg",r="/assets/win4.75bd03c1.jpg",i="/assets/win5.58c1b996.jpg",C="/assets/win7.854d0e0a.jpg",y="/assets/win6.f4215c61.jpg",_=JSON.parse('{"title":"在 Incus 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_windows.md","filePath":"guide/incus/incus_windows.md","lastUpdated":1747972048000}'),D={name:"guide/incus/incus_windows.md"},A=l(`

在 Incus 中运行 Windows 虚拟机

检查 Incus 驱动

确保 incus info 输出中含有 qemu,否则无法创建 VM:

shell
incus info | grep -i driver:

若显示只有 lxc,则incus的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root 目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

支持修补的Windows镜像版本:https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.incus.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screentmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
# 初始化空 VM
-incus init winvm --empty --vm
-
-# 调整根盘大小、CPU、内存
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
-
-# 添加 TPM 设备(Secure Boot/BitLocker 支持)
-incus config device add winvm vtpm tpm path=/dev/tpm0
-
-# 挂载安装 ISO,设为第一启动项
-incus config device add winvm install disk \\
-  source=/root/win.incus.iso \\
-  boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
incus start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示Zabbly的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用incus list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,incus将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后incus delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
incus config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',60),d=[A];function u(h,E,m,F,g,w){return a(),n("div",null,d)}const v=s(D,[["render",u]]);export{_ as __pageData,v as default}; diff --git a/assets/guide_incus_incus_windows.md.5ba7b2ce.lean.js b/assets/guide_incus_incus_windows.md.5ba7b2ce.lean.js deleted file mode 100644 index cecb2a4511..0000000000 --- a/assets/guide_incus_incus_windows.md.5ba7b2ce.lean.js +++ /dev/null @@ -1,28 +0,0 @@ -import{_ as s,v as a,b as n,R as l}from"./chunks/framework.70afa331.js";const p="/assets/win1.7d3fc058.png",o="/assets/win2.72bb0e48.jpg",e="/assets/win3.442eb15f.jpg",t="/assets/wintj.56bef513.jpg",c="/assets/wincf.76927350.jpg",r="/assets/win4.75bd03c1.jpg",i="/assets/win5.58c1b996.jpg",C="/assets/win7.854d0e0a.jpg",y="/assets/win6.f4215c61.jpg",_=JSON.parse('{"title":"在 Incus 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_windows.md","filePath":"guide/incus/incus_windows.md","lastUpdated":1747972048000}'),D={name:"guide/incus/incus_windows.md"},A=l(`

在 Incus 中运行 Windows 虚拟机

检查 Incus 驱动

确保 incus info 输出中含有 qemu,否则无法创建 VM:

shell
incus info | grep -i driver:

若显示只有 lxc,则incus的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root 目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

支持修补的Windows镜像版本:https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.incus.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screentmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
# 初始化空 VM
-incus init winvm --empty --vm
-
-# 调整根盘大小、CPU、内存
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
-
-# 添加 TPM 设备(Secure Boot/BitLocker 支持)
-incus config device add winvm vtpm tpm path=/dev/tpm0
-
-# 挂载安装 ISO,设为第一启动项
-incus config device add winvm install disk \\
-  source=/root/win.incus.iso \\
-  boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
incus start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示Zabbly的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用incus list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,incus将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后incus delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
incus config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',60),d=[A];function u(h,E,m,F,g,w){return a(),n("div",null,d)}const v=s(D,[["render",u]]);export{_ as __pageData,v as default}; diff --git a/assets/guide_incus_incus_windows.md.CFcsS3lD.js b/assets/guide_incus_incus_windows.md.CFcsS3lD.js new file mode 100644 index 0000000000..84fbf419a8 --- /dev/null +++ b/assets/guide_incus_incus_windows.md.CFcsS3lD.js @@ -0,0 +1,28 @@ +import{_ as i,c as a,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/win1.BYIcp55m.png",l="/assets/win2.BNn7RQzT.jpg",h="/assets/win3.BgsODJcQ.jpg",e="/assets/wintj.tP8uDOfH.jpg",k="/assets/wincf.B_Jc2M1G.jpg",d="/assets/win4.DwKt_Ood.jpg",F="/assets/win5.BSQ3T_9y.jpg",r="/assets/win7.xhBfJRvu.jpg",o="/assets/win6.B-575Zc1.jpg",b=JSON.parse('{"title":"在 Incus 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_windows.md","filePath":"guide/incus/incus_windows.md","lastUpdated":1747984962000}'),c={name:"guide/incus/incus_windows.md"};function g(y,s,C,u,B,E){return n(),a("div",null,s[0]||(s[0]=[t(`

在 Incus 中运行 Windows 虚拟机

检查 Incus 驱动

确保 incus info 输出中含有 qemu,否则无法创建 VM:

shell
incus info | grep -i driver:

若显示只有 lxc,则incus的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root 目录下按顺序执行以下命令:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install distrobuilder --classic
+# 重启加载一些配置
+reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

支持修补的Windows镜像版本:https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+distrobuilder repack-windows \\
+  --windows-arch=amd64 \\
+  win.iso \\
+  win.incus.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screentmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
# 初始化空 VM
+incus init winvm --empty --vm
+
+# 调整根盘大小、CPU、内存
+incus config device override winvm root size=30GiB
+incus config set winvm limits.cpu=3
+incus config set winvm limits.memory=5GiB
+
+# 添加 TPM 设备(Secure Boot/BitLocker 支持)
+incus config device add winvm vtpm tpm path=/dev/tpm0
+
+# 挂载安装 ISO,设为第一启动项
+incus config device add winvm install disk \\
+  source=/root/win.incus.iso \\
+  boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
+apt install -y spice-html5 websockify lsof

启动虚拟机

shell
incus start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示Zabbly的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用incus list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
incus stop winvm
+incus config device remove winvm install
+incus start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,incus将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后incus delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
incus config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',60)]))}const v=i(c,[["render",g]]);export{b as __pageData,v as default}; diff --git a/assets/guide_incus_incus_windows.md.CFcsS3lD.lean.js b/assets/guide_incus_incus_windows.md.CFcsS3lD.lean.js new file mode 100644 index 0000000000..f38e6975ab --- /dev/null +++ b/assets/guide_incus_incus_windows.md.CFcsS3lD.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/win1.BYIcp55m.png",l="/assets/win2.BNn7RQzT.jpg",h="/assets/win3.BgsODJcQ.jpg",e="/assets/wintj.tP8uDOfH.jpg",k="/assets/wincf.B_Jc2M1G.jpg",d="/assets/win4.DwKt_Ood.jpg",F="/assets/win5.BSQ3T_9y.jpg",r="/assets/win7.xhBfJRvu.jpg",o="/assets/win6.B-575Zc1.jpg",b=JSON.parse('{"title":"在 Incus 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/incus/incus_windows.md","filePath":"guide/incus/incus_windows.md","lastUpdated":1747984962000}'),c={name:"guide/incus/incus_windows.md"};function g(y,s,C,u,B,E){return n(),a("div",null,s[0]||(s[0]=[t("",60)]))}const v=i(c,[["render",g]]);export{b as __pageData,v as default}; diff --git a/assets/guide_lxd_lxd_custom.md.20323fda.js b/assets/guide_lxd_lxd_custom.md.20323fda.js deleted file mode 100644 index 8b262a3ae5..0000000000 --- a/assets/guide_lxd_lxd_custom.md.20323fda.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const t="/assets/lxd1.78537e30.png",l="/assets/lxd2.da10b5ec.png",p="/assets/lxd3.917f56de.png",o="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",c="/assets/lxd6.572825bf.png",r="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",C="/assets/lxd11.b83f953c.png",g="/assets/lxd12.0da335dd.png",y="/assets/lxd13.308fe0de.png",A="/assets/lxd14.8dbfdcd6.png",m="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",v="/assets/lxd17.d7ea65d8.png",f="/assets/lxd18.d6225daa.png",k="/assets/lxd19.69674669.png",D="/assets/lxd20.179fc6e1.png",P="/assets/lxd21.48123d6a.png",_="/assets/lxd22.4386597e.png",w="/assets/lxd23.c26427e3.png",U=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_custom.md","filePath":"guide/lxd/lxd_custom.md","lastUpdated":1747972048000}'),I={name:"guide/lxd/lxd_custom.md"},x=n(`

自定义

给lxd启用官方的web面板

给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如LXD的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',197),q=[x];function V(E,W,O,F,S,G){return a(),e("div",null,q)}const K=s(I,[["render",V]]);export{U as __pageData,K as default}; diff --git a/assets/guide_lxd_lxd_custom.md.20323fda.lean.js b/assets/guide_lxd_lxd_custom.md.20323fda.lean.js deleted file mode 100644 index 8b262a3ae5..0000000000 --- a/assets/guide_lxd_lxd_custom.md.20323fda.lean.js +++ /dev/null @@ -1,80 +0,0 @@ -import{_ as s,v as a,b as e,R as n}from"./chunks/framework.70afa331.js";const t="/assets/lxd1.78537e30.png",l="/assets/lxd2.da10b5ec.png",p="/assets/lxd3.917f56de.png",o="/assets/lxd4.83a1a121.png",i="/assets/lxd5.4ebc1444.png",c="/assets/lxd6.572825bf.png",r="/assets/lxd7.b73982c7.png",d="/assets/lxd8.9fcc21e5.png",h="/assets/lxd9.00250a32.png",u="/assets/lxd10.a25a745c.png",C="/assets/lxd11.b83f953c.png",g="/assets/lxd12.0da335dd.png",y="/assets/lxd13.308fe0de.png",A="/assets/lxd14.8dbfdcd6.png",m="/assets/lxd15.70114933.png",b="/assets/lxd16.a595fa36.png",v="/assets/lxd17.d7ea65d8.png",f="/assets/lxd18.d6225daa.png",k="/assets/lxd19.69674669.png",D="/assets/lxd20.179fc6e1.png",P="/assets/lxd21.48123d6a.png",_="/assets/lxd22.4386597e.png",w="/assets/lxd23.c26427e3.png",U=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_custom.md","filePath":"guide/lxd/lxd_custom.md","lastUpdated":1747972048000}'),I={name:"guide/lxd/lxd_custom.md"},x=n(`

自定义

给lxd启用官方的web面板

给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如LXD的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',197),q=[x];function V(E,W,O,F,S,G){return a(),e("div",null,q)}const K=s(I,[["render",V]]);export{U as __pageData,K as default}; diff --git a/assets/guide_lxd_lxd_custom.md.gEdxHFHM.js b/assets/guide_lxd_lxd_custom.md.gEdxHFHM.js new file mode 100644 index 0000000000..19e9e3f6f9 --- /dev/null +++ b/assets/guide_lxd_lxd_custom.md.gEdxHFHM.js @@ -0,0 +1,80 @@ +import{_ as s,c as e,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxd1.CbGLa5s4.png",i="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",o="/assets/lxd4.CSfRHLxz.png",c="/assets/lxd5.WUJi0qzd.png",d="/assets/lxd6.Cnds779U.png",r="/assets/lxd7.EJ0s1ls2.png",h="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",b="/assets/lxd11.D6E5sVW2.png",v="/assets/lxd12.B9udKIzn.png",m="/assets/lxd13.Dwv7xBpz.png",k="/assets/lxd14.Whdz6cP-.png",f="/assets/lxd15.BjW7LbDr.png",y="/assets/lxd16.CgeIdYJ2.png",P="/assets/lxd17.CWPY1pea.png",_="/assets/lxd18.DqnpcYcL.png",w="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",C="/assets/lxd21.w-R0l00Y.png",I="/assets/lxd22.45M-VX6J.png",q="/assets/lxd23.CLaVW0qk.png",F=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_custom.md","filePath":"guide/lxd/lxd_custom.md","lastUpdated":1747984962000}'),V={name:"guide/lxd/lxd_custom.md"};function W(E,a,A,D,O,T){return n(),e("div",null,a[0]||(a[0]=[t(`

自定义

给lxd启用官方的web面板

给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
+systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如LXD的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
+EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
+ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
+Client IPv4
+Server IPv6
+Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
+ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
+ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
+apt update -y
+
+# 安装 WireGuard 运行依赖
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# 安装 WireGuard 协议兼容的工具集合
+apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
+yum update -y
+
+# 安装额外包组件
+yum install -y epel-release 
+
+# 安装 WireGuard 运行依赖
+yum install -y net-tools
+
+# 安装 WireGuard 协议兼容的工具集合
+yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
+sed -i '/^precedence \\:\\:ffff\\:0\\:0/d;/^label 2002\\:\\:\\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
+wg-quick up warp
+
+# 查看 IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# 查看 IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# 测试成功后断开 Warp 连接
+wg-quick down warp
+
+# 重新连接并设置进程守护,以便重启后自动生效
+systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

',197)]))}const B=s(V,[["render",W]]);export{F as __pageData,B as default}; diff --git a/assets/guide_lxd_lxd_custom.md.gEdxHFHM.lean.js b/assets/guide_lxd_lxd_custom.md.gEdxHFHM.lean.js new file mode 100644 index 0000000000..3bc84dabef --- /dev/null +++ b/assets/guide_lxd_lxd_custom.md.gEdxHFHM.lean.js @@ -0,0 +1 @@ +import{_ as s,c as e,o as n,ag as t}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxd1.CbGLa5s4.png",i="/assets/lxd2.C4eWfnaM.png",l="/assets/lxd3.tQBNiKQo.png",o="/assets/lxd4.CSfRHLxz.png",c="/assets/lxd5.WUJi0qzd.png",d="/assets/lxd6.Cnds779U.png",r="/assets/lxd7.EJ0s1ls2.png",h="/assets/lxd8.DAOueoww.png",u="/assets/lxd9.Dgmw4lpJ.png",g="/assets/lxd10.BjQ0l1K7.png",b="/assets/lxd11.D6E5sVW2.png",v="/assets/lxd12.B9udKIzn.png",m="/assets/lxd13.Dwv7xBpz.png",k="/assets/lxd14.Whdz6cP-.png",f="/assets/lxd15.BjW7LbDr.png",y="/assets/lxd16.CgeIdYJ2.png",P="/assets/lxd17.CWPY1pea.png",_="/assets/lxd18.DqnpcYcL.png",w="/assets/lxd19.B9_MB265.png",x="/assets/lxd20.rK3P3TT8.png",C="/assets/lxd21.w-R0l00Y.png",I="/assets/lxd22.45M-VX6J.png",q="/assets/lxd23.CLaVW0qk.png",F=JSON.parse('{"title":"自定义","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_custom.md","filePath":"guide/lxd/lxd_custom.md","lastUpdated":1747984962000}'),V={name:"guide/lxd/lxd_custom.md"};function W(E,a,A,D,O,T){return n(),e("div",null,a[0]||(a[0]=[t("",197)]))}const B=s(V,[["render",W]]);export{F as __pageData,B as default}; diff --git a/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.js b/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.js new file mode 100644 index 0000000000..8409d89b57 --- /dev/null +++ b/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.js @@ -0,0 +1,16 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_extra_config.md","filePath":"guide/lxd/lxd_extra_config.md","lastUpdated":1747984962000}'),h={name:"guide/lxd/lxd_extra_config.md"};function n(e,s,p,k,d,F){return t(),a("div",null,s[0]||(s[0]=[l(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为LXD创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

一键安装开lxd宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

一键启用官方可视化操作的面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
sudo snap refresh lxd --channel=latest/stable
+snap set lxd ui.enable=true
+lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
+systemctl reload snap.lxd.daemon
+snap restart --reload lxd

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

一键安装宿主机第三方可视化操作的面板

  • (非必须,该面板只是为了方便可视化操作,没有也没问题)
  • 原作者仓库:跳转
shell
lxc config set core.https_address [::]
+lxc config set core.trust_password your_password
+snap install lxdmosaic

安装完毕后打开宿主机IP地址,按照提示设置admin的密码,其他一路默认就能使用面板了

`,37)]))}const g=i(h,[["render",n]]);export{c as __pageData,g as default}; diff --git a/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.lean.js b/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.lean.js new file mode 100644 index 0000000000..057279bd8b --- /dev/null +++ b/assets/guide_lxd_lxd_extra_config.md.DhbmRlmf.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_extra_config.md","filePath":"guide/lxd/lxd_extra_config.md","lastUpdated":1747984962000}'),h={name:"guide/lxd/lxd_extra_config.md"};function n(e,s,p,k,d,F){return t(),a("div",null,s[0]||(s[0]=[l("",37)]))}const g=i(h,[["render",n]]);export{c as __pageData,g as default}; diff --git a/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.js b/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.js deleted file mode 100644 index 4e33a471b1..0000000000 --- a/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.js +++ /dev/null @@ -1,16 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_extra_config.md","filePath":"guide/lxd/lxd_extra_config.md","lastUpdated":1747972048000}'),p={name:"guide/lxd/lxd_extra_config.md"},o=n(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为LXD创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开lxd宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

一键启用官方可视化操作的面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

一键安装宿主机第三方可视化操作的面板

  • (非必须,该面板只是为了方便可视化操作,没有也没问题)
  • 原作者仓库:跳转
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

安装完毕后打开宿主机IP地址,按照提示设置admin的密码,其他一路默认就能使用面板了

`,37),e=[o];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.lean.js b/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.lean.js deleted file mode 100644 index 4e33a471b1..0000000000 --- a/assets/guide_lxd_lxd_extra_config.md.c1ea1bc8.lean.js +++ /dev/null @@ -1,16 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"其他自定义配置","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_extra_config.md","filePath":"guide/lxd/lxd_extra_config.md","lastUpdated":1747972048000}'),p={name:"guide/lxd/lxd_extra_config.md"},o=n(`

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为LXD创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开lxd宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

一键启用官方可视化操作的面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

一键安装宿主机第三方可视化操作的面板

  • (非必须,该面板只是为了方便可视化操作,没有也没问题)
  • 原作者仓库:跳转
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

安装完毕后打开宿主机IP地址,按照提示设置admin的密码,其他一路默认就能使用面板了

`,37),e=[o];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_lxd_lxd_install.md.8dc77da5.js b/assets/guide_lxd_lxd_install.md.8dc77da5.js deleted file mode 100644 index 2d898afe27..0000000000 --- a/assets/guide_lxd_lxd_install.md.8dc77da5.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const n="/assets/lxdd1.433ff357.png",o="/assets/lxdd2.6a93138a.png",e="/assets/lxdd3.f56cf598.png",t="/assets/lxdd4.28d80b71.png",c="/assets/lxdd0.b1d6b8bc.png",F=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_install.md","filePath":"guide/lxd/lxd_install.md","lastUpdated":1747972048000}'),r={name:"guide/lxd/lxd_install.md"},C=p('

LXD

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

LXD主体安装

WARNING

如果是全新的服务器,务必保证apt updateapt install curl都无问题再执行本脚本。

  • 环境要求:Ubuntu 18+(推荐20.04以上),Debian 8+(推荐11以上)
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

shell
bash lxdinstall.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

WARNING

如果你需要在一台服务器上开启超过200个LXD容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

安装WEB控制面板

自定义 教程中有关于官方面板怎么启用的教程,但这里不选择使用官方的面板,因为官方面板为了安全性,牺牲了很多用户体验,这块使用

https://github.com/turtle0x1/LxdMosaic

的第三方面板

shell
sudo snap install lxdmosaic

直接进行一键安装,然后打开当前宿主机的https://<公网IP地址>/,强制访问,就能进入设置页面

lxd

lxd

lxd

这块如果你需要设置网站名字可以改改

lxd

聊胜于无只能说,没有RBAC权限控制进行分用户隔离

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装LXD

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

如果上面的命令中出现下面的错误

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

使用命令修补后再进行lxd的安装

snap install core

如果无异常,上面三行命令执行结果如下

图片

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

测试lxc有没有软连接上

lxc -h

如果报错则执行以下命令软连接lxc命令

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

连接后再测试lxc命令是否有报错找不到

`,54),i=[C];function y(d,D,A,h,u,m){return a(),l("div",null,i)}const b=s(r,[["render",y]]);export{F as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_install.md.8dc77da5.lean.js b/assets/guide_lxd_lxd_install.md.8dc77da5.lean.js deleted file mode 100644 index 2d898afe27..0000000000 --- a/assets/guide_lxd_lxd_install.md.8dc77da5.lean.js +++ /dev/null @@ -1,6 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const n="/assets/lxdd1.433ff357.png",o="/assets/lxdd2.6a93138a.png",e="/assets/lxdd3.f56cf598.png",t="/assets/lxdd4.28d80b71.png",c="/assets/lxdd0.b1d6b8bc.png",F=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_install.md","filePath":"guide/lxd/lxd_install.md","lastUpdated":1747972048000}'),r={name:"guide/lxd/lxd_install.md"},C=p('

LXD

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

LXD主体安装

WARNING

如果是全新的服务器,务必保证apt updateapt install curl都无问题再执行本脚本。

  • 环境要求:Ubuntu 18+(推荐20.04以上),Debian 8+(推荐11以上)
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

shell
bash lxdinstall.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

WARNING

如果你需要在一台服务器上开启超过200个LXD容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

安装WEB控制面板

自定义 教程中有关于官方面板怎么启用的教程,但这里不选择使用官方的面板,因为官方面板为了安全性,牺牲了很多用户体验,这块使用

https://github.com/turtle0x1/LxdMosaic

的第三方面板

shell
sudo snap install lxdmosaic

直接进行一键安装,然后打开当前宿主机的https://<公网IP地址>/,强制访问,就能进入设置页面

lxd

lxd

lxd

这块如果你需要设置网站名字可以改改

lxd

聊胜于无只能说,没有RBAC权限控制进行分用户隔离

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装LXD

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

如果上面的命令中出现下面的错误

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

使用命令修补后再进行lxd的安装

snap install core

如果无异常,上面三行命令执行结果如下

图片

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

测试lxc有没有软连接上

lxc -h

如果报错则执行以下命令软连接lxc命令

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

连接后再测试lxc命令是否有报错找不到

`,54),i=[C];function y(d,D,A,h,u,m){return a(),l("div",null,i)}const b=s(r,[["render",y]]);export{F as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_install.md.D4zH3hWU.js b/assets/guide_lxd_lxd_install.md.D4zH3hWU.js new file mode 100644 index 0000000000..a21cd22ac1 --- /dev/null +++ b/assets/guide_lxd_lxd_install.md.D4zH3hWU.js @@ -0,0 +1,6 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxdd1.CVTAIewh.png",h="/assets/lxdd2.C_mYE7sL.png",n="/assets/lxdd3.DZ2Na5-t.png",e="/assets/lxdd4.CO1I1FPh.png",d="/assets/lxdd0.QoEngFSd.png",C=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_install.md","filePath":"guide/lxd/lxd_install.md","lastUpdated":1747984962000}'),k={name:"guide/lxd/lxd_install.md"};function r(c,s,o,g,F,u){return t(),a("div",null,s[0]||(s[0]=[l('

LXD

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

LXD主体安装

WARNING

如果是全新的服务器,务必保证apt updateapt install curl都无问题再执行本脚本。

  • 环境要求:Ubuntu 18+(推荐20.04以上),Debian 8+(推荐11以上)
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

shell
bash lxdinstall.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

WARNING

如果你需要在一台服务器上开启超过200个LXD容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

安装WEB控制面板

自定义 教程中有关于官方面板怎么启用的教程,但这里不选择使用官方的面板,因为官方面板为了安全性,牺牲了很多用户体验,这块使用

https://github.com/turtle0x1/LxdMosaic

的第三方面板

shell
sudo snap install lxdmosaic

直接进行一键安装,然后打开当前宿主机的https://<公网IP地址>/,强制访问,就能进入设置页面

lxd

lxd

lxd

这块如果你需要设置网站名字可以改改

lxd

聊胜于无只能说,没有RBAC权限控制进行分用户隔离

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装LXD

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

apt install snapd -y
+snap install lxd
+/snap/bin/lxd init

如果上面的命令中出现下面的错误

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

使用命令修补后再进行lxd的安装

snap install core

如果无异常,上面三行命令执行结果如下

图片

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

测试lxc有没有软连接上

lxc -h

如果报错则执行以下命令软连接lxc命令

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

连接后再测试lxc命令是否有报错找不到

`,54)]))}const b=i(k,[["render",r]]);export{C as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_install.md.D4zH3hWU.lean.js b/assets/guide_lxd_lxd_install.md.D4zH3hWU.lean.js new file mode 100644 index 0000000000..7d91a43c88 --- /dev/null +++ b/assets/guide_lxd_lxd_install.md.D4zH3hWU.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const p="/assets/lxdd1.CVTAIewh.png",h="/assets/lxdd2.C_mYE7sL.png",n="/assets/lxdd3.DZ2Na5-t.png",e="/assets/lxdd4.CO1I1FPh.png",d="/assets/lxdd0.QoEngFSd.png",C=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_install.md","filePath":"guide/lxd/lxd_install.md","lastUpdated":1747984962000}'),k={name:"guide/lxd/lxd_install.md"};function r(c,s,o,g,F,u){return t(),a("div",null,s[0]||(s[0]=[l("",54)]))}const b=i(k,[["render",r]]);export{C as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_lxc.md.728ada33.js b/assets/guide_lxd_lxd_lxc.md.728ada33.js deleted file mode 100644 index 5774e788a7..0000000000 --- a/assets/guide_lxd_lxd_lxc.md.728ada33.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"LXC虚拟化","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_lxc.md","filePath":"guide/lxd/lxd_lxc.md","lastUpdated":1747972048000}'),p={name:"guide/lxd/lxd_lxc.md"},o=n(`

LXC虚拟化

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载开机脚本是非必须的,如果你使用过一键安装LXD的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian12,注意传入参数为系统名字+版本号,如:

  • debian12,debian13
  • ubuntu22,ubuntu24
  • centos8,centos9 (实际都是Stream版本)
  • alpine3.16,alpine3.17,alpine3.18,alpine3.19
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

需要进入容器内部则执行

lxc exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用LXD命令

查看所有

bash
lxc list

查看个例

bash
lxc info 服务器名字

启动个例

bash
lxc start 服务器名字

停止个例

bash
lxc stop 服务器名字

删除个例

bash
lxc delete -f 服务器名字

进入内部

bash
lxc exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,92),e=[o];function t(c,r,C,i,y,A){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_lxd_lxd_lxc.md.728ada33.lean.js b/assets/guide_lxd_lxd_lxc.md.728ada33.lean.js deleted file mode 100644 index 5774e788a7..0000000000 --- a/assets/guide_lxd_lxd_lxc.md.728ada33.lean.js +++ /dev/null @@ -1,25 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const d=JSON.parse('{"title":"LXC虚拟化","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_lxc.md","filePath":"guide/lxd/lxd_lxc.md","lastUpdated":1747972048000}'),p={name:"guide/lxd/lxd_lxc.md"},o=n(`

LXC虚拟化

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载开机脚本是非必须的,如果你使用过一键安装LXD的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian12,注意传入参数为系统名字+版本号,如:

  • debian12,debian13
  • ubuntu22,ubuntu24
  • centos8,centos9 (实际都是Stream版本)
  • alpine3.16,alpine3.17,alpine3.18,alpine3.19
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

需要进入容器内部则执行

lxc exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用LXD命令

查看所有

bash
lxc list

查看个例

bash
lxc info 服务器名字

启动个例

bash
lxc start 服务器名字

停止个例

bash
lxc stop 服务器名字

删除个例

bash
lxc delete -f 服务器名字

进入内部

bash
lxc exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,92),e=[o];function t(c,r,C,i,y,A){return a(),l("div",null,e)}const h=s(p,[["render",t]]);export{d as __pageData,h as default}; diff --git a/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.js b/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.js new file mode 100644 index 0000000000..51711182c5 --- /dev/null +++ b/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.js @@ -0,0 +1,25 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"LXC虚拟化","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_lxc.md","filePath":"guide/lxd/lxd_lxc.md","lastUpdated":1747984962000}'),l={name:"guide/lxd/lxd_lxc.md"};function n(p,s,e,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h(`

LXC虚拟化

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载开机脚本是非必须的,如果你使用过一键安装LXD的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian12,注意传入参数为系统名字+版本号,如:

  • debian12,debian13
  • ubuntu22,ubuntu24
  • centos8,centos9 (实际都是Stream版本)
  • alpine3.16,alpine3.17,alpine3.18,alpine3.19
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

需要进入容器内部则执行

lxc exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
lxc stop test
+lxc delete test
+rm -rf test
+rm -rf test_v6
+ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
+2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用LXD命令

查看所有

bash
lxc list

查看个例

bash
lxc info 服务器名字

启动个例

bash
lxc start 服务器名字

停止个例

bash
lxc stop 服务器名字

删除个例

bash
lxc delete -f 服务器名字

进入内部

bash
lxc exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

`,92)]))}const o=i(l,[["render",n]]);export{c as __pageData,o as default}; diff --git a/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.lean.js b/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.lean.js new file mode 100644 index 0000000000..c17ccf4cfa --- /dev/null +++ b/assets/guide_lxd_lxd_lxc.md.PKqgxyhI.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"LXC虚拟化","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_lxc.md","filePath":"guide/lxd/lxd_lxc.md","lastUpdated":1747984962000}'),l={name:"guide/lxd/lxd_lxc.md"};function n(p,s,e,k,d,r){return t(),a("div",null,s[0]||(s[0]=[h("",92)]))}const o=i(l,[["render",n]]);export{c as __pageData,o as default}; diff --git a/assets/guide_lxd_lxd_precheck.md.42adf95c.js b/assets/guide_lxd_lxd_precheck.md.42adf95c.js deleted file mode 100644 index e0ffabdbf0..0000000000 --- a/assets/guide_lxd_lxd_precheck.md.42adf95c.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as l}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_precheck.md","filePath":"guide/lxd/lxd_precheck.md","lastUpdated":1747972048000}'),i={name:"guide/lxd/lxd_precheck.md"},r=l('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/lxd

要求

硬件要求:

  • 系统:Debian 8+, Ubuntu 18+(推荐20.04)
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu20,Ubuntu别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加清华镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',17),c=[r];function s(o,p,n,d,h,u){return t(),a("div",null,c)}const k=e(i,[["render",s]]);export{g as __pageData,k as default}; diff --git a/assets/guide_lxd_lxd_precheck.md.42adf95c.lean.js b/assets/guide_lxd_lxd_precheck.md.42adf95c.lean.js deleted file mode 100644 index e0ffabdbf0..0000000000 --- a/assets/guide_lxd_lxd_precheck.md.42adf95c.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as t,b as a,R as l}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_precheck.md","filePath":"guide/lxd/lxd_precheck.md","lastUpdated":1747972048000}'),i={name:"guide/lxd/lxd_precheck.md"},r=l('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/lxd

要求

硬件要求:

  • 系统:Debian 8+, Ubuntu 18+(推荐20.04)
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu20,Ubuntu别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加清华镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',17),c=[r];function s(o,p,n,d,h,u){return t(),a("div",null,c)}const k=e(i,[["render",s]]);export{g as __pageData,k as default}; diff --git a/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.js b/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.js new file mode 100644 index 0000000000..4e129d5930 --- /dev/null +++ b/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as i,ag as l}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_precheck.md","filePath":"guide/lxd/lxd_precheck.md","lastUpdated":1747984962000}'),r={name:"guide/lxd/lxd_precheck.md"};function c(p,e,o,s,n,d){return i(),a("div",null,e[0]||(e[0]=[l('

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/lxd

要求

硬件要求:

  • 系统:Debian 8+, Ubuntu 18+(推荐20.04)
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu20,Ubuntu别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加清华镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
',17)]))}const b=t(r,[["render",c]]);export{u as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.lean.js b/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.lean.js new file mode 100644 index 0000000000..d5db04bb5d --- /dev/null +++ b/assets/guide_lxd_lxd_precheck.md.BDmkuKzJ.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as i,ag as l}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_precheck.md","filePath":"guide/lxd/lxd_precheck.md","lastUpdated":1747984962000}'),r={name:"guide/lxd/lxd_precheck.md"};function c(p,e,o,s,n,d){return i(),a("div",null,e[0]||(e[0]=[l("",17)]))}const b=t(r,[["render",c]]);export{u as __pageData,b as default}; diff --git a/assets/guide_lxd_lxd_qa.md.44833073.js b/assets/guide_lxd_lxd_qa.md.44833073.js deleted file mode 100644 index dace0e6748..0000000000 --- a/assets/guide_lxd_lxd_qa.md.44833073.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as a,v as e,b as s,R as t}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_qa.md","filePath":"guide/lxd/lxd_qa.md","lastUpdated":1747972048000}'),l={name:"guide/lxd/lxd_qa.md"},o=t(`

解惑

如果LXD安装后lxc命令显示找不到怎么办

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

执行这个命令后尝试

lxc -h

看看lxc命令是否已修复

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销

`,18),p=[o];function n(r,c,i,d,u,h){return e(),s("div",null,p)}const m=a(l,[["render",n]]);export{_ as __pageData,m as default}; diff --git a/assets/guide_lxd_lxd_qa.md.44833073.lean.js b/assets/guide_lxd_lxd_qa.md.44833073.lean.js deleted file mode 100644 index dace0e6748..0000000000 --- a/assets/guide_lxd_lxd_qa.md.44833073.lean.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as a,v as e,b as s,R as t}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_qa.md","filePath":"guide/lxd/lxd_qa.md","lastUpdated":1747972048000}'),l={name:"guide/lxd/lxd_qa.md"},o=t(`

解惑

如果LXD安装后lxc命令显示找不到怎么办

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

执行这个命令后尝试

lxc -h

看看lxc命令是否已修复

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销

`,18),p=[o];function n(r,c,i,d,u,h){return e(),s("div",null,p)}const m=a(l,[["render",n]]);export{_ as __pageData,m as default}; diff --git a/assets/guide_lxd_lxd_qa.md.C4FXk4za.js b/assets/guide_lxd_lxd_qa.md.C4FXk4za.js new file mode 100644 index 0000000000..3a41127008 --- /dev/null +++ b/assets/guide_lxd_lxd_qa.md.C4FXk4za.js @@ -0,0 +1,2 @@ +import{_ as e,c as s,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_qa.md","filePath":"guide/lxd/lxd_qa.md","lastUpdated":1747984962000}'),i={name:"guide/lxd/lxd_qa.md"};function o(l,a,n,r,d,c){return t(),s("div",null,a[0]||(a[0]=[p(`

解惑

如果LXD安装后lxc命令显示找不到怎么办

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

执行这个命令后尝试

lxc -h

看看lxc命令是否已修复

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销

`,18)]))}const g=e(i,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_lxd_lxd_qa.md.C4FXk4za.lean.js b/assets/guide_lxd_lxd_qa.md.C4FXk4za.lean.js new file mode 100644 index 0000000000..6b333fafb9 --- /dev/null +++ b/assets/guide_lxd_lxd_qa.md.C4FXk4za.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_qa.md","filePath":"guide/lxd/lxd_qa.md","lastUpdated":1747984962000}'),i={name:"guide/lxd/lxd_qa.md"};function o(l,a,n,r,d,c){return t(),s("div",null,a[0]||(a[0]=[p("",18)]))}const g=e(i,[["render",o]]);export{u as __pageData,g as default}; diff --git a/assets/guide_lxd_lxd_thanks.md.6aebeab6.js b/assets/guide_lxd_lxd_thanks.md.6aebeab6.js deleted file mode 100644 index 4e7c99814d..0000000000 --- a/assets/guide_lxd_lxd_thanks.md.6aebeab6.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as r,b as e,R as a}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/lxd/lxd_thanks.md","filePath":"guide/lxd/lxd_thanks.md","lastUpdated":1747972048000}'),s={name:"guide/lxd/lxd_thanks.md"},n=a('

致谢

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

感谢 @Ella-Alinda @fscarmen 提供的指导

',12),o=[n];function i(p,l,c,h,d,u){return r(),e("div",null,o)}const x=t(s,[["render",i]]);export{g as __pageData,x as default}; diff --git a/assets/guide_lxd_lxd_thanks.md.6aebeab6.lean.js b/assets/guide_lxd_lxd_thanks.md.6aebeab6.lean.js deleted file mode 100644 index 4e7c99814d..0000000000 --- a/assets/guide_lxd_lxd_thanks.md.6aebeab6.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as t,v as r,b as e,R as a}from"./chunks/framework.70afa331.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/lxd/lxd_thanks.md","filePath":"guide/lxd/lxd_thanks.md","lastUpdated":1747972048000}'),s={name:"guide/lxd/lxd_thanks.md"},n=a('

致谢

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

感谢 @Ella-Alinda @fscarmen 提供的指导

',12),o=[n];function i(p,l,c,h,d,u){return r(),e("div",null,o)}const x=t(s,[["render",i]]);export{g as __pageData,x as default}; diff --git a/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.js b/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.js new file mode 100644 index 0000000000..1d7837f40f --- /dev/null +++ b/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.js @@ -0,0 +1 @@ +import{_ as r,c as e,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/lxd/lxd_thanks.md","filePath":"guide/lxd/lxd_thanks.md","lastUpdated":1747984962000}'),s={name:"guide/lxd/lxd_thanks.md"};function o(i,t,l,p,c,d){return a(),e("div",null,t[0]||(t[0]=[n('

致谢

https://github.com/lxc/lxd

https://lxdware.com/

https://discuss.linuxcontainers.org/

https://discuss.linuxcontainers.org/t/how-to-run-docker-inside-lxc-container/13017/4

https://discuss.linuxcontainers.org/t/error-seccomp-notify-not-supported-on-container-start/15038/3

https://discuss.linuxcontainers.org/t/how-do-i-assign-a-public-ipv6-address-to-a-lxc-container/6028

https://github.com/turtle0x1/LxdMosaic

https://openzfs.github.io/openzfs-docs/Getting Started/Debian/index.html

https://github.com/SuperManito/LinuxMirrors

https://images.opsmaru.dev/

感谢 @Ella-Alinda @fscarmen 提供的指导

',12)]))}const f=r(s,[["render",o]]);export{u as __pageData,f as default}; diff --git a/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.lean.js b/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.lean.js new file mode 100644 index 0000000000..38bb4a7731 --- /dev/null +++ b/assets/guide_lxd_lxd_thanks.md.oRZKHNsx.lean.js @@ -0,0 +1 @@ +import{_ as r,c as e,o as a,ag as n}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/lxd/lxd_thanks.md","filePath":"guide/lxd/lxd_thanks.md","lastUpdated":1747984962000}'),s={name:"guide/lxd/lxd_thanks.md"};function o(i,t,l,p,c,d){return a(),e("div",null,t[0]||(t[0]=[n("",12)]))}const f=r(s,[["render",o]]);export{u as __pageData,f as default}; diff --git a/assets/guide_lxd_lxd_windows.md.9b33f709.js b/assets/guide_lxd_lxd_windows.md.9b33f709.js deleted file mode 100644 index 5e37474a2c..0000000000 --- a/assets/guide_lxd_lxd_windows.md.9b33f709.js +++ /dev/null @@ -1,18 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const p="/assets/win1.c8d28bad.png",o="/assets/win2.72bb0e48.jpg",e="/assets/win3.442eb15f.jpg",t="/assets/wintj.56bef513.jpg",c="/assets/wincf.76927350.jpg",r="/assets/win4.75bd03c1.jpg",C="/assets/win5.cacd68cb.jpg",i="/assets/win7.8f856089.jpg",y="/assets/win6.19e58640.jpg",_=JSON.parse('{"title":"在 LXD 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_windows.md","filePath":"guide/lxd/lxd_windows.md","lastUpdated":1747972048000}'),D={name:"guide/lxd/lxd_windows.md"},A=n(`

在 LXD 中运行 Windows 虚拟机

检查 lxd 驱动

确保lxc info输出中含有qemu,否则无法创建VM:

shell
lxc info | grep -i driver:

若显示只有lxc,则lxd的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.lxd.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screen或tmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
lxc start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示三个立方体的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用lxc list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,lxd将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后lxc delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
lxc config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',59),d=[A];function h(E,m,F,g,u,w){return a(),l("div",null,d)}const v=s(D,[["render",h]]);export{_ as __pageData,v as default}; diff --git a/assets/guide_lxd_lxd_windows.md.9b33f709.lean.js b/assets/guide_lxd_lxd_windows.md.9b33f709.lean.js deleted file mode 100644 index 5e37474a2c..0000000000 --- a/assets/guide_lxd_lxd_windows.md.9b33f709.lean.js +++ /dev/null @@ -1,18 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const p="/assets/win1.c8d28bad.png",o="/assets/win2.72bb0e48.jpg",e="/assets/win3.442eb15f.jpg",t="/assets/wintj.56bef513.jpg",c="/assets/wincf.76927350.jpg",r="/assets/win4.75bd03c1.jpg",C="/assets/win5.cacd68cb.jpg",i="/assets/win7.8f856089.jpg",y="/assets/win6.19e58640.jpg",_=JSON.parse('{"title":"在 LXD 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_windows.md","filePath":"guide/lxd/lxd_windows.md","lastUpdated":1747972048000}'),D={name:"guide/lxd/lxd_windows.md"},A=n(`

在 LXD 中运行 Windows 虚拟机

检查 lxd 驱动

确保lxc info输出中含有qemu,否则无法创建VM:

shell
lxc info | grep -i driver:

若显示只有lxc,则lxd的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \\
-  --windows-arch=amd64 \\
-  win.iso \\
-  win.lxd.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screen或tmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
lxc start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示三个立方体的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用lxc list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,lxd将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后lxc delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
lxc config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',59),d=[A];function h(E,m,F,g,u,w){return a(),l("div",null,d)}const v=s(D,[["render",h]]);export{_ as __pageData,v as default}; diff --git a/assets/guide_lxd_lxd_windows.md.CpTtBXvV.js b/assets/guide_lxd_lxd_windows.md.CpTtBXvV.js new file mode 100644 index 0000000000..b3a23d50cb --- /dev/null +++ b/assets/guide_lxd_lxd_windows.md.CpTtBXvV.js @@ -0,0 +1,18 @@ +import{_ as i,c as a,o as l,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.CJKAoRm5.png",p="/assets/win2.BNn7RQzT.jpg",h="/assets/win3.BgsODJcQ.jpg",e="/assets/wintj.tP8uDOfH.jpg",k="/assets/wincf.B_Jc2M1G.jpg",d="/assets/win4.DwKt_Ood.jpg",F="/assets/win5.C8qmMo1u.jpg",r="/assets/win7.CI43Ul0V.jpg",o="/assets/win6.Cx0KdzQb.jpg",b=JSON.parse('{"title":"在 LXD 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_windows.md","filePath":"guide/lxd/lxd_windows.md","lastUpdated":1747984962000}'),c={name:"guide/lxd/lxd_windows.md"};function g(C,s,y,B,u,m){return l(),a("div",null,s[0]||(s[0]=[t(`

在 LXD 中运行 Windows 虚拟机

检查 lxd 驱动

确保lxc info输出中含有qemu,否则无法创建VM:

shell
lxc info | grep -i driver:

若显示只有lxc,则lxd的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root目录下按顺序执行以下命令:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install lxd-imagebuilder --classic --edge
+# 重启加载一些配置
+reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+lxd-imagebuilder repack-windows \\
+  --windows-arch=amd64 \\
+  win.iso \\
+  win.lxd.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screen或tmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
lxc init winvm --vm --empty
+lxc config device override winvm root size=30GiB
+lxc config set winvm limits.cpu=3 limits.memory=5GiB
+lxc config device add winvm vtpm tpm path=/dev/tpm0
+lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
+apt install -y spice-html5 websockify lsof

启动虚拟机

shell
lxc start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://\${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示三个立方体的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用lxc list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
lxc stop winvm
+lxc config device remove winvm install
+lxc start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,lxd将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后lxc delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
lxc config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

',59)]))}const v=i(c,[["render",g]]);export{b as __pageData,v as default}; diff --git a/assets/guide_lxd_lxd_windows.md.CpTtBXvV.lean.js b/assets/guide_lxd_lxd_windows.md.CpTtBXvV.lean.js new file mode 100644 index 0000000000..374a9747a4 --- /dev/null +++ b/assets/guide_lxd_lxd_windows.md.CpTtBXvV.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as l,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/win1.CJKAoRm5.png",p="/assets/win2.BNn7RQzT.jpg",h="/assets/win3.BgsODJcQ.jpg",e="/assets/wintj.tP8uDOfH.jpg",k="/assets/wincf.B_Jc2M1G.jpg",d="/assets/win4.DwKt_Ood.jpg",F="/assets/win5.C8qmMo1u.jpg",r="/assets/win7.CI43Ul0V.jpg",o="/assets/win6.Cx0KdzQb.jpg",b=JSON.parse('{"title":"在 LXD 中运行 Windows 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/lxd/lxd_windows.md","filePath":"guide/lxd/lxd_windows.md","lastUpdated":1747984962000}'),c={name:"guide/lxd/lxd_windows.md"};function g(C,s,y,B,u,m){return l(),a("div",null,s[0]||(s[0]=[t("",59)]))}const v=i(c,[["render",g]]);export{b as __pageData,v as default}; diff --git a/assets/guide_pve_images_readme.md.ZJUoqm_K.js b/assets/guide_pve_images_readme.md.ZJUoqm_K.js new file mode 100644 index 0000000000..fea54f42eb --- /dev/null +++ b/assets/guide_pve_images_readme.md.ZJUoqm_K.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,j as s}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/images/readme.md","filePath":"guide/pve/images/readme.md","lastUpdated":1747984962000}'),d={name:"guide/pve/images/readme.md"};function o(n,e,i,m,p,c){return r(),t("div",null,e[0]||(e[0]=[s("p",null,"暂存图片",-1)]))}const _=a(d,[["render",o]]);export{u as __pageData,_ as default}; diff --git a/assets/guide_pve_images_readme.md.ZJUoqm_K.lean.js b/assets/guide_pve_images_readme.md.ZJUoqm_K.lean.js new file mode 100644 index 0000000000..fea54f42eb --- /dev/null +++ b/assets/guide_pve_images_readme.md.ZJUoqm_K.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,j as s}from"./chunks/framework.CSeR4K32.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/images/readme.md","filePath":"guide/pve/images/readme.md","lastUpdated":1747984962000}'),d={name:"guide/pve/images/readme.md"};function o(n,e,i,m,p,c){return r(),t("div",null,e[0]||(e[0]=[s("p",null,"暂存图片",-1)]))}const _=a(d,[["render",o]]);export{u as __pageData,_ as default}; diff --git a/assets/guide_pve_images_readme.md.e91db2b4.js b/assets/guide_pve_images_readme.md.e91db2b4.js deleted file mode 100644 index 93f818ab0c..0000000000 --- a/assets/guide_pve_images_readme.md.e91db2b4.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,F as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/images/readme.md","filePath":"guide/pve/images/readme.md","lastUpdated":1747972048000}'),d={name:"guide/pve/images/readme.md"},r=s("p",null,"暂存图片",-1),i=[r];function n(o,m,p,_,c,l){return a(),t("div",null,i)}const g=e(d,[["render",n]]);export{f as __pageData,g as default}; diff --git a/assets/guide_pve_images_readme.md.e91db2b4.lean.js b/assets/guide_pve_images_readme.md.e91db2b4.lean.js deleted file mode 100644 index 93f818ab0c..0000000000 --- a/assets/guide_pve_images_readme.md.e91db2b4.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,F as s}from"./chunks/framework.70afa331.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/images/readme.md","filePath":"guide/pve/images/readme.md","lastUpdated":1747972048000}'),d={name:"guide/pve/images/readme.md"},r=s("p",null,"暂存图片",-1),i=[r];function n(o,m,p,_,c,l){return a(),t("div",null,i)}const g=e(d,[["render",n]]);export{f as __pageData,g as default}; diff --git a/assets/guide_pve_pve_android.md.5728ca62.js b/assets/guide_pve_pve_android.md.5728ca62.js deleted file mode 100644 index 33d8b791a5..0000000000 --- a/assets/guide_pve_pve_android.md.5728ca62.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as p,b as e,R as o}from"./chunks/framework.70afa331.js";const a="/assets/a1.662d9415.png",t="/assets/a2.1d7d86db.png",c="/assets/a3.178777a1.png",d="/assets/a4.65c15963.png",r="/assets/a5.01b8514f.png",i="/assets/a6.67efded0.png",n="/assets/a7.b8de9a6c.png",l="/assets/a8.69056d9a.png",m="/assets/a9.d4cc5fc0.png",g="/assets/a10.36860678.png",_="/assets/a11.bbc20080.png",b="/assets/a12.da46fe54.png",h="/assets/a13.b49276aa.png",f="/assets/a14.908480a6.png",u="/assets/a15.9533f30d.png",x="/assets/a16.2257f2d8.png",q="/assets/a17.b57c7755.png",I="/assets/a18.c3a22602.png",O="/assets/a19.1eefd81d.png",P="/assets/a20.24042237.png",C="/assets/a21.2bb37c9a.png",A="/assets/a22.44ab6d75.png",v="/assets/a23.191de0ca.png",k="/assets/a24.d2a9c729.png",G="/assets/a25.3e24d99b.png",V="/assets/a26.2fce6332.png",w="/assets/ar.0d8bb8f3.png",y="/assets/a27.dd61884c.png",F="/assets/a31.6d3a9d85.png",K="/assets/a32.d9973307.png",U="/assets/a33.8b54ce3f.png",D="/assets/a34.07f5cc75.png",B="/assets/a35.78be61d4.png",E="/assets/a36.a36765c2.png",S="/assets/a37.e6740eaa.png",N="/assets/a38.999b4ffb.png",M="/assets/a39.9dac95e1.png",R="/assets/a40.7f5ad4ea.png",L="/assets/a41.bbc5e317.png",T="/assets/a42.de7d1da7.png",W="/assets/a43.e713599d.png",z="/assets/a44.5c4e5e0a.png",j="/assets/a45.2c32612e.png",Q="/assets/b1.c1fdb506.png",$="/assets/b2.519a9bf0.png",Y="/assets/b3.42fd37a2.png",H="/assets/b4.b6d283a7.png",J="/assets/b5.4cd5361f.png",X="/assets/b6.36f0470d.png",Z="/assets/b7.9714bb16.png",ss="/assets/b8.2eb373bf.png",ps="/assets/b9.3f01ffdc.png",es="/assets/b10.52a93636.png",os="/assets/b11.2e525d8d.png",as="/assets/b12.54c3189d.png",ts="/assets/b13.3b3ae784.png",cs="/assets/b14.662b1a1b.png",ds="/assets/b15.0c5536d8.png",rs="/assets/b16.0fbcfcb1.png",is="/assets/b17.4e7429fe.png",ns="/assets/b18.8211f293.png",ls="/assets/b19.2128d0fa.png",ms="/assets/b20.8a62698b.png",gs="/assets/b21.dfe1e8f0.png",_s="/assets/b22.13e3438c.png",bs="/assets/b23.e293a560.png",hs="/assets/b24.23cbc29a.png",fs="/assets/b25.f2c2ebd7.png",us="/assets/b26.b7136167.png",xs="/assets/b27.cc8f8644.png",qs="/assets/b28.2bf4d8b9.png",Is="/assets/b29.8d301c10.png",Os="/assets/b30.a50bc8f3.png",Ps="/assets/b31.4881ca1d.png",Cs="/assets/b32.b857654b.png",As="/assets/b33.1125a81c.png",vs="/assets/b34.2101ce9a.png",ks="/assets/b35.83c5a766.png",Gs="/assets/b36.ea1f048c.png",Vs="/assets/b37.b60405a9.png",ws="/assets/br.bb3418b4.png",ys="/assets/b38.4d73fbe3.png",Fs="/assets/b39.c59ccabe.png",Ks="/assets/b40.c1d0ee00.png",Us="/assets/b41.0c6d7432.png",Ds="/assets/b42.66cc353b.png",Bs="/assets/b43.a775b641.png",Es="/assets/b44.2d540844.png",Ss="/assets/b45.fe0240c6.png",Ns="/assets/b46.f6b9da14.png",Js=JSON.parse('{"title":"Android 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_android.md","filePath":"guide/pve/pve_android.md","lastUpdated":1747972048000}'),Ms={name:"guide/pve/pve_android.md"},Rs=o('

Android 虚拟机

安卓系统镜像下载

Android系统版本9及以前的镜像下载地址:

国际

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

国内

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Android系统版本10及以后的新镜像下载地址:

https://blissos.org/index.html#download

虚拟机开设

以安卓版本9及以前的镜像开设Android虚拟机

本指南以

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

作为示例进行演示

1

模板设置

开设VMID为100的虚拟机选择对应的存储盘

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

Graphic card选择Vmware compatible,其他选项选择默认如图所示

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面

9

系统安装

进入引导后,选择Installation开头的选项

10

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了

11

选择不使用GPT格式

12

显示空白盘后,选择New

13

选择分区类型Primary

14

然后会提示划分多大的空间,默认回车就行,使用全部的空间

15

然后是选择Flags,移动到Bootable后,按回车,直到Flags下方显示Boot

16

然后移动到Write,回车,进行写入

17

这时候会让你确认是否继续,输入yes后回车继续

18

一段进度条跑过后,回到了最初的菜单,选择Quit退出菜单,一切准备就绪了

19

然后这时候回到了UI界面,使用前面初始化好的盘,选择OK按钮回车

20

文件系统按方向键选择ext4类型,选择OK按钮回车

21

确认进行格式化,选择Yes按钮回车

22

确认GRUB引导安装,选择OK按钮回车

23

确认文件系统可读写,选择OK按钮回车

24

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车

25

然后一段时间后进入安卓LOGO界面

26

镜像移除

然后会进入一段黑屏,大概3~5分钟后仍然黑屏的话,宿主机执行qm stop 100,然后开始移除镜像文件

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

ar

然后宿主机再执行qm start 100,然后应该就会进入安卓系统的初始化界面了

系统初始化

初始化界面选择语言,然后点击确定按钮

27

此时回尝试连接WIFI,由于本项目安装的PVE是完全的静态网络配置,直接跳过,稍后再进行设置

31

点击下一步按钮确认设置时间

32

点击取消屏幕保护,确认仍然跳过

33

然后一段时间黑屏后,会出现主屏幕应用的选择,如果等待3~5分钟这个界面仍然没有出现,那么像之前那样重启虚拟机,再进入VNC应该就会显示了

选择Quickstep

34

网络设置

进入桌面,此时需要开始设置网络,左上角点击设置图标

35

出现下拉框,点击按住下拉

36

点击齿轮按钮

37

进入网络和互联网设置

38

左键双击WIFI

39

修改目前识别到的VirtWIFI,右键点击出现选择框后,点击修改网络

40

出现高级选项,点击打开隐藏的选项

41

如图进行对应的网络设置

IP地址 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码 24

默认网关 172.16.1.1

DNS 8.8.8.8144.144.144.144

然后点击保存按钮

42

此时出来后可能仍然未应用设置,点击关闭WIFI后,再启用WIFI,应该就会显示已连接

43

然后退出到主界面,点击谷歌浏览器,尝试打开一个网页

44

可以看到打开本指南的网址无问题,证明网络已联通

45

以安卓版本10及以后的新镜像开设Android虚拟机

本指南以

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

作为示例进行演示

1

模板设置

宿主机需要先执行以下命令安装图形环境依赖

shell
apt install libgl1 libegl1 -y

然后开始创建虚拟机,点击右上角的Create VM按钮,填写VMIDNameResource Pool

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

如果宿主机本身携带有GPU,那么Graphic card选择VirGL GPU

如果宿主机本身不携带GPU,那么Graphic card选择VirtIOVmware compatible

Machine选择q35BIOS选择OVMF (UEFI)启动,EFI Storage选择local

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面。

系统安装

进入引导后,选择Installation结尾的选项

9

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了。

10

选择不使用GPT格式,依然使用cfdisk格式。

11

显示格式选择框,选择gpt

12

显示空白盘后,选择New

13

因为要划分EFI分区,这个盘需要修改大小,不能使用默认大小,数字改成1就行,分配1G硬盘,然后按回车。

14

然后回到了菜单栏,按方向键选择Type,然后回车,给分区选择格式类型

15

按方向键选择第一个选项EFI System,然后回车

16

此时回到菜单栏,页面上半部分就能看到具体的分区大小和格式

17

然后按下方向键,选择下一行空白的分区

18

菜单栏选择New,然后回车

19

这块需要填写分区大小,此时对照右上角选中的空白分区大小一致即可,然后回车。

20

回到菜单栏,选择Write,回车,写入分区。

21

会提示你输入yes进行确认,输入后回车。

22

然后一段进度条跑过,应该会回到菜单栏,选择Quit退出菜单,一切准备就绪了

23

然后这时候回到了UI界面,使用前面初始化好的1GB大小的盘,选择OK按钮回车。

24

文件系统按方向键选择fat32类型,选择OK按钮回车

25

确认不修改名字,选择OK按钮回车

26

确认进行格式化,选择Yes按钮回车

27

然后回到最初的UI栏,选择第二块不是1GB大小的分区,选择OK按钮回车

28

文件系统按方向键选择ext4类型,选择OK按钮回车

29

确认不修改名字,选择OK按钮回车

30

确认进行格式化,选择Yes按钮回车

31

默认不使用额外空间更新,选择No按钮回车

32

确认GRUB2 EFI BootLoader,选择OK按钮回车

33

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车。

34

系统初始化

然后一段时间后进入LOGO界面。

35

再过一段时间,应该就会进入初始的安卓界面了,能看到弹窗和时间,按住左键上划

36

会出现主屏幕应用的选择,选择Quickstep

如果等待3~5分钟这个界面仍然没有出现,那么就重启虚拟机,再进入VNC应该就会显示了

37

镜像移除

出现了安卓的界面后,宿主机执行qm stop 100,然后开始移除镜像文件。

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

br

然后宿主机再执行qm start 100,然后应该就会进入系统的初始界面了。

网络设置

进入桌面,此时需要开始设置网络,图示位置按住左键,上划

38

弹出一堆应用,在里面找到那个叫做Bliss Ethernet Manager的应用,点击并打开

39

IP Assignment点击打开,选择Static类型,点击OK按钮确认

40

IP Address点击打开,填入172.16.1.xxx/24(xxx我写的100,因为这里我的虚拟机VMID是100方便区分),点击OK按钮确认

41

Gateway Address点击打开,填入172.16.1.1,点击OK按钮确认

42

DNS Address点击打开,填入8.8.8.8,点击OK按钮确认

43

然后在应用界面中,点击Interface UpRefresh,然后键盘按exit键退出程序

44

主界面中打开浏览器,验证网络是否畅通

45

可以看到打开本指南无问题,网络畅通

46

',227),Ls=[Rs];function Ts(Ws,zs,js,Qs,$s,Ys){return p(),e("div",null,Ls)}const Xs=s(Ms,[["render",Ts]]);export{Js as __pageData,Xs as default}; diff --git a/assets/guide_pve_pve_android.md.5728ca62.lean.js b/assets/guide_pve_pve_android.md.5728ca62.lean.js deleted file mode 100644 index 33d8b791a5..0000000000 --- a/assets/guide_pve_pve_android.md.5728ca62.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as p,b as e,R as o}from"./chunks/framework.70afa331.js";const a="/assets/a1.662d9415.png",t="/assets/a2.1d7d86db.png",c="/assets/a3.178777a1.png",d="/assets/a4.65c15963.png",r="/assets/a5.01b8514f.png",i="/assets/a6.67efded0.png",n="/assets/a7.b8de9a6c.png",l="/assets/a8.69056d9a.png",m="/assets/a9.d4cc5fc0.png",g="/assets/a10.36860678.png",_="/assets/a11.bbc20080.png",b="/assets/a12.da46fe54.png",h="/assets/a13.b49276aa.png",f="/assets/a14.908480a6.png",u="/assets/a15.9533f30d.png",x="/assets/a16.2257f2d8.png",q="/assets/a17.b57c7755.png",I="/assets/a18.c3a22602.png",O="/assets/a19.1eefd81d.png",P="/assets/a20.24042237.png",C="/assets/a21.2bb37c9a.png",A="/assets/a22.44ab6d75.png",v="/assets/a23.191de0ca.png",k="/assets/a24.d2a9c729.png",G="/assets/a25.3e24d99b.png",V="/assets/a26.2fce6332.png",w="/assets/ar.0d8bb8f3.png",y="/assets/a27.dd61884c.png",F="/assets/a31.6d3a9d85.png",K="/assets/a32.d9973307.png",U="/assets/a33.8b54ce3f.png",D="/assets/a34.07f5cc75.png",B="/assets/a35.78be61d4.png",E="/assets/a36.a36765c2.png",S="/assets/a37.e6740eaa.png",N="/assets/a38.999b4ffb.png",M="/assets/a39.9dac95e1.png",R="/assets/a40.7f5ad4ea.png",L="/assets/a41.bbc5e317.png",T="/assets/a42.de7d1da7.png",W="/assets/a43.e713599d.png",z="/assets/a44.5c4e5e0a.png",j="/assets/a45.2c32612e.png",Q="/assets/b1.c1fdb506.png",$="/assets/b2.519a9bf0.png",Y="/assets/b3.42fd37a2.png",H="/assets/b4.b6d283a7.png",J="/assets/b5.4cd5361f.png",X="/assets/b6.36f0470d.png",Z="/assets/b7.9714bb16.png",ss="/assets/b8.2eb373bf.png",ps="/assets/b9.3f01ffdc.png",es="/assets/b10.52a93636.png",os="/assets/b11.2e525d8d.png",as="/assets/b12.54c3189d.png",ts="/assets/b13.3b3ae784.png",cs="/assets/b14.662b1a1b.png",ds="/assets/b15.0c5536d8.png",rs="/assets/b16.0fbcfcb1.png",is="/assets/b17.4e7429fe.png",ns="/assets/b18.8211f293.png",ls="/assets/b19.2128d0fa.png",ms="/assets/b20.8a62698b.png",gs="/assets/b21.dfe1e8f0.png",_s="/assets/b22.13e3438c.png",bs="/assets/b23.e293a560.png",hs="/assets/b24.23cbc29a.png",fs="/assets/b25.f2c2ebd7.png",us="/assets/b26.b7136167.png",xs="/assets/b27.cc8f8644.png",qs="/assets/b28.2bf4d8b9.png",Is="/assets/b29.8d301c10.png",Os="/assets/b30.a50bc8f3.png",Ps="/assets/b31.4881ca1d.png",Cs="/assets/b32.b857654b.png",As="/assets/b33.1125a81c.png",vs="/assets/b34.2101ce9a.png",ks="/assets/b35.83c5a766.png",Gs="/assets/b36.ea1f048c.png",Vs="/assets/b37.b60405a9.png",ws="/assets/br.bb3418b4.png",ys="/assets/b38.4d73fbe3.png",Fs="/assets/b39.c59ccabe.png",Ks="/assets/b40.c1d0ee00.png",Us="/assets/b41.0c6d7432.png",Ds="/assets/b42.66cc353b.png",Bs="/assets/b43.a775b641.png",Es="/assets/b44.2d540844.png",Ss="/assets/b45.fe0240c6.png",Ns="/assets/b46.f6b9da14.png",Js=JSON.parse('{"title":"Android 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_android.md","filePath":"guide/pve/pve_android.md","lastUpdated":1747972048000}'),Ms={name:"guide/pve/pve_android.md"},Rs=o('

Android 虚拟机

安卓系统镜像下载

Android系统版本9及以前的镜像下载地址:

国际

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

国内

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Android系统版本10及以后的新镜像下载地址:

https://blissos.org/index.html#download

虚拟机开设

以安卓版本9及以前的镜像开设Android虚拟机

本指南以

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

作为示例进行演示

1

模板设置

开设VMID为100的虚拟机选择对应的存储盘

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

Graphic card选择Vmware compatible,其他选项选择默认如图所示

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面

9

系统安装

进入引导后,选择Installation开头的选项

10

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了

11

选择不使用GPT格式

12

显示空白盘后,选择New

13

选择分区类型Primary

14

然后会提示划分多大的空间,默认回车就行,使用全部的空间

15

然后是选择Flags,移动到Bootable后,按回车,直到Flags下方显示Boot

16

然后移动到Write,回车,进行写入

17

这时候会让你确认是否继续,输入yes后回车继续

18

一段进度条跑过后,回到了最初的菜单,选择Quit退出菜单,一切准备就绪了

19

然后这时候回到了UI界面,使用前面初始化好的盘,选择OK按钮回车

20

文件系统按方向键选择ext4类型,选择OK按钮回车

21

确认进行格式化,选择Yes按钮回车

22

确认GRUB引导安装,选择OK按钮回车

23

确认文件系统可读写,选择OK按钮回车

24

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车

25

然后一段时间后进入安卓LOGO界面

26

镜像移除

然后会进入一段黑屏,大概3~5分钟后仍然黑屏的话,宿主机执行qm stop 100,然后开始移除镜像文件

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

ar

然后宿主机再执行qm start 100,然后应该就会进入安卓系统的初始化界面了

系统初始化

初始化界面选择语言,然后点击确定按钮

27

此时回尝试连接WIFI,由于本项目安装的PVE是完全的静态网络配置,直接跳过,稍后再进行设置

31

点击下一步按钮确认设置时间

32

点击取消屏幕保护,确认仍然跳过

33

然后一段时间黑屏后,会出现主屏幕应用的选择,如果等待3~5分钟这个界面仍然没有出现,那么像之前那样重启虚拟机,再进入VNC应该就会显示了

选择Quickstep

34

网络设置

进入桌面,此时需要开始设置网络,左上角点击设置图标

35

出现下拉框,点击按住下拉

36

点击齿轮按钮

37

进入网络和互联网设置

38

左键双击WIFI

39

修改目前识别到的VirtWIFI,右键点击出现选择框后,点击修改网络

40

出现高级选项,点击打开隐藏的选项

41

如图进行对应的网络设置

IP地址 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码 24

默认网关 172.16.1.1

DNS 8.8.8.8144.144.144.144

然后点击保存按钮

42

此时出来后可能仍然未应用设置,点击关闭WIFI后,再启用WIFI,应该就会显示已连接

43

然后退出到主界面,点击谷歌浏览器,尝试打开一个网页

44

可以看到打开本指南的网址无问题,证明网络已联通

45

以安卓版本10及以后的新镜像开设Android虚拟机

本指南以

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

作为示例进行演示

1

模板设置

宿主机需要先执行以下命令安装图形环境依赖

shell
apt install libgl1 libegl1 -y

然后开始创建虚拟机,点击右上角的Create VM按钮,填写VMIDNameResource Pool

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

如果宿主机本身携带有GPU,那么Graphic card选择VirGL GPU

如果宿主机本身不携带GPU,那么Graphic card选择VirtIOVmware compatible

Machine选择q35BIOS选择OVMF (UEFI)启动,EFI Storage选择local

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面。

系统安装

进入引导后,选择Installation结尾的选项

9

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了。

10

选择不使用GPT格式,依然使用cfdisk格式。

11

显示格式选择框,选择gpt

12

显示空白盘后,选择New

13

因为要划分EFI分区,这个盘需要修改大小,不能使用默认大小,数字改成1就行,分配1G硬盘,然后按回车。

14

然后回到了菜单栏,按方向键选择Type,然后回车,给分区选择格式类型

15

按方向键选择第一个选项EFI System,然后回车

16

此时回到菜单栏,页面上半部分就能看到具体的分区大小和格式

17

然后按下方向键,选择下一行空白的分区

18

菜单栏选择New,然后回车

19

这块需要填写分区大小,此时对照右上角选中的空白分区大小一致即可,然后回车。

20

回到菜单栏,选择Write,回车,写入分区。

21

会提示你输入yes进行确认,输入后回车。

22

然后一段进度条跑过,应该会回到菜单栏,选择Quit退出菜单,一切准备就绪了

23

然后这时候回到了UI界面,使用前面初始化好的1GB大小的盘,选择OK按钮回车。

24

文件系统按方向键选择fat32类型,选择OK按钮回车

25

确认不修改名字,选择OK按钮回车

26

确认进行格式化,选择Yes按钮回车

27

然后回到最初的UI栏,选择第二块不是1GB大小的分区,选择OK按钮回车

28

文件系统按方向键选择ext4类型,选择OK按钮回车

29

确认不修改名字,选择OK按钮回车

30

确认进行格式化,选择Yes按钮回车

31

默认不使用额外空间更新,选择No按钮回车

32

确认GRUB2 EFI BootLoader,选择OK按钮回车

33

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车。

34

系统初始化

然后一段时间后进入LOGO界面。

35

再过一段时间,应该就会进入初始的安卓界面了,能看到弹窗和时间,按住左键上划

36

会出现主屏幕应用的选择,选择Quickstep

如果等待3~5分钟这个界面仍然没有出现,那么就重启虚拟机,再进入VNC应该就会显示了

37

镜像移除

出现了安卓的界面后,宿主机执行qm stop 100,然后开始移除镜像文件。

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

br

然后宿主机再执行qm start 100,然后应该就会进入系统的初始界面了。

网络设置

进入桌面,此时需要开始设置网络,图示位置按住左键,上划

38

弹出一堆应用,在里面找到那个叫做Bliss Ethernet Manager的应用,点击并打开

39

IP Assignment点击打开,选择Static类型,点击OK按钮确认

40

IP Address点击打开,填入172.16.1.xxx/24(xxx我写的100,因为这里我的虚拟机VMID是100方便区分),点击OK按钮确认

41

Gateway Address点击打开,填入172.16.1.1,点击OK按钮确认

42

DNS Address点击打开,填入8.8.8.8,点击OK按钮确认

43

然后在应用界面中,点击Interface UpRefresh,然后键盘按exit键退出程序

44

主界面中打开浏览器,验证网络是否畅通

45

可以看到打开本指南无问题,网络畅通

46

',227),Ls=[Rs];function Ts(Ws,zs,js,Qs,$s,Ys){return p(),e("div",null,Ls)}const Xs=s(Ms,[["render",Ts]]);export{Js as __pageData,Xs as default}; diff --git a/assets/guide_pve_pve_android.md.DauuQgmC.js b/assets/guide_pve_pve_android.md.DauuQgmC.js new file mode 100644 index 0000000000..43d1ffe73e --- /dev/null +++ b/assets/guide_pve_pve_android.md.DauuQgmC.js @@ -0,0 +1 @@ +import{_ as p,c as e,o,ag as t}from"./chunks/framework.CSeR4K32.js";const a="/assets/a1.DvgNELwZ.png",c="/assets/a2.BQniQEw_.png",r="/assets/a3.DHUpjnAe.png",d="/assets/a4.BtVJtyBL.png",i="/assets/a5.CamDlEuL.png",n="/assets/a6.auUigeOH.png",l="/assets/a7.3_Is3HF1.png",m="/assets/a8.CkyIulFy.png",g="/assets/a9.Dg58RrTs.png",_="/assets/a10.CPK2ZJEJ.png",h="/assets/a11.Bq6vmveu.png",b="/assets/a12.bStrZLWw.png",u="/assets/a13.DRz8WTJR.png",x="/assets/a14.D56M6gMb.png",f="/assets/a15.CtjmUhal.png",B="/assets/a16.BL0_sgNg.png",k="/assets/a17.B9keXK9k.png",C="/assets/a18.Bu92JFv5.png",I="/assets/a19.DZjr60Xs.png",P="/assets/a20.CesdkIR_.png",F="/assets/a21.BO8sy8n4.png",O="/assets/a22.COjD9r-B.png",q="/assets/a23.BxEEAckp.png",v="/assets/a24.BrCKYLHX.png",D="/assets/a25.CUB6zoiS.png",A="/assets/a26.zvaFRs59.png",w="/assets/ar.Dy_5EjFU.png",G="/assets/a27.QkS9Cjl7.png",K="/assets/a31.BiCzGFMR.png",V="/assets/a32.54sdf1AZ.png",y="/assets/a33.QYBAXO71.png",U="/assets/a34.BBqAz_kr.png",E="/assets/a35.B8NF_iJX.png",S="/assets/a36.CPvsggxV.png",N="/assets/a37.DJRI7pv9.png",R="/assets/a38.BhfuTk-3.png",T="/assets/a39.BNtfZ4xd.png",j="/assets/a40.DTfyEQe2.png",L="/assets/a41.Cb6MjiUm.png",M="/assets/a42.Du63tHI8.png",H="/assets/a43.Cxy9Fqxr.png",J="/assets/a44.Dhcgau_f.png",z="/assets/a45.DQgcLv5f.png",W="/assets/b1.CSqggjTM.png",Q="/assets/b2.BnvPQMj3.png",X="/assets/b3.DPn2dzFl.png",Z="/assets/b4.JBQupWN9.png",Y="/assets/b5.DeuT9J-4.png",$="/assets/b6.cZYHMwJ8.png",ss="/assets/b7.5Fkbt05C.png",ps="/assets/b8.BXlK1Dnb.png",es="/assets/b9.CaK5eLKm.png",os="/assets/b10.DGHfd73s.png",ts="/assets/b11.DKZjwgY8.png",as="/assets/b12.BISDj2Ri.png",cs="/assets/b13.WGr5jMeK.png",rs="/assets/b14.BqBpvoFk.png",ds="/assets/b15.Cd3Rj7ju.png",is="/assets/b16.BR7AHi1X.png",ns="/assets/b17.Cn1C4e1e.png",ls="/assets/b18.ElAa2UCQ.png",ms="/assets/b19.BwC-oHOW.png",gs="/assets/b20.Dj-0rOwy.png",_s="/assets/b21.CYRPkSXE.png",hs="/assets/b22.BH7kRZ3Z.png",bs="/assets/b23.JVX-KOL7.png",us="/assets/b24.a2fv8lkf.png",xs="/assets/b25.BJrNgkiA.png",fs="/assets/b26.5bTO5HK5.png",Bs="/assets/b27.BSRz6moE.png",ks="/assets/b28.WNjJaEPB.png",Cs="/assets/b29.Bs69Ykqp.png",Is="/assets/b30.B96bh_Ou.png",Ps="/assets/b31.BBIAIScF.png",Fs="/assets/b32.8G5Xy9mr.png",Os="/assets/b33.RYxcR7vu.png",qs="/assets/b34.Dw6MyLex.png",vs="/assets/b35.DUCPsVIG.png",Ds="/assets/b36.7aKaNaLh.png",As="/assets/b37.B5CHAJzN.png",ws="/assets/br.CyzpZwsx.png",Gs="/assets/b38.Pnnij22W.png",Ks="/assets/b39.ajiHDdbx.png",Vs="/assets/b40.B6FTkFUT.png",ys="/assets/b41.DcCdod5l.png",Us="/assets/b42.CT1JvTLX.png",Es="/assets/b43.HthhPs5o.png",Ss="/assets/b44.C9NeP-UC.png",Ns="/assets/b45.BWxBBH-l.png",Rs="/assets/b46.B6Ds58im.png",Qs=JSON.parse('{"title":"Android 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_android.md","filePath":"guide/pve/pve_android.md","lastUpdated":1747984962000}'),Ts={name:"guide/pve/pve_android.md"};function js(Ls,s,Ms,Hs,Js,zs){return o(),e("div",null,s[0]||(s[0]=[t('

Android 虚拟机

安卓系统镜像下载

Android系统版本9及以前的镜像下载地址:

国际

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

国内

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Android系统版本10及以后的新镜像下载地址:

https://blissos.org/index.html#download

虚拟机开设

以安卓版本9及以前的镜像开设Android虚拟机

本指南以

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

作为示例进行演示

1

模板设置

开设VMID为100的虚拟机选择对应的存储盘

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

Graphic card选择Vmware compatible,其他选项选择默认如图所示

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面

9

系统安装

进入引导后,选择Installation开头的选项

10

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了

11

选择不使用GPT格式

12

显示空白盘后,选择New

13

选择分区类型Primary

14

然后会提示划分多大的空间,默认回车就行,使用全部的空间

15

然后是选择Flags,移动到Bootable后,按回车,直到Flags下方显示Boot

16

然后移动到Write,回车,进行写入

17

这时候会让你确认是否继续,输入yes后回车继续

18

一段进度条跑过后,回到了最初的菜单,选择Quit退出菜单,一切准备就绪了

19

然后这时候回到了UI界面,使用前面初始化好的盘,选择OK按钮回车

20

文件系统按方向键选择ext4类型,选择OK按钮回车

21

确认进行格式化,选择Yes按钮回车

22

确认GRUB引导安装,选择OK按钮回车

23

确认文件系统可读写,选择OK按钮回车

24

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车

25

然后一段时间后进入安卓LOGO界面

26

镜像移除

然后会进入一段黑屏,大概3~5分钟后仍然黑屏的话,宿主机执行qm stop 100,然后开始移除镜像文件

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

ar

然后宿主机再执行qm start 100,然后应该就会进入安卓系统的初始化界面了

系统初始化

初始化界面选择语言,然后点击确定按钮

27

此时回尝试连接WIFI,由于本项目安装的PVE是完全的静态网络配置,直接跳过,稍后再进行设置

31

点击下一步按钮确认设置时间

32

点击取消屏幕保护,确认仍然跳过

33

然后一段时间黑屏后,会出现主屏幕应用的选择,如果等待3~5分钟这个界面仍然没有出现,那么像之前那样重启虚拟机,再进入VNC应该就会显示了

选择Quickstep

34

网络设置

进入桌面,此时需要开始设置网络,左上角点击设置图标

35

出现下拉框,点击按住下拉

36

点击齿轮按钮

37

进入网络和互联网设置

38

左键双击WIFI

39

修改目前识别到的VirtWIFI,右键点击出现选择框后,点击修改网络

40

出现高级选项,点击打开隐藏的选项

41

如图进行对应的网络设置

IP地址 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码 24

默认网关 172.16.1.1

DNS 8.8.8.8144.144.144.144

然后点击保存按钮

42

此时出来后可能仍然未应用设置,点击关闭WIFI后,再启用WIFI,应该就会显示已连接

43

然后退出到主界面,点击谷歌浏览器,尝试打开一个网页

44

可以看到打开本指南的网址无问题,证明网络已联通

45

以安卓版本10及以后的新镜像开设Android虚拟机

本指南以

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

作为示例进行演示

1

模板设置

宿主机需要先执行以下命令安装图形环境依赖

shell
apt install libgl1 libegl1 -y

然后开始创建虚拟机,点击右上角的Create VM按钮,填写VMIDNameResource Pool

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

如果宿主机本身携带有GPU,那么Graphic card选择VirGL GPU

如果宿主机本身不携带GPU,那么Graphic card选择VirtIOVmware compatible

Machine选择q35BIOS选择OVMF (UEFI)启动,EFI Storage选择local

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面。

系统安装

进入引导后,选择Installation结尾的选项

9

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了。

10

选择不使用GPT格式,依然使用cfdisk格式。

11

显示格式选择框,选择gpt

12

显示空白盘后,选择New

13

因为要划分EFI分区,这个盘需要修改大小,不能使用默认大小,数字改成1就行,分配1G硬盘,然后按回车。

14

然后回到了菜单栏,按方向键选择Type,然后回车,给分区选择格式类型

15

按方向键选择第一个选项EFI System,然后回车

16

此时回到菜单栏,页面上半部分就能看到具体的分区大小和格式

17

然后按下方向键,选择下一行空白的分区

18

菜单栏选择New,然后回车

19

这块需要填写分区大小,此时对照右上角选中的空白分区大小一致即可,然后回车。

20

回到菜单栏,选择Write,回车,写入分区。

21

会提示你输入yes进行确认,输入后回车。

22

然后一段进度条跑过,应该会回到菜单栏,选择Quit退出菜单,一切准备就绪了

23

然后这时候回到了UI界面,使用前面初始化好的1GB大小的盘,选择OK按钮回车。

24

文件系统按方向键选择fat32类型,选择OK按钮回车

25

确认不修改名字,选择OK按钮回车

26

确认进行格式化,选择Yes按钮回车

27

然后回到最初的UI栏,选择第二块不是1GB大小的分区,选择OK按钮回车

28

文件系统按方向键选择ext4类型,选择OK按钮回车

29

确认不修改名字,选择OK按钮回车

30

确认进行格式化,选择Yes按钮回车

31

默认不使用额外空间更新,选择No按钮回车

32

确认GRUB2 EFI BootLoader,选择OK按钮回车

33

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车。

34

系统初始化

然后一段时间后进入LOGO界面。

35

再过一段时间,应该就会进入初始的安卓界面了,能看到弹窗和时间,按住左键上划

36

会出现主屏幕应用的选择,选择Quickstep

如果等待3~5分钟这个界面仍然没有出现,那么就重启虚拟机,再进入VNC应该就会显示了

37

镜像移除

出现了安卓的界面后,宿主机执行qm stop 100,然后开始移除镜像文件。

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

br

然后宿主机再执行qm start 100,然后应该就会进入系统的初始界面了。

网络设置

进入桌面,此时需要开始设置网络,图示位置按住左键,上划

38

弹出一堆应用,在里面找到那个叫做Bliss Ethernet Manager的应用,点击并打开

39

IP Assignment点击打开,选择Static类型,点击OK按钮确认

40

IP Address点击打开,填入172.16.1.xxx/24(xxx我写的100,因为这里我的虚拟机VMID是100方便区分),点击OK按钮确认

41

Gateway Address点击打开,填入172.16.1.1,点击OK按钮确认

42

DNS Address点击打开,填入8.8.8.8,点击OK按钮确认

43

然后在应用界面中,点击Interface UpRefresh,然后键盘按exit键退出程序

44

主界面中打开浏览器,验证网络是否畅通

45

可以看到打开本指南无问题,网络畅通

46

',227)]))}const Xs=p(Ts,[["render",js]]);export{Qs as __pageData,Xs as default}; diff --git a/assets/guide_pve_pve_android.md.DauuQgmC.lean.js b/assets/guide_pve_pve_android.md.DauuQgmC.lean.js new file mode 100644 index 0000000000..9d177160ff --- /dev/null +++ b/assets/guide_pve_pve_android.md.DauuQgmC.lean.js @@ -0,0 +1 @@ +import{_ as p,c as e,o,ag as t}from"./chunks/framework.CSeR4K32.js";const a="/assets/a1.DvgNELwZ.png",c="/assets/a2.BQniQEw_.png",r="/assets/a3.DHUpjnAe.png",d="/assets/a4.BtVJtyBL.png",i="/assets/a5.CamDlEuL.png",n="/assets/a6.auUigeOH.png",l="/assets/a7.3_Is3HF1.png",m="/assets/a8.CkyIulFy.png",g="/assets/a9.Dg58RrTs.png",_="/assets/a10.CPK2ZJEJ.png",h="/assets/a11.Bq6vmveu.png",b="/assets/a12.bStrZLWw.png",u="/assets/a13.DRz8WTJR.png",x="/assets/a14.D56M6gMb.png",f="/assets/a15.CtjmUhal.png",B="/assets/a16.BL0_sgNg.png",k="/assets/a17.B9keXK9k.png",C="/assets/a18.Bu92JFv5.png",I="/assets/a19.DZjr60Xs.png",P="/assets/a20.CesdkIR_.png",F="/assets/a21.BO8sy8n4.png",O="/assets/a22.COjD9r-B.png",q="/assets/a23.BxEEAckp.png",v="/assets/a24.BrCKYLHX.png",D="/assets/a25.CUB6zoiS.png",A="/assets/a26.zvaFRs59.png",w="/assets/ar.Dy_5EjFU.png",G="/assets/a27.QkS9Cjl7.png",K="/assets/a31.BiCzGFMR.png",V="/assets/a32.54sdf1AZ.png",y="/assets/a33.QYBAXO71.png",U="/assets/a34.BBqAz_kr.png",E="/assets/a35.B8NF_iJX.png",S="/assets/a36.CPvsggxV.png",N="/assets/a37.DJRI7pv9.png",R="/assets/a38.BhfuTk-3.png",T="/assets/a39.BNtfZ4xd.png",j="/assets/a40.DTfyEQe2.png",L="/assets/a41.Cb6MjiUm.png",M="/assets/a42.Du63tHI8.png",H="/assets/a43.Cxy9Fqxr.png",J="/assets/a44.Dhcgau_f.png",z="/assets/a45.DQgcLv5f.png",W="/assets/b1.CSqggjTM.png",Q="/assets/b2.BnvPQMj3.png",X="/assets/b3.DPn2dzFl.png",Z="/assets/b4.JBQupWN9.png",Y="/assets/b5.DeuT9J-4.png",$="/assets/b6.cZYHMwJ8.png",ss="/assets/b7.5Fkbt05C.png",ps="/assets/b8.BXlK1Dnb.png",es="/assets/b9.CaK5eLKm.png",os="/assets/b10.DGHfd73s.png",ts="/assets/b11.DKZjwgY8.png",as="/assets/b12.BISDj2Ri.png",cs="/assets/b13.WGr5jMeK.png",rs="/assets/b14.BqBpvoFk.png",ds="/assets/b15.Cd3Rj7ju.png",is="/assets/b16.BR7AHi1X.png",ns="/assets/b17.Cn1C4e1e.png",ls="/assets/b18.ElAa2UCQ.png",ms="/assets/b19.BwC-oHOW.png",gs="/assets/b20.Dj-0rOwy.png",_s="/assets/b21.CYRPkSXE.png",hs="/assets/b22.BH7kRZ3Z.png",bs="/assets/b23.JVX-KOL7.png",us="/assets/b24.a2fv8lkf.png",xs="/assets/b25.BJrNgkiA.png",fs="/assets/b26.5bTO5HK5.png",Bs="/assets/b27.BSRz6moE.png",ks="/assets/b28.WNjJaEPB.png",Cs="/assets/b29.Bs69Ykqp.png",Is="/assets/b30.B96bh_Ou.png",Ps="/assets/b31.BBIAIScF.png",Fs="/assets/b32.8G5Xy9mr.png",Os="/assets/b33.RYxcR7vu.png",qs="/assets/b34.Dw6MyLex.png",vs="/assets/b35.DUCPsVIG.png",Ds="/assets/b36.7aKaNaLh.png",As="/assets/b37.B5CHAJzN.png",ws="/assets/br.CyzpZwsx.png",Gs="/assets/b38.Pnnij22W.png",Ks="/assets/b39.ajiHDdbx.png",Vs="/assets/b40.B6FTkFUT.png",ys="/assets/b41.DcCdod5l.png",Us="/assets/b42.CT1JvTLX.png",Es="/assets/b43.HthhPs5o.png",Ss="/assets/b44.C9NeP-UC.png",Ns="/assets/b45.BWxBBH-l.png",Rs="/assets/b46.B6Ds58im.png",Qs=JSON.parse('{"title":"Android 虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_android.md","filePath":"guide/pve/pve_android.md","lastUpdated":1747984962000}'),Ts={name:"guide/pve/pve_android.md"};function js(Ls,s,Ms,Hs,Js,zs){return o(),e("div",null,s[0]||(s[0]=[t("",227)]))}const Xs=p(Ts,[["render",js]]);export{Qs as __pageData,Xs as default}; diff --git a/assets/guide_pve_pve_custom.md.0uRKiuWM.js b/assets/guide_pve_pve_custom.md.0uRKiuWM.js new file mode 100644 index 0000000000..79d1ccd793 --- /dev/null +++ b/assets/guide_pve_pve_custom.md.0uRKiuWM.js @@ -0,0 +1,30 @@ +import{_ as a,c as i,o as e,ag as p}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"自定义分区","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_custom.md","filePath":"guide/pve/pve_custom.md","lastUpdated":1747984962000}'),n={name:"guide/pve/pve_custom.md"};function t(l,s,h,o,d,c){return e(),i("div",null,s[0]||(s[0]=[p(`

自定义分区

在非Debian系统上安装 Proxmox VE 7

本机硬件配置的最低要求同先前正常安装的要求一致

需要先安装docker

curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

然后使用uname -m查询架构,使用对应架构的命令

开设出的PVE面板信息为:

登录用户名和密码都是root,登录后务必使用web的SSH更改密码以免被爆破

用宿主机SSH时务必登录对应https://IPV4地址:8006在web面板上使用SSH,不要使用宿主机的22端口操控PVE

因为web面板上的SSH是在Docker内的,所以不支持后续的一键配置,请自行配置网关等进行使用

X86架构

bash
docker run -idt --network host \\
+--privileged \\
+--name pve \\
+--add-host pve:10.13.14.101 \\
+--hostname pve \\
+spiritlhl/pve:7_x86_64

ARM架构

bash
docker run -idt --network host \\
+--privileged \\
+--name pve \\
+--add-host pve:10.13.14.101 \\
+--hostname pve \\
+spiritlhl/pve:7_aarch64

开设出的面板实际是开设在容器内的,但网络已使用host模式,PVE的端口约等于就使用的宿主机的端口

但这里登录的用户名和密码就变成了rootroot,如需修改请docker exec -it pve /bin/bash进入后修改root的密码,然后按ctrl键和A+D退出。

有许多错误需要修复,欢迎PR解决问题,实测在Ubuntu系统的宿主机上安装Proxmox VE的面板成功,解决了通过网络安装Proxmox VE只能使用Debian系统做宿主机的问题

在低配置系统中优化Proxmox-VE的内存占用

以下优化可以减少至少400M内存左右的占用,部分机器能减少6GB以上,实际减少多少内存占用自行测试

减少max_workers数量

执行下述命令查询

cd /usr/share/perl5/PVE/Service
+grep 'max_workers => 3' *

可见

pvedaemon.pm:    max_workers => 3,
+pveproxy.pm:    max_workers => 3,
+spiceproxy.pm:    max_workers => 3, # todo: do we need more?

默认的max_workers是3,可以修改对应的文件,最低max_workers可为1,可使用如下命令进行修改

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

停用HA服务

集群(多节点)可以使用HA服务,如果是单节点,或者没有HA使用的需求,可以执行下述命令禁用

systemctl stop pve-ha-lrm.service 
+systemctl stop pve-ha-crm.service 
+systemctl disable pve-ha-lrm.service 
+systemctl disable pve-ha-crm.service

停用防火墙服务

可执行下述命令停用服务

systemctl stop pve-firewall.service 
+systemctl disable pve-firewall.service

停用调度服务

如果不需要计划任务,如备份、同步之类的任务,可执行下述命令停用服务

systemctl stop pvescheduler.service
+systemctl disable pvescheduler.service

停用Spiceproxy服务

如果不需要使用Spice进行虚拟机/容器链接(arm下暂不支持Spice),可执行下述命令停用服务

systemctl stop spiceproxy.service 
+systemctl disable spiceproxy.service

使用定时任务删除内存缓存

清理不同类型的缓存以及对文件系统进行TRIM操作

shell
TEMP_CRON=$(mktemp)
+sudo crontab -l > $TEMP_CRON
+echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
+sudo crontab $TEMP_CRON
+rm $TEMP_CRON

上面的命令需要宿主机本身有sudocrontab命令才可使用。

在开设出的NAT的KVM虚拟机上自行映射公网端口

使用nanovim命令修改文件增加端口映射:

/etc/iptables/rules.v4

例如我有一台内网IP为172.16.1.152的KVM虚拟机,虚拟机内已经开设MYSQL监听了3306,我需要使用tcp协议映射出来到宿主机IP上的33306端口上进行使用,那么需要在上面的那个文件中的COMMIT行以上增加如下行

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

保存文件退出文件编辑后执行

service netfilter-persistent restart

重载端口映射

此时在宿主机上执行

lsof -i:33306

可见端口映射规则是否生效

开设Linux虚拟机的时候自定义CPU的TYPE

在宿主机上使用类似

shell
echo "kvm64" > /usr/local/bin/cpu_type

这样的方式指定默认的CPU的TYPE,可将kvm64替换为你需要的类型

`,57)]))}const g=a(n,[["render",t]]);export{k as __pageData,g as default}; diff --git a/assets/guide_pve_pve_custom.md.0uRKiuWM.lean.js b/assets/guide_pve_pve_custom.md.0uRKiuWM.lean.js new file mode 100644 index 0000000000..d83bd33faf --- /dev/null +++ b/assets/guide_pve_pve_custom.md.0uRKiuWM.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as e,ag as p}from"./chunks/framework.CSeR4K32.js";const k=JSON.parse('{"title":"自定义分区","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_custom.md","filePath":"guide/pve/pve_custom.md","lastUpdated":1747984962000}'),n={name:"guide/pve/pve_custom.md"};function t(l,s,h,o,d,c){return e(),i("div",null,s[0]||(s[0]=[p("",57)]))}const g=a(n,[["render",t]]);export{k as __pageData,g as default}; diff --git a/assets/guide_pve_pve_custom.md.c31784f7.js b/assets/guide_pve_pve_custom.md.c31784f7.js deleted file mode 100644 index 56d024559d..0000000000 --- a/assets/guide_pve_pve_custom.md.c31784f7.js +++ /dev/null @@ -1,30 +0,0 @@ -import{_ as s,v as a,b as e,R as p}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"自定义分区","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_custom.md","filePath":"guide/pve/pve_custom.md","lastUpdated":1747972048000}'),n={name:"guide/pve/pve_custom.md"},o=p(`

自定义分区

在非Debian系统上安装 Proxmox VE 7

本机硬件配置的最低要求同先前正常安装的要求一致

需要先安装docker

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

然后使用uname -m查询架构,使用对应架构的命令

开设出的PVE面板信息为:

登录用户名和密码都是root,登录后务必使用web的SSH更改密码以免被爆破

用宿主机SSH时务必登录对应https://IPV4地址:8006在web面板上使用SSH,不要使用宿主机的22端口操控PVE

因为web面板上的SSH是在Docker内的,所以不支持后续的一键配置,请自行配置网关等进行使用

X86架构

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_x86_64

ARM架构

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_aarch64

开设出的面板实际是开设在容器内的,但网络已使用host模式,PVE的端口约等于就使用的宿主机的端口

但这里登录的用户名和密码就变成了rootroot,如需修改请docker exec -it pve /bin/bash进入后修改root的密码,然后按ctrl键和A+D退出。

有许多错误需要修复,欢迎PR解决问题,实测在Ubuntu系统的宿主机上安装Proxmox VE的面板成功,解决了通过网络安装Proxmox VE只能使用Debian系统做宿主机的问题

在低配置系统中优化Proxmox-VE的内存占用

以下优化可以减少至少400M内存左右的占用,部分机器能减少6GB以上,实际减少多少内存占用自行测试

减少max_workers数量

执行下述命令查询

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

可见

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

默认的max_workers是3,可以修改对应的文件,最低max_workers可为1,可使用如下命令进行修改

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

停用HA服务

集群(多节点)可以使用HA服务,如果是单节点,或者没有HA使用的需求,可以执行下述命令禁用

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

停用防火墙服务

可执行下述命令停用服务

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

停用调度服务

如果不需要计划任务,如备份、同步之类的任务,可执行下述命令停用服务

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

停用Spiceproxy服务

如果不需要使用Spice进行虚拟机/容器链接(arm下暂不支持Spice),可执行下述命令停用服务

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

使用定时任务删除内存缓存

清理不同类型的缓存以及对文件系统进行TRIM操作

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

上面的命令需要宿主机本身有sudocrontab命令才可使用。

在开设出的NAT的KVM虚拟机上自行映射公网端口

使用nanovim命令修改文件增加端口映射:

/etc/iptables/rules.v4

例如我有一台内网IP为172.16.1.152的KVM虚拟机,虚拟机内已经开设MYSQL监听了3306,我需要使用tcp协议映射出来到宿主机IP上的33306端口上进行使用,那么需要在上面的那个文件中的COMMIT行以上增加如下行

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

保存文件退出文件编辑后执行

service netfilter-persistent restart

重载端口映射

此时在宿主机上执行

lsof -i:33306

可见端口映射规则是否生效

开设Linux虚拟机的时候自定义CPU的TYPE

在宿主机上使用类似

shell
echo "kvm64" > /usr/local/bin/cpu_type

这样的方式指定默认的CPU的TYPE,可将kvm64替换为你需要的类型

`,57),l=[o];function t(c,r,i,C,d,y){return a(),e("div",null,l)}const D=s(n,[["render",t]]);export{h as __pageData,D as default}; diff --git a/assets/guide_pve_pve_custom.md.c31784f7.lean.js b/assets/guide_pve_pve_custom.md.c31784f7.lean.js deleted file mode 100644 index 56d024559d..0000000000 --- a/assets/guide_pve_pve_custom.md.c31784f7.lean.js +++ /dev/null @@ -1,30 +0,0 @@ -import{_ as s,v as a,b as e,R as p}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"自定义分区","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_custom.md","filePath":"guide/pve/pve_custom.md","lastUpdated":1747972048000}'),n={name:"guide/pve/pve_custom.md"},o=p(`

自定义分区

在非Debian系统上安装 Proxmox VE 7

本机硬件配置的最低要求同先前正常安装的要求一致

需要先安装docker

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

然后使用uname -m查询架构,使用对应架构的命令

开设出的PVE面板信息为:

登录用户名和密码都是root,登录后务必使用web的SSH更改密码以免被爆破

用宿主机SSH时务必登录对应https://IPV4地址:8006在web面板上使用SSH,不要使用宿主机的22端口操控PVE

因为web面板上的SSH是在Docker内的,所以不支持后续的一键配置,请自行配置网关等进行使用

X86架构

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_x86_64

ARM架构

bash
docker run -idt --network host \\
---privileged \\
---name pve \\
---add-host pve:10.13.14.101 \\
---hostname pve \\
-spiritlhl/pve:7_aarch64

开设出的面板实际是开设在容器内的,但网络已使用host模式,PVE的端口约等于就使用的宿主机的端口

但这里登录的用户名和密码就变成了rootroot,如需修改请docker exec -it pve /bin/bash进入后修改root的密码,然后按ctrl键和A+D退出。

有许多错误需要修复,欢迎PR解决问题,实测在Ubuntu系统的宿主机上安装Proxmox VE的面板成功,解决了通过网络安装Proxmox VE只能使用Debian系统做宿主机的问题

在低配置系统中优化Proxmox-VE的内存占用

以下优化可以减少至少400M内存左右的占用,部分机器能减少6GB以上,实际减少多少内存占用自行测试

减少max_workers数量

执行下述命令查询

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

可见

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

默认的max_workers是3,可以修改对应的文件,最低max_workers可为1,可使用如下命令进行修改

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

停用HA服务

集群(多节点)可以使用HA服务,如果是单节点,或者没有HA使用的需求,可以执行下述命令禁用

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

停用防火墙服务

可执行下述命令停用服务

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

停用调度服务

如果不需要计划任务,如备份、同步之类的任务,可执行下述命令停用服务

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

停用Spiceproxy服务

如果不需要使用Spice进行虚拟机/容器链接(arm下暂不支持Spice),可执行下述命令停用服务

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

使用定时任务删除内存缓存

清理不同类型的缓存以及对文件系统进行TRIM操作

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

上面的命令需要宿主机本身有sudocrontab命令才可使用。

在开设出的NAT的KVM虚拟机上自行映射公网端口

使用nanovim命令修改文件增加端口映射:

/etc/iptables/rules.v4

例如我有一台内网IP为172.16.1.152的KVM虚拟机,虚拟机内已经开设MYSQL监听了3306,我需要使用tcp协议映射出来到宿主机IP上的33306端口上进行使用,那么需要在上面的那个文件中的COMMIT行以上增加如下行

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

保存文件退出文件编辑后执行

service netfilter-persistent restart

重载端口映射

此时在宿主机上执行

lsof -i:33306

可见端口映射规则是否生效

开设Linux虚拟机的时候自定义CPU的TYPE

在宿主机上使用类似

shell
echo "kvm64" > /usr/local/bin/cpu_type

这样的方式指定默认的CPU的TYPE,可将kvm64替换为你需要的类型

`,57),l=[o];function t(c,r,i,C,d,y){return a(),e("div",null,l)}const D=s(n,[["render",t]]);export{h as __pageData,D as default}; diff --git a/assets/guide_pve_pve_install.md.CdRZOjQC.js b/assets/guide_pve_pve_install.md.CdRZOjQC.js new file mode 100644 index 0000000000..8ee11cfdb0 --- /dev/null +++ b/assets/guide_pve_pve_install.md.CdRZOjQC.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const r=JSON.parse('{"title":"PVE主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_install.md","filePath":"guide/pve/pve_install.md","lastUpdated":1747984962000}'),l={name:"guide/pve/pve_install.md"};function p(h,s,n,c,d,o){return t(),a("div",null,s[0]||(s[0]=[e('

PVE主体安装

安装过程中遇到选项不会选的可无脑按回车,本项目所有脚本内置国内外IP自动判断,使用的是不同的安装源与配置文件,有使用CDN加速镜像下载

TIP

低配置的宿主机,建议所有内容安装完毕后,查看自定义分区的内容,进行内存调优,减少内存占用。

一键安装PVE

TIP

建议debian12,实测部分独立服务器的debian11系统会出现一重启网络就失联的情况,debian12没有这种问题

  • 安装的是当下apt源最新的PVE
  • 比如debian10则是pve6.4,debian11则是pve7.x,debian12则是pve8.x
  • /etc/hosts文件修改(修正商家hostname设置错误以及新增PVE所需的内容)
  • /etc/cloud/cloud.cfg文件修改(避免覆写已修改的hostname等配置)
  • /etc/network/interfaces文件修改(修复auto、dhcp类型为static、增加vmbr0网关)
  • 检测是否为中国IP,如果为中国IP使用清华镜像源,否则使用官方源,同时处理apt的源和对应的nameserver,避免断网
  • 创建vmbr0(独立IP网关),宿主机允许addr和gateway为内网IP或外网IP,已自动识别
  • vmbr0创建支持开设纯IPV4、纯IPV6、双栈虚拟机,自动识别IPV4地址和IPV6地址,自动识别对应的IP区间
  • 安装PVE开虚拟机需要的必备工具包
  • x86_64的替换apt源中的企业订阅为社区源,arm的使用第三方修复的补丁构建的源
  • 打印查询Linux系统内核和PVE内核是否已安装
  • 设置DNS检测8.8.8.8的开机自启添加DNS的systemd服务
  • 新增PVE的APT源链接后,下载PVE并打印输出登陆信息

所有修改过的文件均已设置为只读模式,避免重启后文件被覆写,如需修改请使用chattr -i 文件路径取消只读锁定,修改完毕请执行chattr +i 文件路径进行只读锁定

执行过程中会提示重启系统一次,重启后务必等待起码20秒确保系统未再次自动重启,因为原始环境可能缺失ifupdownifupdown2环境,有加载安装的守护进程进行安装,安装后会再次自动重启系统,等待20秒未自重启确保这个安装已运行完毕.

如果你需要将新安装的PVE纳管进入已有的集群,那么这块安装的时候,名字就不能回车默认使用pve,需要换一个名字避免和集群内的pve本身的hostname冲突.

若宿主机本身存在SLAAC分配的IPV6地址,将可选择是否使用最大的IPV6子网范围,默认回车不使用最大的IPV6子网范围仅使用本机IPV6,若后续需要给虚拟机/容器附加独立的IPV6地址,该选项务必选择y.

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

shell
bash install_pve.sh

TIP

安装成功后打开网页可能提示不安全,点击高级或更多选项,坚持访问即可

登录的信息是你SSH的账户和密码

预配置环境

  • 创建资源池mypool(local)
  • 移除订阅弹窗
  • 尝试开启硬件直通
  • 对AppArmor模块检测和自动安装
  • 重启系统前推荐挂上nezha探针方便在后台不通过SSH使用命令行,避免SSH可能因为商家奇葩的预设可能导致重启后root密码丢失
  • 执行reboot前需要等待后台任务执行完毕,一些宿主机的系统apt命令执行很慢,得等一会才能执行完毕,当然大部分的机器没这么烂,如果很久都起不来ssh无法连接,那么尝试通过控制面板重启一下服务器

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

自动配置宿主机的网关

WARNING

使用前请保证重启过服务器且此时PVE能正常登录进WEB端再执行,重启机器后不要立即执行此命令,待WEB端启动并可登录成功后至少等1分钟再执行本命令 如果WEB端起不来,执行systemctl status pveproxy查看是否启动,如果卡住未启动,执行systemctl start pveproxy启动WEB端。

TIP

这一步是最容易造成SSH断开的,原因是未等待PVE内核启动就修改网络会造成设置冲突,所以至少等几分钟待内核启动也就是WEB端启动成功后再执行。

TIP

在执行本命令前如果宿主机需要附加IPV6隧道(给没有IPV6地址的宿主机添加IPV6子网),请查看IPV6免费子网附加部分的内容附加到对应的配置文件中,但请忽略<初始环境修改>的操作,直接进行附加,附加后验证有IPV6地址了再执行下面的一键配置网关的命令。

  • 如果vmbr0未创建,则自动创建,逻辑同主体安装一致
  • 创建vmbr1(NAT网关),支持开设NAT的IPV6网络的NAT的IPV4的服务器
  • 创建vmbr2(独立IPV6网关),使用ndppd解决宿主机对IPV6地址进行MAC校验的问题,支持开设带独立IPV6网络的服务器
  • 想查看完整设置可以执行cat /etc/network/interfaces查看,如需修改网关需要修改该文件,web端已经无法修改
  • 加载iptables并设置回源且允许NAT端口转发

简单的说,vmbr0负责v4的独立IP,vmbr1负责复杂v4/v6的NAT,vmbr2负责v6的独立IP

开独立IPV4的虚拟机时使用的vmbr0,gateway同宿主机,IPV4/CIDR使用同一网段的地址和相同的子网掩码,使用宿主机未绑定的IPV4地址做IPV4/CIDR,当然如果后续使用本套脚本无需关注这点细枝末节的东西

开NAT的IPV4的虚拟机时使用vmbr1,gateway使用172.16.1.1,IPV4/CIDR使用172.16.1.x/24,这里的x不能是1,当然如果后续使用本套脚本无需关注这点细枝末节的东西

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

这一步是可能需要你执行成功几分钟后重启系统,详见脚本最后执行完毕的提示,但重启可以保证部分隐藏设置加载成功,有条件务必重启一次服务器

',37)]))}const g=i(l,[["render",p]]);export{r as __pageData,g as default}; diff --git a/assets/guide_pve_pve_install.md.CdRZOjQC.lean.js b/assets/guide_pve_pve_install.md.CdRZOjQC.lean.js new file mode 100644 index 0000000000..affcf77029 --- /dev/null +++ b/assets/guide_pve_pve_install.md.CdRZOjQC.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const r=JSON.parse('{"title":"PVE主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_install.md","filePath":"guide/pve/pve_install.md","lastUpdated":1747984962000}'),l={name:"guide/pve/pve_install.md"};function p(h,s,n,c,d,o){return t(),a("div",null,s[0]||(s[0]=[e("",37)]))}const g=i(l,[["render",p]]);export{r as __pageData,g as default}; diff --git a/assets/guide_pve_pve_install.md.b9ed6cd8.js b/assets/guide_pve_pve_install.md.b9ed6cd8.js deleted file mode 100644 index a0050afc63..0000000000 --- a/assets/guide_pve_pve_install.md.b9ed6cd8.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as l,b as a,R as e}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"PVE主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_install.md","filePath":"guide/pve/pve_install.md","lastUpdated":1747972048000}'),p={name:"guide/pve/pve_install.md"},t=e('

PVE主体安装

安装过程中遇到选项不会选的可无脑按回车,本项目所有脚本内置国内外IP自动判断,使用的是不同的安装源与配置文件,有使用CDN加速镜像下载

TIP

低配置的宿主机,建议所有内容安装完毕后,查看自定义分区的内容,进行内存调优,减少内存占用。

一键安装PVE

TIP

建议debian12,实测部分独立服务器的debian11系统会出现一重启网络就失联的情况,debian12没有这种问题

  • 安装的是当下apt源最新的PVE
  • 比如debian10则是pve6.4,debian11则是pve7.x,debian12则是pve8.x
  • /etc/hosts文件修改(修正商家hostname设置错误以及新增PVE所需的内容)
  • /etc/cloud/cloud.cfg文件修改(避免覆写已修改的hostname等配置)
  • /etc/network/interfaces文件修改(修复auto、dhcp类型为static、增加vmbr0网关)
  • 检测是否为中国IP,如果为中国IP使用清华镜像源,否则使用官方源,同时处理apt的源和对应的nameserver,避免断网
  • 创建vmbr0(独立IP网关),宿主机允许addr和gateway为内网IP或外网IP,已自动识别
  • vmbr0创建支持开设纯IPV4、纯IPV6、双栈虚拟机,自动识别IPV4地址和IPV6地址,自动识别对应的IP区间
  • 安装PVE开虚拟机需要的必备工具包
  • x86_64的替换apt源中的企业订阅为社区源,arm的使用第三方修复的补丁构建的源
  • 打印查询Linux系统内核和PVE内核是否已安装
  • 设置DNS检测8.8.8.8的开机自启添加DNS的systemd服务
  • 新增PVE的APT源链接后,下载PVE并打印输出登陆信息

所有修改过的文件均已设置为只读模式,避免重启后文件被覆写,如需修改请使用chattr -i 文件路径取消只读锁定,修改完毕请执行chattr +i 文件路径进行只读锁定

执行过程中会提示重启系统一次,重启后务必等待起码20秒确保系统未再次自动重启,因为原始环境可能缺失ifupdownifupdown2环境,有加载安装的守护进程进行安装,安装后会再次自动重启系统,等待20秒未自重启确保这个安装已运行完毕.

如果你需要将新安装的PVE纳管进入已有的集群,那么这块安装的时候,名字就不能回车默认使用pve,需要换一个名字避免和集群内的pve本身的hostname冲突.

若宿主机本身存在SLAAC分配的IPV6地址,将可选择是否使用最大的IPV6子网范围,默认回车不使用最大的IPV6子网范围仅使用本机IPV6,若后续需要给虚拟机/容器附加独立的IPV6地址,该选项务必选择y.

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

shell
bash install_pve.sh

TIP

安装成功后打开网页可能提示不安全,点击高级或更多选项,坚持访问即可

登录的信息是你SSH的账户和密码

预配置环境

  • 创建资源池mypool(local)
  • 移除订阅弹窗
  • 尝试开启硬件直通
  • 对AppArmor模块检测和自动安装
  • 重启系统前推荐挂上nezha探针方便在后台不通过SSH使用命令行,避免SSH可能因为商家奇葩的预设可能导致重启后root密码丢失
  • 执行reboot前需要等待后台任务执行完毕,一些宿主机的系统apt命令执行很慢,得等一会才能执行完毕,当然大部分的机器没这么烂,如果很久都起不来ssh无法连接,那么尝试通过控制面板重启一下服务器

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

自动配置宿主机的网关

WARNING

使用前请保证重启过服务器且此时PVE能正常登录进WEB端再执行,重启机器后不要立即执行此命令,待WEB端启动并可登录成功后至少等1分钟再执行本命令 如果WEB端起不来,执行systemctl status pveproxy查看是否启动,如果卡住未启动,执行systemctl start pveproxy启动WEB端。

TIP

这一步是最容易造成SSH断开的,原因是未等待PVE内核启动就修改网络会造成设置冲突,所以至少等几分钟待内核启动也就是WEB端启动成功后再执行。

TIP

在执行本命令前如果宿主机需要附加IPV6隧道(给没有IPV6地址的宿主机添加IPV6子网),请查看IPV6免费子网附加部分的内容附加到对应的配置文件中,但请忽略<初始环境修改>的操作,直接进行附加,附加后验证有IPV6地址了再执行下面的一键配置网关的命令。

  • 如果vmbr0未创建,则自动创建,逻辑同主体安装一致
  • 创建vmbr1(NAT网关),支持开设NAT的IPV6网络的NAT的IPV4的服务器
  • 创建vmbr2(独立IPV6网关),使用ndppd解决宿主机对IPV6地址进行MAC校验的问题,支持开设带独立IPV6网络的服务器
  • 想查看完整设置可以执行cat /etc/network/interfaces查看,如需修改网关需要修改该文件,web端已经无法修改
  • 加载iptables并设置回源且允许NAT端口转发

简单的说,vmbr0负责v4的独立IP,vmbr1负责复杂v4/v6的NAT,vmbr2负责v6的独立IP

开独立IPV4的虚拟机时使用的vmbr0,gateway同宿主机,IPV4/CIDR使用同一网段的地址和相同的子网掩码,使用宿主机未绑定的IPV4地址做IPV4/CIDR,当然如果后续使用本套脚本无需关注这点细枝末节的东西

开NAT的IPV4的虚拟机时使用vmbr1,gateway使用172.16.1.1,IPV4/CIDR使用172.16.1.x/24,这里的x不能是1,当然如果后续使用本套脚本无需关注这点细枝末节的东西

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

这一步是可能需要你执行成功几分钟后重启系统,详见脚本最后执行完毕的提示,但重启可以保证部分隐藏设置加载成功,有条件务必重启一次服务器

',37),o=[t];function n(c,i,r,d,h,C){return l(),a("div",null,o)}const v=s(p,[["render",n]]);export{u as __pageData,v as default}; diff --git a/assets/guide_pve_pve_install.md.b9ed6cd8.lean.js b/assets/guide_pve_pve_install.md.b9ed6cd8.lean.js deleted file mode 100644 index a0050afc63..0000000000 --- a/assets/guide_pve_pve_install.md.b9ed6cd8.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as l,b as a,R as e}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"PVE主体安装","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_install.md","filePath":"guide/pve/pve_install.md","lastUpdated":1747972048000}'),p={name:"guide/pve/pve_install.md"},t=e('

PVE主体安装

安装过程中遇到选项不会选的可无脑按回车,本项目所有脚本内置国内外IP自动判断,使用的是不同的安装源与配置文件,有使用CDN加速镜像下载

TIP

低配置的宿主机,建议所有内容安装完毕后,查看自定义分区的内容,进行内存调优,减少内存占用。

一键安装PVE

TIP

建议debian12,实测部分独立服务器的debian11系统会出现一重启网络就失联的情况,debian12没有这种问题

  • 安装的是当下apt源最新的PVE
  • 比如debian10则是pve6.4,debian11则是pve7.x,debian12则是pve8.x
  • /etc/hosts文件修改(修正商家hostname设置错误以及新增PVE所需的内容)
  • /etc/cloud/cloud.cfg文件修改(避免覆写已修改的hostname等配置)
  • /etc/network/interfaces文件修改(修复auto、dhcp类型为static、增加vmbr0网关)
  • 检测是否为中国IP,如果为中国IP使用清华镜像源,否则使用官方源,同时处理apt的源和对应的nameserver,避免断网
  • 创建vmbr0(独立IP网关),宿主机允许addr和gateway为内网IP或外网IP,已自动识别
  • vmbr0创建支持开设纯IPV4、纯IPV6、双栈虚拟机,自动识别IPV4地址和IPV6地址,自动识别对应的IP区间
  • 安装PVE开虚拟机需要的必备工具包
  • x86_64的替换apt源中的企业订阅为社区源,arm的使用第三方修复的补丁构建的源
  • 打印查询Linux系统内核和PVE内核是否已安装
  • 设置DNS检测8.8.8.8的开机自启添加DNS的systemd服务
  • 新增PVE的APT源链接后,下载PVE并打印输出登陆信息

所有修改过的文件均已设置为只读模式,避免重启后文件被覆写,如需修改请使用chattr -i 文件路径取消只读锁定,修改完毕请执行chattr +i 文件路径进行只读锁定

执行过程中会提示重启系统一次,重启后务必等待起码20秒确保系统未再次自动重启,因为原始环境可能缺失ifupdownifupdown2环境,有加载安装的守护进程进行安装,安装后会再次自动重启系统,等待20秒未自重启确保这个安装已运行完毕.

如果你需要将新安装的PVE纳管进入已有的集群,那么这块安装的时候,名字就不能回车默认使用pve,需要换一个名字避免和集群内的pve本身的hostname冲突.

若宿主机本身存在SLAAC分配的IPV6地址,将可选择是否使用最大的IPV6子网范围,默认回车不使用最大的IPV6子网范围仅使用本机IPV6,若后续需要给虚拟机/容器附加独立的IPV6地址,该选项务必选择y.

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

shell
bash install_pve.sh

TIP

安装成功后打开网页可能提示不安全,点击高级或更多选项,坚持访问即可

登录的信息是你SSH的账户和密码

预配置环境

  • 创建资源池mypool(local)
  • 移除订阅弹窗
  • 尝试开启硬件直通
  • 对AppArmor模块检测和自动安装
  • 重启系统前推荐挂上nezha探针方便在后台不通过SSH使用命令行,避免SSH可能因为商家奇葩的预设可能导致重启后root密码丢失
  • 执行reboot前需要等待后台任务执行完毕,一些宿主机的系统apt命令执行很慢,得等一会才能执行完毕,当然大部分的机器没这么烂,如果很久都起不来ssh无法连接,那么尝试通过控制面板重启一下服务器

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

自动配置宿主机的网关

WARNING

使用前请保证重启过服务器且此时PVE能正常登录进WEB端再执行,重启机器后不要立即执行此命令,待WEB端启动并可登录成功后至少等1分钟再执行本命令 如果WEB端起不来,执行systemctl status pveproxy查看是否启动,如果卡住未启动,执行systemctl start pveproxy启动WEB端。

TIP

这一步是最容易造成SSH断开的,原因是未等待PVE内核启动就修改网络会造成设置冲突,所以至少等几分钟待内核启动也就是WEB端启动成功后再执行。

TIP

在执行本命令前如果宿主机需要附加IPV6隧道(给没有IPV6地址的宿主机添加IPV6子网),请查看IPV6免费子网附加部分的内容附加到对应的配置文件中,但请忽略<初始环境修改>的操作,直接进行附加,附加后验证有IPV6地址了再执行下面的一键配置网关的命令。

  • 如果vmbr0未创建,则自动创建,逻辑同主体安装一致
  • 创建vmbr1(NAT网关),支持开设NAT的IPV6网络的NAT的IPV4的服务器
  • 创建vmbr2(独立IPV6网关),使用ndppd解决宿主机对IPV6地址进行MAC校验的问题,支持开设带独立IPV6网络的服务器
  • 想查看完整设置可以执行cat /etc/network/interfaces查看,如需修改网关需要修改该文件,web端已经无法修改
  • 加载iptables并设置回源且允许NAT端口转发

简单的说,vmbr0负责v4的独立IP,vmbr1负责复杂v4/v6的NAT,vmbr2负责v6的独立IP

开独立IPV4的虚拟机时使用的vmbr0,gateway同宿主机,IPV4/CIDR使用同一网段的地址和相同的子网掩码,使用宿主机未绑定的IPV4地址做IPV4/CIDR,当然如果后续使用本套脚本无需关注这点细枝末节的东西

开NAT的IPV4的虚拟机时使用vmbr1,gateway使用172.16.1.1,IPV4/CIDR使用172.16.1.x/24,这里的x不能是1,当然如果后续使用本套脚本无需关注这点细枝末节的东西

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

这一步是可能需要你执行成功几分钟后重启系统,详见脚本最后执行完毕的提示,但重启可以保证部分隐藏设置加载成功,有条件务必重启一次服务器

',37),o=[t];function n(c,i,r,d,h,C){return l(),a("div",null,o)}const v=s(p,[["render",n]]);export{u as __pageData,v as default}; diff --git a/assets/guide_pve_pve_kvm.md.43713910.js b/assets/guide_pve_pve_kvm.md.43713910.js deleted file mode 100644 index 99cfdf7f01..0000000000 --- a/assets/guide_pve_pve_kvm.md.43713910.js +++ /dev/null @@ -1,15 +0,0 @@ -import{_ as s,v as l,b as a,R as t}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Linux虚拟机(KVM/TCG)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_kvm.md","filePath":"guide/pve/pve_kvm.md","lastUpdated":1747972048000}'),o={name:"guide/pve/pve_kvm.md"},n=t(`

Linux虚拟机(KVM/TCG)

SSH登录说明

开设出的虚拟机,默认生成的用户名可以不是root,此时你需要执行sudo -i切换为root用户

默认设置的用户名不是root时,未经过设置的默认的root密码是passwordoneclickvirt

登录SSH切换为root权限后,一定要修改root密码,可以使用以下命令修改

国际

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

国内

bash
bash <(curl -sSL https://cdn.spiritlhl.net/https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

开设带IPV6地址的虚拟机的注意事项

由于长期闲置IPV6不使用可能导致NDP广播缓存失效重置,一般闲置50分钟左右就会出现IPV6不可用的情况,俗称“IPV6断流”,此时需要设置一个定时任务

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

在开设出的虚拟机中执行上述命令,可保证IPV6网络一直被使用,不会失效断流

开设虚拟机可使用的镜像

  • 已预安装开启cloudinit
  • 开启SSH登陆
  • 预设置SSH监听V4和V6的22端口
  • 开启允许密码验证登陆
  • 开启允许root登陆
  • 部分预安装Qemu-guest-agent

目前可使用的镜像名字的列表为

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

以及

https://github.com/oneclickvirt/pve_kvm_images

仓库的Release中存储的每日修补镜像

单独开设NAT的虚拟化的虚拟机

  • 自动开设NAT服务器,默认使用Debian10镜像,因为该镜像占用最小
  • 可在命令中自定义需要使用的镜像,这里有给出配置好的镜像,镜像自带空间设置是2~10G硬盘,日常使用至少10G以上即可,除非某些镜像开不起来再增加硬盘大小
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 自定义内存大小推荐512MB内存
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloud-init配置好网络以及登陆信息,大概需要5分钟
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是/64的子网

使用方法

  • 系统支持:
    • x86_64架构的详见 跳转 中列出的系统,使用时只需写文件名字,不需要.qcow2尾缀
    • arm架构的详见 跳转 中列出的系统,使用时只需要写系统名字+系统版本号,如ubuntu20、ubutnu22这种

TIP

注意这里的用户名不能是纯数字,会造成cloudinit出问题,最好是纯英文或英文开头

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

各参数含义

shell
# ./buildvm.sh VMID 用户名 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6地址(留空默认N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

开设完毕可执行cat vm111查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小10G
SSH端口40001
80端口40002
443端口40003
内外网映射端口一致的区间50000到50025
系统debian11
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除指定虚拟机

  • 停止VM
  • 删除VM
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应VMID的虚拟机,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个VMID即可,可一次性删除多个

批量开设NAT的虚拟化的虚拟机

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成VM
  • 自动开设NAT服务器,选项留空默认使用debian11镜像,可自定义使用镜像名字,支持的系统名字详见上文支持的镜像列表
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloudinit配置好网络以及登陆信息,大概需要5分钟,每个虚拟机创建之间有间隔等待60秒避免突发性能不足
  • 默认批量开设的虚拟机网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

开设完毕可执行cat vmlog查看信息,或到WEB端对应VM的NOTES中查看

删除所有虚拟机

  • 删除所有VM
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

PVE修改VM配置前都得停机先,再修改配置,修改完再启动,免得出现配置重载错误

开设独立IPV4地址的虚拟机

三个脚本,各取所需,各有优缺点。

前两个脚本不需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将直接绑定额外的IPV4地址。

最后一个脚本需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将做NAT全端口映射内网IPV4地址,不直接绑定额外的IPV4地址。

自动选择宿主机同一子网内的额外IPV4地址开设虚拟机

WARNING

使用前需要保证当前宿主机的IP段带了至少2个IP,且有空余的IP未配置,该空余的IP未绑定宿主机。

TIP

此时附加的IPV4地址是宿主机目前的IPV4地址顺位后面的地址, 比如目前宿主机地址是1.1.1.32然后1.1.1.33已经有虚拟机了,那么本脚本附加IP地址为1.1.1.34

  • 自动检测可用的IP区间,通过ping检测空余可使用的IP,选取其中之一绑定到虚拟机上
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 自动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同)
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

各参数含义

shell
# ./buildvm_extra_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘
IPV6附加默认不附加

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

手动指定额外IPV4地址开设虚拟机

  • 需要手动在命令中指定IPV4地址,且带上子网长度
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 如果商家有给IPV4地址和子网长度,请仔细比对,按照下面示例的命令写参数
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网
  • 手动附加的IPV4地址与宿主机的IPV4地址是在不同子网内的(IP地址前缀不同),将使用宿主机IP地址做网关
  • 手动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同),将使用宿主机的网关做网关
  • 可选择是否指定虚拟机的MAC地址
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

TIP

不同子网内的IP地址,如果附加时不指定MAC地址,那么路由器无法识别源 MAC 地址,流量将被标记为“滥用”,并“可能”导致服务器被阻止。 (如果使用Hetzner的独立服务器务建议提供附加IPV4地址对应的MAC地址防止被报告滥用)

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

各参数含义

shell
# ./buildvm_manual_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N) MAC地址(不提供时将不指定虚拟机的MAC地址)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
子网/24 子网
IPV6
MAC地址

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

宿主机手动附加额外IPV4地址后再指定IPV4地址开设虚拟机

  • 需要自己在/etc/network/interfaces中给vmbr0添加额外的IPV4地址(注意chattr -i解锁文件修改后再chattr +i加锁回去)
  • 其他功能类似开设NAT的虚拟机,只不过这里映射不再是部分端口映射,也不再是映射到宿主机的IPV4地址上,而是全端口一一映射到额外的IPV4地址上
  • 在虚拟机外进入虚拟机的流量走绑定的额外IPV4的地址,在虚拟机内发出的流量走原有的宿主机的IPV4地址

TIP

务必保证开设前你能使用额外的IPV4地址通过SSH登录宿主机,但curl ip.sb却仍显示原来的宿主机IPV4地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

各参数含义

shell
# ./buildvm_fullnat_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
IPV6

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

进出流量都走绑定的IPV4地址

执行

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

即可,但这会导致宿主机丧失开设非独立IPV4地址的NAT的虚拟机/容器的能力,慎重执行

执行后你只能开设独立IPV4地址的虚拟机了。

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际虚拟机仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应虚拟机编号的V6地址绑定到虚拟机上
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

各参数含义

shell
# ./buildvm_onlyv6.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

创建示例

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的虚拟机

参数
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除vm152示例

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
`,144),p=[n];function e(c,r,i,C,d,y){return l(),a("div",null,p)}const h=s(o,[["render",e]]);export{D as __pageData,h as default}; diff --git a/assets/guide_pve_pve_kvm.md.43713910.lean.js b/assets/guide_pve_pve_kvm.md.43713910.lean.js deleted file mode 100644 index 99cfdf7f01..0000000000 --- a/assets/guide_pve_pve_kvm.md.43713910.lean.js +++ /dev/null @@ -1,15 +0,0 @@ -import{_ as s,v as l,b as a,R as t}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"Linux虚拟机(KVM/TCG)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_kvm.md","filePath":"guide/pve/pve_kvm.md","lastUpdated":1747972048000}'),o={name:"guide/pve/pve_kvm.md"},n=t(`

Linux虚拟机(KVM/TCG)

SSH登录说明

开设出的虚拟机,默认生成的用户名可以不是root,此时你需要执行sudo -i切换为root用户

默认设置的用户名不是root时,未经过设置的默认的root密码是passwordoneclickvirt

登录SSH切换为root权限后,一定要修改root密码,可以使用以下命令修改

国际

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

国内

bash
bash <(curl -sSL https://cdn.spiritlhl.net/https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

开设带IPV6地址的虚拟机的注意事项

由于长期闲置IPV6不使用可能导致NDP广播缓存失效重置,一般闲置50分钟左右就会出现IPV6不可用的情况,俗称“IPV6断流”,此时需要设置一个定时任务

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

在开设出的虚拟机中执行上述命令,可保证IPV6网络一直被使用,不会失效断流

开设虚拟机可使用的镜像

  • 已预安装开启cloudinit
  • 开启SSH登陆
  • 预设置SSH监听V4和V6的22端口
  • 开启允许密码验证登陆
  • 开启允许root登陆
  • 部分预安装Qemu-guest-agent

目前可使用的镜像名字的列表为

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

以及

https://github.com/oneclickvirt/pve_kvm_images

仓库的Release中存储的每日修补镜像

单独开设NAT的虚拟化的虚拟机

  • 自动开设NAT服务器,默认使用Debian10镜像,因为该镜像占用最小
  • 可在命令中自定义需要使用的镜像,这里有给出配置好的镜像,镜像自带空间设置是2~10G硬盘,日常使用至少10G以上即可,除非某些镜像开不起来再增加硬盘大小
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 自定义内存大小推荐512MB内存
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloud-init配置好网络以及登陆信息,大概需要5分钟
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是/64的子网

使用方法

  • 系统支持:
    • x86_64架构的详见 跳转 中列出的系统,使用时只需写文件名字,不需要.qcow2尾缀
    • arm架构的详见 跳转 中列出的系统,使用时只需要写系统名字+系统版本号,如ubuntu20、ubutnu22这种

TIP

注意这里的用户名不能是纯数字,会造成cloudinit出问题,最好是纯英文或英文开头

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

各参数含义

shell
# ./buildvm.sh VMID 用户名 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6地址(留空默认N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

开设完毕可执行cat vm111查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小10G
SSH端口40001
80端口40002
443端口40003
内外网映射端口一致的区间50000到50025
系统debian11
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除指定虚拟机

  • 停止VM
  • 删除VM
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应VMID的虚拟机,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个VMID即可,可一次性删除多个

批量开设NAT的虚拟化的虚拟机

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成VM
  • 自动开设NAT服务器,选项留空默认使用debian11镜像,可自定义使用镜像名字,支持的系统名字详见上文支持的镜像列表
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloudinit配置好网络以及登陆信息,大概需要5分钟,每个虚拟机创建之间有间隔等待60秒避免突发性能不足
  • 默认批量开设的虚拟机网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

开设完毕可执行cat vmlog查看信息,或到WEB端对应VM的NOTES中查看

删除所有虚拟机

  • 删除所有VM
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

PVE修改VM配置前都得停机先,再修改配置,修改完再启动,免得出现配置重载错误

开设独立IPV4地址的虚拟机

三个脚本,各取所需,各有优缺点。

前两个脚本不需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将直接绑定额外的IPV4地址。

最后一个脚本需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将做NAT全端口映射内网IPV4地址,不直接绑定额外的IPV4地址。

自动选择宿主机同一子网内的额外IPV4地址开设虚拟机

WARNING

使用前需要保证当前宿主机的IP段带了至少2个IP,且有空余的IP未配置,该空余的IP未绑定宿主机。

TIP

此时附加的IPV4地址是宿主机目前的IPV4地址顺位后面的地址, 比如目前宿主机地址是1.1.1.32然后1.1.1.33已经有虚拟机了,那么本脚本附加IP地址为1.1.1.34

  • 自动检测可用的IP区间,通过ping检测空余可使用的IP,选取其中之一绑定到虚拟机上
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 自动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同)
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

各参数含义

shell
# ./buildvm_extra_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘
IPV6附加默认不附加

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

手动指定额外IPV4地址开设虚拟机

  • 需要手动在命令中指定IPV4地址,且带上子网长度
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 如果商家有给IPV4地址和子网长度,请仔细比对,按照下面示例的命令写参数
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网
  • 手动附加的IPV4地址与宿主机的IPV4地址是在不同子网内的(IP地址前缀不同),将使用宿主机IP地址做网关
  • 手动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同),将使用宿主机的网关做网关
  • 可选择是否指定虚拟机的MAC地址
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

TIP

不同子网内的IP地址,如果附加时不指定MAC地址,那么路由器无法识别源 MAC 地址,流量将被标记为“滥用”,并“可能”导致服务器被阻止。 (如果使用Hetzner的独立服务器务建议提供附加IPV4地址对应的MAC地址防止被报告滥用)

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

各参数含义

shell
# ./buildvm_manual_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N) MAC地址(不提供时将不指定虚拟机的MAC地址)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
子网/24 子网
IPV6
MAC地址

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

宿主机手动附加额外IPV4地址后再指定IPV4地址开设虚拟机

  • 需要自己在/etc/network/interfaces中给vmbr0添加额外的IPV4地址(注意chattr -i解锁文件修改后再chattr +i加锁回去)
  • 其他功能类似开设NAT的虚拟机,只不过这里映射不再是部分端口映射,也不再是映射到宿主机的IPV4地址上,而是全端口一一映射到额外的IPV4地址上
  • 在虚拟机外进入虚拟机的流量走绑定的额外IPV4的地址,在虚拟机内发出的流量走原有的宿主机的IPV4地址

TIP

务必保证开设前你能使用额外的IPV4地址通过SSH登录宿主机,但curl ip.sb却仍显示原来的宿主机IPV4地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

各参数含义

shell
# ./buildvm_fullnat_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
IPV6

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

进出流量都走绑定的IPV4地址

执行

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

即可,但这会导致宿主机丧失开设非独立IPV4地址的NAT的虚拟机/容器的能力,慎重执行

执行后你只能开设独立IPV4地址的虚拟机了。

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际虚拟机仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应虚拟机编号的V6地址绑定到虚拟机上
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

各参数含义

shell
# ./buildvm_onlyv6.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

创建示例

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的虚拟机

参数
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除vm152示例

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
`,144),p=[n];function e(c,r,i,C,d,y){return l(),a("div",null,p)}const h=s(o,[["render",e]]);export{D as __pageData,h as default}; diff --git a/assets/guide_pve_pve_kvm.md.DiXxjdva.js b/assets/guide_pve_pve_kvm.md.DiXxjdva.js new file mode 100644 index 0000000000..3ff5d737fa --- /dev/null +++ b/assets/guide_pve_pve_kvm.md.DiXxjdva.js @@ -0,0 +1,15 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Linux虚拟机(KVM/TCG)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_kvm.md","filePath":"guide/pve/pve_kvm.md","lastUpdated":1747984962000}'),h={name:"guide/pve/pve_kvm.md"};function e(p,s,n,d,k,r){return t(),a("div",null,s[0]||(s[0]=[l(`

Linux虚拟机(KVM/TCG)

SSH登录说明

开设出的虚拟机,默认生成的用户名可以不是root,此时你需要执行sudo -i切换为root用户

默认设置的用户名不是root时,未经过设置的默认的root密码是passwordoneclickvirt

登录SSH切换为root权限后,一定要修改root密码,可以使用以下命令修改

国际

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

国内

bash
bash <(curl -sSL https://cdn.spiritlhl.net/https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

开设带IPV6地址的虚拟机的注意事项

由于长期闲置IPV6不使用可能导致NDP广播缓存失效重置,一般闲置50分钟左右就会出现IPV6不可用的情况,俗称“IPV6断流”,此时需要设置一个定时任务

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

在开设出的虚拟机中执行上述命令,可保证IPV6网络一直被使用,不会失效断流

开设虚拟机可使用的镜像

  • 已预安装开启cloudinit
  • 开启SSH登陆
  • 预设置SSH监听V4和V6的22端口
  • 开启允许密码验证登陆
  • 开启允许root登陆
  • 部分预安装Qemu-guest-agent

目前可使用的镜像名字的列表为

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

以及

https://github.com/oneclickvirt/pve_kvm_images

仓库的Release中存储的每日修补镜像

单独开设NAT的虚拟化的虚拟机

  • 自动开设NAT服务器,默认使用Debian10镜像,因为该镜像占用最小
  • 可在命令中自定义需要使用的镜像,这里有给出配置好的镜像,镜像自带空间设置是2~10G硬盘,日常使用至少10G以上即可,除非某些镜像开不起来再增加硬盘大小
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 自定义内存大小推荐512MB内存
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloud-init配置好网络以及登陆信息,大概需要5分钟
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是/64的子网

使用方法

  • 系统支持:
    • x86_64架构的详见 跳转 中列出的系统,使用时只需写文件名字,不需要.qcow2尾缀
    • arm架构的详见 跳转 中列出的系统,使用时只需要写系统名字+系统版本号,如ubuntu20、ubutnu22这种

TIP

注意这里的用户名不能是纯数字,会造成cloudinit出问题,最好是纯英文或英文开头

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

各参数含义

shell
# ./buildvm.sh VMID 用户名 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6地址(留空默认N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

开设完毕可执行cat vm111查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小10G
SSH端口40001
80端口40002
443端口40003
内外网映射端口一致的区间50000到50025
系统debian11
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除指定虚拟机

  • 停止VM
  • 删除VM
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应VMID的虚拟机,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个VMID即可,可一次性删除多个

批量开设NAT的虚拟化的虚拟机

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成VM
  • 自动开设NAT服务器,选项留空默认使用debian11镜像,可自定义使用镜像名字,支持的系统名字详见上文支持的镜像列表
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloudinit配置好网络以及登陆信息,大概需要5分钟,每个虚拟机创建之间有间隔等待60秒避免突发性能不足
  • 默认批量开设的虚拟机网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

开设完毕可执行cat vmlog查看信息,或到WEB端对应VM的NOTES中查看

删除所有虚拟机

  • 删除所有VM
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4
+rm -rf vmlog
+rm -rf vm*

TIP

PVE修改VM配置前都得停机先,再修改配置,修改完再启动,免得出现配置重载错误

开设独立IPV4地址的虚拟机

三个脚本,各取所需,各有优缺点。

前两个脚本不需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将直接绑定额外的IPV4地址。

最后一个脚本需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将做NAT全端口映射内网IPV4地址,不直接绑定额外的IPV4地址。

自动选择宿主机同一子网内的额外IPV4地址开设虚拟机

WARNING

使用前需要保证当前宿主机的IP段带了至少2个IP,且有空余的IP未配置,该空余的IP未绑定宿主机。

TIP

此时附加的IPV4地址是宿主机目前的IPV4地址顺位后面的地址, 比如目前宿主机地址是1.1.1.32然后1.1.1.33已经有虚拟机了,那么本脚本附加IP地址为1.1.1.34

  • 自动检测可用的IP区间,通过ping检测空余可使用的IP,选取其中之一绑定到虚拟机上
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 自动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同)
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

各参数含义

shell
# ./buildvm_extra_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘
IPV6附加默认不附加

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

手动指定额外IPV4地址开设虚拟机

  • 需要手动在命令中指定IPV4地址,且带上子网长度
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 如果商家有给IPV4地址和子网长度,请仔细比对,按照下面示例的命令写参数
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网
  • 手动附加的IPV4地址与宿主机的IPV4地址是在不同子网内的(IP地址前缀不同),将使用宿主机IP地址做网关
  • 手动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同),将使用宿主机的网关做网关
  • 可选择是否指定虚拟机的MAC地址
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

TIP

不同子网内的IP地址,如果附加时不指定MAC地址,那么路由器无法识别源 MAC 地址,流量将被标记为“滥用”,并“可能”导致服务器被阻止。 (如果使用Hetzner的独立服务器务建议提供附加IPV4地址对应的MAC地址防止被报告滥用)

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

各参数含义

shell
# ./buildvm_manual_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N) MAC地址(不提供时将不指定虚拟机的MAC地址)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
子网/24 子网
IPV6
MAC地址

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

宿主机手动附加额外IPV4地址后再指定IPV4地址开设虚拟机

  • 需要自己在/etc/network/interfaces中给vmbr0添加额外的IPV4地址(注意chattr -i解锁文件修改后再chattr +i加锁回去)
  • 其他功能类似开设NAT的虚拟机,只不过这里映射不再是部分端口映射,也不再是映射到宿主机的IPV4地址上,而是全端口一一映射到额外的IPV4地址上
  • 在虚拟机外进入虚拟机的流量走绑定的额外IPV4的地址,在虚拟机内发出的流量走原有的宿主机的IPV4地址

TIP

务必保证开设前你能使用额外的IPV4地址通过SSH登录宿主机,但curl ip.sb却仍显示原来的宿主机IPV4地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

各参数含义

shell
# ./buildvm_fullnat_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
IPV6

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

进出流量都走绑定的IPV4地址

执行

line="-A POSTROUTING -s 172.16.1.0\\/24 -o vmbr0 -j MASQUERADE"
+sed -i "\\|$line|d" /etc/iptables/rules.v4
+service netfilter-persistent restart

即可,但这会导致宿主机丧失开设非独立IPV4地址的NAT的虚拟机/容器的能力,慎重执行

执行后你只能开设独立IPV4地址的虚拟机了。

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际虚拟机仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应虚拟机编号的V6地址绑定到虚拟机上
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

各参数含义

shell
# ./buildvm_onlyv6.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

创建示例

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的虚拟机

参数
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除vm152示例

shell
qm stop 152
+qm destroy 152
+systemctl restart ndpresponder.service
+rm -rf vm152
`,144)]))}const F=i(h,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_pve_pve_kvm.md.DiXxjdva.lean.js b/assets/guide_pve_pve_kvm.md.DiXxjdva.lean.js new file mode 100644 index 0000000000..5d1fd699b7 --- /dev/null +++ b/assets/guide_pve_pve_kvm.md.DiXxjdva.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"Linux虚拟机(KVM/TCG)","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_kvm.md","filePath":"guide/pve/pve_kvm.md","lastUpdated":1747984962000}'),h={name:"guide/pve/pve_kvm.md"};function e(p,s,n,d,k,r){return t(),a("div",null,s[0]||(s[0]=[l("",144)]))}const F=i(h,[["render",e]]);export{c as __pageData,F as default}; diff --git a/assets/guide_pve_pve_lxc.md.704d4792.js b/assets/guide_pve_pve_lxc.md.704d4792.js deleted file mode 100644 index cf607df48e..0000000000 --- a/assets/guide_pve_pve_lxc.md.704d4792.js +++ /dev/null @@ -1,12 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"LXC容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_lxc.md","filePath":"guide/pve/pve_lxc.md","lastUpdated":1747972048000}'),t={name:"guide/pve/pve_lxc.md"},n=p(`

LXC容器

WARNING

如果你需要在一台服务器上开启超过200个LXC容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

开设LXC容器可使用的镜像

x86_64:

自动修补镜像:https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

每日自动拉取进行编译和修补

手动修补镜像: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

其中的部分镜像有缺陷,不保证所有PVE可用,名字为 ubuntu16.04debian6centos7opensuse42.2opensuse42.3 非必要不要使用。

执行pveam available --section system查看官方可用的系统名字和版本号

优先级:自修补镜像(Proxmox-VE 5及其以下版本不支持) > 官方默认镜像(都支持)

已通过脚本自动识别版本使用对应镜像

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

可在上面的文件中查看支持的系统,其中列出的debian和ubuntu系统不要使用里面的别名,使用数字代号即可。

TIP

系统参数一律是小写的系统名字拼接版本号,如:debian11,ubuntu22等。 (自修补镜像支持一些偏门系统,如 centos6、centos7、debian8、debian9 等)

所有系统的CT默认用户名是root

TIP

当然有时候会存在特殊情况,version可能是current/base,此时系统参数仅使用英文系统名字即可,如 archlinux、gentoo、kali。

单独开设LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 自动开设NAT服务器,默认使用Debian11镜像,也可自定义系统
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部配置好网络以及登陆信息,大概需要3分钟
  • 默认开设的网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

各参数含义

shell
# ./buildct.sh CTID 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6(默认为N)

测试示例

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

开设完毕可执行cat ct111查看信息,或在web端的NOTES查看

以下为开设的示例CT的信息:

属性
CTID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小5G
SSH端口20001
80端口20002
443端口20003
内外网映射端口一致的区间30000到30025
系统debian11
宿主机的存储盘local
IPV6

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除指定容器

  • 停止CT
  • 删除CT
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应CTID的容器,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个CTID即可,可一次性删除多个

批量开设NAT的LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成CT容器,但需要注意的是宿主机内存记得开点swap免得机器炸了开SWAP点我跳转
  • 每个容器创建之间有间隔等待60秒避免突发性能不足
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

开设完毕可执行cat ctlog查看信息,或在web端的NOTES查看

删除所有CT

  • 删除所有CT
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际容器仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应容器编号的V6地址绑定到容器上
  • 系统的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

各参数含义

shell
# ./buildct_onlyv6.sh CTID 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

创建示例

shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的容器

属性
容器类型CT
CTID152
用户名root
密码oneclick123
CPU核心数1
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除示例

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
`,78),o=[n];function e(c,r,C,i,y,d){return a(),l("div",null,o)}const h=s(t,[["render",e]]);export{D as __pageData,h as default}; diff --git a/assets/guide_pve_pve_lxc.md.704d4792.lean.js b/assets/guide_pve_pve_lxc.md.704d4792.lean.js deleted file mode 100644 index cf607df48e..0000000000 --- a/assets/guide_pve_pve_lxc.md.704d4792.lean.js +++ /dev/null @@ -1,12 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"LXC容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_lxc.md","filePath":"guide/pve/pve_lxc.md","lastUpdated":1747972048000}'),t={name:"guide/pve/pve_lxc.md"},n=p(`

LXC容器

WARNING

如果你需要在一台服务器上开启超过200个LXC容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

开设LXC容器可使用的镜像

x86_64:

自动修补镜像:https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

每日自动拉取进行编译和修补

手动修补镜像: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

其中的部分镜像有缺陷,不保证所有PVE可用,名字为 ubuntu16.04debian6centos7opensuse42.2opensuse42.3 非必要不要使用。

执行pveam available --section system查看官方可用的系统名字和版本号

优先级:自修补镜像(Proxmox-VE 5及其以下版本不支持) > 官方默认镜像(都支持)

已通过脚本自动识别版本使用对应镜像

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

可在上面的文件中查看支持的系统,其中列出的debian和ubuntu系统不要使用里面的别名,使用数字代号即可。

TIP

系统参数一律是小写的系统名字拼接版本号,如:debian11,ubuntu22等。 (自修补镜像支持一些偏门系统,如 centos6、centos7、debian8、debian9 等)

所有系统的CT默认用户名是root

TIP

当然有时候会存在特殊情况,version可能是current/base,此时系统参数仅使用英文系统名字即可,如 archlinux、gentoo、kali。

单独开设LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 自动开设NAT服务器,默认使用Debian11镜像,也可自定义系统
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部配置好网络以及登陆信息,大概需要3分钟
  • 默认开设的网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

各参数含义

shell
# ./buildct.sh CTID 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6(默认为N)

测试示例

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

开设完毕可执行cat ct111查看信息,或在web端的NOTES查看

以下为开设的示例CT的信息:

属性
CTID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小5G
SSH端口20001
80端口20002
443端口20003
内外网映射端口一致的区间30000到30025
系统debian11
宿主机的存储盘local
IPV6

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除指定容器

  • 停止CT
  • 删除CT
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应CTID的容器,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个CTID即可,可一次性删除多个

批量开设NAT的LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成CT容器,但需要注意的是宿主机内存记得开点swap免得机器炸了开SWAP点我跳转
  • 每个容器创建之间有间隔等待60秒避免突发性能不足
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

开设完毕可执行cat ctlog查看信息,或在web端的NOTES查看

删除所有CT

  • 删除所有CT
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际容器仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应容器编号的V6地址绑定到容器上
  • 系统的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

各参数含义

shell
# ./buildct_onlyv6.sh CTID 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

创建示例

shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的容器

属性
容器类型CT
CTID152
用户名root
密码oneclick123
CPU核心数1
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除示例

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
`,78),o=[n];function e(c,r,C,i,y,d){return a(),l("div",null,o)}const h=s(t,[["render",e]]);export{D as __pageData,h as default}; diff --git a/assets/guide_pve_pve_lxc.md.D_RYunJp.js b/assets/guide_pve_pve_lxc.md.D_RYunJp.js new file mode 100644 index 0000000000..a9629793e9 --- /dev/null +++ b/assets/guide_pve_pve_lxc.md.D_RYunJp.js @@ -0,0 +1,12 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"LXC容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_lxc.md","filePath":"guide/pve/pve_lxc.md","lastUpdated":1747984962000}'),e={name:"guide/pve/pve_lxc.md"};function h(p,s,n,k,d,r){return t(),a("div",null,s[0]||(s[0]=[l(`

LXC容器

WARNING

如果你需要在一台服务器上开启超过200个LXC容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

开设LXC容器可使用的镜像

x86_64:

自动修补镜像:https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

每日自动拉取进行编译和修补

手动修补镜像: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

其中的部分镜像有缺陷,不保证所有PVE可用,名字为 ubuntu16.04debian6centos7opensuse42.2opensuse42.3 非必要不要使用。

执行pveam available --section system查看官方可用的系统名字和版本号

优先级:自修补镜像(Proxmox-VE 5及其以下版本不支持) > 官方默认镜像(都支持)

已通过脚本自动识别版本使用对应镜像

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

可在上面的文件中查看支持的系统,其中列出的debian和ubuntu系统不要使用里面的别名,使用数字代号即可。

TIP

系统参数一律是小写的系统名字拼接版本号,如:debian11,ubuntu22等。 (自修补镜像支持一些偏门系统,如 centos6、centos7、debian8、debian9 等)

所有系统的CT默认用户名是root

TIP

当然有时候会存在特殊情况,version可能是current/base,此时系统参数仅使用英文系统名字即可,如 archlinux、gentoo、kali。

单独开设LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 自动开设NAT服务器,默认使用Debian11镜像,也可自定义系统
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部配置好网络以及登陆信息,大概需要3分钟
  • 默认开设的网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

各参数含义

shell
# ./buildct.sh CTID 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6(默认为N)

测试示例

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

开设完毕可执行cat ct111查看信息,或在web端的NOTES查看

以下为开设的示例CT的信息:

属性
CTID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小5G
SSH端口20001
80端口20002
443端口20003
内外网映射端口一致的区间30000到30025
系统debian11
宿主机的存储盘local
IPV6

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除指定容器

  • 停止CT
  • 删除CT
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应CTID的容器,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个CTID即可,可一次性删除多个

批量开设NAT的LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成CT容器,但需要注意的是宿主机内存记得开点swap免得机器炸了开SWAP点我跳转
  • 每个容器创建之间有间隔等待60秒避免突发性能不足
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

开设完毕可执行cat ctlog查看信息,或在web端的NOTES查看

删除所有CT

  • 删除所有CT
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
+rm -rf ct*
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际容器仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应容器编号的V6地址绑定到容器上
  • 系统的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

各参数含义

shell
# ./buildct_onlyv6.sh CTID 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

创建示例

shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的容器

属性
容器类型CT
CTID152
用户名root
密码oneclick123
CPU核心数1
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除示例

shell
rm -rf ct*
+pct stop 152 
+pct destroy 152
+systemctl restart ndpresponder.service
`,78)]))}const F=i(e,[["render",h]]);export{o as __pageData,F as default}; diff --git a/assets/guide_pve_pve_lxc.md.D_RYunJp.lean.js b/assets/guide_pve_pve_lxc.md.D_RYunJp.lean.js new file mode 100644 index 0000000000..7dbc70d45c --- /dev/null +++ b/assets/guide_pve_pve_lxc.md.D_RYunJp.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"LXC容器","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_lxc.md","filePath":"guide/pve/pve_lxc.md","lastUpdated":1747984962000}'),e={name:"guide/pve/pve_lxc.md"};function h(p,s,n,k,d,r){return t(),a("div",null,s[0]||(s[0]=[l("",78)]))}const F=i(e,[["render",h]]);export{o as __pageData,F as default}; diff --git a/assets/guide_pve_pve_macos.md.21762f54.js b/assets/guide_pve_pve_macos.md.21762f54.js deleted file mode 100644 index 38922a02fc..0000000000 --- a/assets/guide_pve_pve_macos.md.21762f54.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as s,v as a,b as o,R as p}from"./chunks/framework.70afa331.js";import{_ as l}from"./chunks/wk7.6fe7513d.js";const e="/assets/mac0.935d53f3.png",n="/assets/mac00.4296be7b.png",c="/assets/mac1.3307e401.png",t="/assets/mac2.da6ce0bc.png",r="/assets/mac3.76a50b9f.png",i="/assets/mac4.c341ba50.png",d="/assets/mac5.39e1c9a4.png",C="/assets/mac6.1cc0462b.png",m="/assets/mac7.181275ae.png",y="/assets/mac8.dd556f02.png",h="/assets/mac9.c5d88eba.png",A="/assets/mac10.e9c284db.png",D="/assets/mac11.a7587e0e.png",g="/assets/mac12.06b051d3.png",u="/assets/mac13.7d4e3199.png",_="/assets/mac14.39a58b6a.png",b="/assets/mac15.f151793c.png",v="/assets/mac16.eae177db.png",F="/assets/mac17.be61913a.png",E="/assets/mac18.f9454618.png",B="/assets/mac19.845f5510.png",f="/assets/mac20.49a5800c.png",k="/assets/mac21.2c30b60f.png",z=JSON.parse('{"title":"开设MacOS虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_macos.md","filePath":"guide/pve/pve_macos.md","lastUpdated":1747972048000}'),x={name:"guide/pve/pve_macos.md"},P=p(`

开设MacOS虚拟机

前置需求

系统和硬件配置要求 --> 检测环境

只有检测环境检测出宿主机支持KVM嵌套虚拟化时,才可以开设MACOS虚拟机,否则会被硬件识别无法开设。

前置环境设置

  • 自动识别 CPU 类型(AMD 或 Intel),并根据类型设置嵌套虚拟化参数。
  • 修改 GRUB 启动参数,启用 IOMMU 和禁用默认 framebuffer。
  • 添加 VFIO 模块支持,便于直通硬件设备。
  • 黑名单声卡和显卡驱动模块,避免与 macOS 冲突。
  • 配置 KVM 相关内核参数,忽略 MSR 错误,提高兼容性。
  • 修补 Proxmox 前端状态检测逻辑,绕过状态限制。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

执行成功后会显示15秒后重启本机,这是正常的流程,不重启无法使得内核参数生效。

系统镜像下载

  • 所有镜像已预装组件,体积较大(最小约4.9GB),下载与解压任务将后台挂起执行。
  • 镜像为完整系统含所有组件,无需联网即可引导使用。
  • 若系统盘空闲空间不足镜像大小的2倍,将拒绝下载。
  • 镜像为7z压缩格式,下载后需解压才能使用。
  • 可随时查看当前下载与解压任务状态,完成后方可创建虚拟机。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

shell
bash install_macos_images.sh

后台下载任务挂起执行后,可关闭SSH窗口,等待半小时到3个小时(具体等待时间取决于你的服务器带宽大小和连通性),下载iso的7z压缩包。

下载任务执行完毕后,查询显示当前下载任务为空时,就可以选择解压任务执行了,解压挂起执行等待的时间取决于你的服务器CPU性能。

当解压任务执行完毕,查询显示当前解压任务为空时,一切准备工作就算准备好了。

相同类型的任务可以并发,也可以随时取消某个任务,取消时需要输入PID的值。

通过 https://github.com/oneclickvirt/macos 制作的目前支持的镜像压缩包:

# 按系统发布时间从旧到新
-high-sierra.iso.7z (大小: 5.23GB)
-mojave.iso.7z (大小: 6.03GB)
-catalina.iso.7z (大小: 8.33GB)
-big‑sur.iso.7z (大小: 12.21GB)
-monterey.iso.7z (大小: 12.36GB)
-ventura.iso.7z (大小: 12.31GB)
-sonoma.iso.7z (大小: 14.41GB)
-sequoia.iso.7z (大小: 15.02GB)

MACOS虚拟机模板设置

  • 系统high-sierramojavecatalina需要至少2核4G内存40G硬盘进行开设
  • big‑sur及更新版本的MACOS系统需要至少6核6G内存50G硬盘进行开设
  • 系统版本越新(下载的序号越靠后)所需的硬件就越多
  • 所有镜像均为启动盘镜像,未设置任何个人数据,所以关于硬盘分配,登录信息设置,网络设置都需要后续按照说明手动设置
  • 需要手动在web端启动虚拟机,启动前可以查看所有模板是否符合预期再启动

下载模板脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

参数含义

shell
# ./buildvm_macos.sh VMID CPU核数 内存 硬盘 SSH端口 VNC端口 系统 存储盘 独立IPV6(留空默认N)

TIP

这块的硬盘大小只是你开设的虚拟机的硬盘大小,实际开设过程中,程序还会挂载引导盘和系统镜像,所以实际开设一个虚拟机的硬盘需求是 虚拟机硬盘大小+镜像本体大小+引导盘大小(500MB) 请时刻注意你的硬盘空间是否足够开设虚拟机

示例命令

以最旧的版本(high-sierra)为例,实验支持的配置如下(非常卡顿)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

模板开设完毕可执行cat vm100查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID100
CPU核数2
内存大小4096MB
磁盘大小45G
SSH端口44022
VNC端口45901
系统high-sierra
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

MACOS系统引导和安装

前面的流程走完后,面板端可以看到一个灰色的虚拟机待启动

mac0

点击启动后,进入VNC面板,左侧选择框有一个全屏按钮,实际操作时建议全屏操作,避免分辨率问题

mac00

经过大概3分钟的引导盘加载后,屏幕中央靠左侧会显示有一个启动盘可用,直接点击或回车

然后又是大概3~5分钟的启动盘加载后,会出现四个选择框,选择Disk Utility点击进入

mac1

进入后可以看到有三个盘和一个镜像,找到那个盘大小大于40G且名字叫QEMU HARDDISK Media的盘,点击Erase

mac2

此时会出现一个弹窗,需要给name重命名为macos方便后续识别使用,然后点击Erase继续初始化

mac3

初始化完毕后,点击Done

mac4

此时需要退出Disk Utility界面,右上角点击Disk Utility选择Quit Disk Utility退出当前选择框

mac5

然后回到了之前那四个选择框那里,选择Install macOS XXXX(由于我在以Big Sur为示例安装,所以XXXX为Big Sur系统),点击continue

mac6

后续就是继续点击continue,然后点击Agree,然后又是点击Agree

mac7

mac8

mac9

直到又出现那三个盘,但在这块可以那个盘大小大于40G且名字叫macos的盘,选择它,然后点击continue

mac10

一段时间的文件复制硬盘加载(大概跑个12分钟)后,正式进入系统安装环节,这块看你宿主机在哪个地区选哪个

mac11

选择完地区后一路点击continue

mac12

mac13

直到出现数据迁移选项Migration Assistant,选择左下角的Not Now不导入用户数据

mac14

然后就会提示你创建用户,填写用户名和账户名,还有登录所需的密码,设置完毕后点击continue

mac15

然后后面就会一路畅通点击continue,直到系统安装完毕了

网络配置

由于是离线环境进行的系统安装,所以这块需要手动配置静态网络连接宿主机的网桥

右上角点击WIFI按钮,关闭WIFI后,点击Network Preferences ...

mac16

进入设置界面后,点击Advanced按钮,进入高级设置界面

mac17

TCP/IP这一栏填写静态网络配置

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

如果你需要配置IPV6网络,类比上面的IPV4设置,需要填写的会是虚拟机绑定的公网IPV6地址(PVE面板中的Note框有写),子网掩码填128,默认网关填写cat /usr/local/bin/pve_check_ipv6在宿主机执行后显示的地址。

mac18

DNS这一栏填写静态网络的DNS配置

一般加入8.8.8.81.1.1.1足够了,中国境内使用114.114.114.114即可。

mac19

填写完毕且apply后,设置的左上角会显示网络已连通

mac20

此时打开默认的浏览器,随便打开一个网址,都是可访问公网资源的,证明网络已配置成功

mac21

卸载iso镜像

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

Macos系统就是卸载opencore.isoxxxx(安装使用的系统镜像).iso,类似上面示例图片的Windows系统卸载win镜像和virtio镜像一样。

',100),M=[P];function S(q,I,V,G,N,O){return a(),o("div",null,M)}const X=s(x,[["render",S]]);export{z as __pageData,X as default}; diff --git a/assets/guide_pve_pve_macos.md.21762f54.lean.js b/assets/guide_pve_pve_macos.md.21762f54.lean.js deleted file mode 100644 index 38922a02fc..0000000000 --- a/assets/guide_pve_pve_macos.md.21762f54.lean.js +++ /dev/null @@ -1,9 +0,0 @@ -import{_ as s,v as a,b as o,R as p}from"./chunks/framework.70afa331.js";import{_ as l}from"./chunks/wk7.6fe7513d.js";const e="/assets/mac0.935d53f3.png",n="/assets/mac00.4296be7b.png",c="/assets/mac1.3307e401.png",t="/assets/mac2.da6ce0bc.png",r="/assets/mac3.76a50b9f.png",i="/assets/mac4.c341ba50.png",d="/assets/mac5.39e1c9a4.png",C="/assets/mac6.1cc0462b.png",m="/assets/mac7.181275ae.png",y="/assets/mac8.dd556f02.png",h="/assets/mac9.c5d88eba.png",A="/assets/mac10.e9c284db.png",D="/assets/mac11.a7587e0e.png",g="/assets/mac12.06b051d3.png",u="/assets/mac13.7d4e3199.png",_="/assets/mac14.39a58b6a.png",b="/assets/mac15.f151793c.png",v="/assets/mac16.eae177db.png",F="/assets/mac17.be61913a.png",E="/assets/mac18.f9454618.png",B="/assets/mac19.845f5510.png",f="/assets/mac20.49a5800c.png",k="/assets/mac21.2c30b60f.png",z=JSON.parse('{"title":"开设MacOS虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_macos.md","filePath":"guide/pve/pve_macos.md","lastUpdated":1747972048000}'),x={name:"guide/pve/pve_macos.md"},P=p(`

开设MacOS虚拟机

前置需求

系统和硬件配置要求 --> 检测环境

只有检测环境检测出宿主机支持KVM嵌套虚拟化时,才可以开设MACOS虚拟机,否则会被硬件识别无法开设。

前置环境设置

  • 自动识别 CPU 类型(AMD 或 Intel),并根据类型设置嵌套虚拟化参数。
  • 修改 GRUB 启动参数,启用 IOMMU 和禁用默认 framebuffer。
  • 添加 VFIO 模块支持,便于直通硬件设备。
  • 黑名单声卡和显卡驱动模块,避免与 macOS 冲突。
  • 配置 KVM 相关内核参数,忽略 MSR 错误,提高兼容性。
  • 修补 Proxmox 前端状态检测逻辑,绕过状态限制。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

执行成功后会显示15秒后重启本机,这是正常的流程,不重启无法使得内核参数生效。

系统镜像下载

  • 所有镜像已预装组件,体积较大(最小约4.9GB),下载与解压任务将后台挂起执行。
  • 镜像为完整系统含所有组件,无需联网即可引导使用。
  • 若系统盘空闲空间不足镜像大小的2倍,将拒绝下载。
  • 镜像为7z压缩格式,下载后需解压才能使用。
  • 可随时查看当前下载与解压任务状态,完成后方可创建虚拟机。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

shell
bash install_macos_images.sh

后台下载任务挂起执行后,可关闭SSH窗口,等待半小时到3个小时(具体等待时间取决于你的服务器带宽大小和连通性),下载iso的7z压缩包。

下载任务执行完毕后,查询显示当前下载任务为空时,就可以选择解压任务执行了,解压挂起执行等待的时间取决于你的服务器CPU性能。

当解压任务执行完毕,查询显示当前解压任务为空时,一切准备工作就算准备好了。

相同类型的任务可以并发,也可以随时取消某个任务,取消时需要输入PID的值。

通过 https://github.com/oneclickvirt/macos 制作的目前支持的镜像压缩包:

# 按系统发布时间从旧到新
-high-sierra.iso.7z (大小: 5.23GB)
-mojave.iso.7z (大小: 6.03GB)
-catalina.iso.7z (大小: 8.33GB)
-big‑sur.iso.7z (大小: 12.21GB)
-monterey.iso.7z (大小: 12.36GB)
-ventura.iso.7z (大小: 12.31GB)
-sonoma.iso.7z (大小: 14.41GB)
-sequoia.iso.7z (大小: 15.02GB)

MACOS虚拟机模板设置

  • 系统high-sierramojavecatalina需要至少2核4G内存40G硬盘进行开设
  • big‑sur及更新版本的MACOS系统需要至少6核6G内存50G硬盘进行开设
  • 系统版本越新(下载的序号越靠后)所需的硬件就越多
  • 所有镜像均为启动盘镜像,未设置任何个人数据,所以关于硬盘分配,登录信息设置,网络设置都需要后续按照说明手动设置
  • 需要手动在web端启动虚拟机,启动前可以查看所有模板是否符合预期再启动

下载模板脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

参数含义

shell
# ./buildvm_macos.sh VMID CPU核数 内存 硬盘 SSH端口 VNC端口 系统 存储盘 独立IPV6(留空默认N)

TIP

这块的硬盘大小只是你开设的虚拟机的硬盘大小,实际开设过程中,程序还会挂载引导盘和系统镜像,所以实际开设一个虚拟机的硬盘需求是 虚拟机硬盘大小+镜像本体大小+引导盘大小(500MB) 请时刻注意你的硬盘空间是否足够开设虚拟机

示例命令

以最旧的版本(high-sierra)为例,实验支持的配置如下(非常卡顿)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

模板开设完毕可执行cat vm100查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID100
CPU核数2
内存大小4096MB
磁盘大小45G
SSH端口44022
VNC端口45901
系统high-sierra
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

MACOS系统引导和安装

前面的流程走完后,面板端可以看到一个灰色的虚拟机待启动

mac0

点击启动后,进入VNC面板,左侧选择框有一个全屏按钮,实际操作时建议全屏操作,避免分辨率问题

mac00

经过大概3分钟的引导盘加载后,屏幕中央靠左侧会显示有一个启动盘可用,直接点击或回车

然后又是大概3~5分钟的启动盘加载后,会出现四个选择框,选择Disk Utility点击进入

mac1

进入后可以看到有三个盘和一个镜像,找到那个盘大小大于40G且名字叫QEMU HARDDISK Media的盘,点击Erase

mac2

此时会出现一个弹窗,需要给name重命名为macos方便后续识别使用,然后点击Erase继续初始化

mac3

初始化完毕后,点击Done

mac4

此时需要退出Disk Utility界面,右上角点击Disk Utility选择Quit Disk Utility退出当前选择框

mac5

然后回到了之前那四个选择框那里,选择Install macOS XXXX(由于我在以Big Sur为示例安装,所以XXXX为Big Sur系统),点击continue

mac6

后续就是继续点击continue,然后点击Agree,然后又是点击Agree

mac7

mac8

mac9

直到又出现那三个盘,但在这块可以那个盘大小大于40G且名字叫macos的盘,选择它,然后点击continue

mac10

一段时间的文件复制硬盘加载(大概跑个12分钟)后,正式进入系统安装环节,这块看你宿主机在哪个地区选哪个

mac11

选择完地区后一路点击continue

mac12

mac13

直到出现数据迁移选项Migration Assistant,选择左下角的Not Now不导入用户数据

mac14

然后就会提示你创建用户,填写用户名和账户名,还有登录所需的密码,设置完毕后点击continue

mac15

然后后面就会一路畅通点击continue,直到系统安装完毕了

网络配置

由于是离线环境进行的系统安装,所以这块需要手动配置静态网络连接宿主机的网桥

右上角点击WIFI按钮,关闭WIFI后,点击Network Preferences ...

mac16

进入设置界面后,点击Advanced按钮,进入高级设置界面

mac17

TCP/IP这一栏填写静态网络配置

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

如果你需要配置IPV6网络,类比上面的IPV4设置,需要填写的会是虚拟机绑定的公网IPV6地址(PVE面板中的Note框有写),子网掩码填128,默认网关填写cat /usr/local/bin/pve_check_ipv6在宿主机执行后显示的地址。

mac18

DNS这一栏填写静态网络的DNS配置

一般加入8.8.8.81.1.1.1足够了,中国境内使用114.114.114.114即可。

mac19

填写完毕且apply后,设置的左上角会显示网络已连通

mac20

此时打开默认的浏览器,随便打开一个网址,都是可访问公网资源的,证明网络已配置成功

mac21

卸载iso镜像

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

Macos系统就是卸载opencore.isoxxxx(安装使用的系统镜像).iso,类似上面示例图片的Windows系统卸载win镜像和virtio镜像一样。

',100),M=[P];function S(q,I,V,G,N,O){return a(),o("div",null,M)}const X=s(x,[["render",S]]);export{z as __pageData,X as default}; diff --git a/assets/guide_pve_pve_macos.md.CRq8lCuz.js b/assets/guide_pve_pve_macos.md.CRq8lCuz.js new file mode 100644 index 0000000000..43e6472f49 --- /dev/null +++ b/assets/guide_pve_pve_macos.md.CRq8lCuz.js @@ -0,0 +1,9 @@ +import{_ as i}from"./chunks/wk7.Bl1-W8YX.js";import{_ as a,c as t,o as e,ag as p}from"./chunks/framework.CSeR4K32.js";const l="/assets/mac0.CofQ9vw_.png",n="/assets/mac00.DelKhhmr.png",h="/assets/mac1.D7yJtJrl.png",c="/assets/mac2.du7V_m90.png",o="/assets/mac3.BCWQuf_Q.png",d="/assets/mac4.B0L5oLF9.png",r="/assets/mac5.QrcmrZyS.png",k="/assets/mac6.CEnQahaC.png",m="/assets/mac7.Cq44sm3y.png",g="/assets/mac8.CfhgXZ8s.png",F="/assets/mac9.DIA9P3VH.png",u="/assets/mac10.CZg7Yifb.png",C="/assets/mac11.P11nsmhn.png",_="/assets/mac12.DHTBO7ih.png",y="/assets/mac13.DDrsH3zK.png",b="/assets/mac14.dLHoMtJy.png",v="/assets/mac15.vkr7IxY1.png",B="/assets/mac16.CeB_3pKz.png",E="/assets/mac17.qkqeaTbW.png",x="/assets/mac18.ChbyoMxq.png",f="/assets/mac19.C_d085-7.png",P="/assets/mac20.DsWyqQaw.png",S="/assets/mac21.XZ5wILhH.png",O=JSON.parse('{"title":"开设MacOS虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_macos.md","filePath":"guide/pve/pve_macos.md","lastUpdated":1747984962000}'),M={name:"guide/pve/pve_macos.md"};function q(I,s,D,V,A,w){return e(),t("div",null,s[0]||(s[0]=[p(`

开设MacOS虚拟机

前置需求

系统和硬件配置要求 --> 检测环境

只有检测环境检测出宿主机支持KVM嵌套虚拟化时,才可以开设MACOS虚拟机,否则会被硬件识别无法开设。

前置环境设置

  • 自动识别 CPU 类型(AMD 或 Intel),并根据类型设置嵌套虚拟化参数。
  • 修改 GRUB 启动参数,启用 IOMMU 和禁用默认 framebuffer。
  • 添加 VFIO 模块支持,便于直通硬件设备。
  • 黑名单声卡和显卡驱动模块,避免与 macOS 冲突。
  • 配置 KVM 相关内核参数,忽略 MSR 错误,提高兼容性。
  • 修补 Proxmox 前端状态检测逻辑,绕过状态限制。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

执行成功后会显示15秒后重启本机,这是正常的流程,不重启无法使得内核参数生效。

系统镜像下载

  • 所有镜像已预装组件,体积较大(最小约4.9GB),下载与解压任务将后台挂起执行。
  • 镜像为完整系统含所有组件,无需联网即可引导使用。
  • 若系统盘空闲空间不足镜像大小的2倍,将拒绝下载。
  • 镜像为7z压缩格式,下载后需解压才能使用。
  • 可随时查看当前下载与解压任务状态,完成后方可创建虚拟机。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

shell
bash install_macos_images.sh

后台下载任务挂起执行后,可关闭SSH窗口,等待半小时到3个小时(具体等待时间取决于你的服务器带宽大小和连通性),下载iso的7z压缩包。

下载任务执行完毕后,查询显示当前下载任务为空时,就可以选择解压任务执行了,解压挂起执行等待的时间取决于你的服务器CPU性能。

当解压任务执行完毕,查询显示当前解压任务为空时,一切准备工作就算准备好了。

相同类型的任务可以并发,也可以随时取消某个任务,取消时需要输入PID的值。

通过 https://github.com/oneclickvirt/macos 制作的目前支持的镜像压缩包:

# 按系统发布时间从旧到新
+high-sierra.iso.7z (大小: 5.23GB)
+mojave.iso.7z (大小: 6.03GB)
+catalina.iso.7z (大小: 8.33GB)
+big‑sur.iso.7z (大小: 12.21GB)
+monterey.iso.7z (大小: 12.36GB)
+ventura.iso.7z (大小: 12.31GB)
+sonoma.iso.7z (大小: 14.41GB)
+sequoia.iso.7z (大小: 15.02GB)

MACOS虚拟机模板设置

  • 系统high-sierramojavecatalina需要至少2核4G内存40G硬盘进行开设
  • big‑sur及更新版本的MACOS系统需要至少6核6G内存50G硬盘进行开设
  • 系统版本越新(下载的序号越靠后)所需的硬件就越多
  • 所有镜像均为启动盘镜像,未设置任何个人数据,所以关于硬盘分配,登录信息设置,网络设置都需要后续按照说明手动设置
  • 需要手动在web端启动虚拟机,启动前可以查看所有模板是否符合预期再启动

下载模板脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

参数含义

shell
# ./buildvm_macos.sh VMID CPU核数 内存 硬盘 SSH端口 VNC端口 系统 存储盘 独立IPV6(留空默认N)

TIP

这块的硬盘大小只是你开设的虚拟机的硬盘大小,实际开设过程中,程序还会挂载引导盘和系统镜像,所以实际开设一个虚拟机的硬盘需求是 虚拟机硬盘大小+镜像本体大小+引导盘大小(500MB) 请时刻注意你的硬盘空间是否足够开设虚拟机

示例命令

以最旧的版本(high-sierra)为例,实验支持的配置如下(非常卡顿)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

模板开设完毕可执行cat vm100查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID100
CPU核数2
内存大小4096MB
磁盘大小45G
SSH端口44022
VNC端口45901
系统high-sierra
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

MACOS系统引导和安装

前面的流程走完后,面板端可以看到一个灰色的虚拟机待启动

mac0

点击启动后,进入VNC面板,左侧选择框有一个全屏按钮,实际操作时建议全屏操作,避免分辨率问题

mac00

经过大概3分钟的引导盘加载后,屏幕中央靠左侧会显示有一个启动盘可用,直接点击或回车

然后又是大概3~5分钟的启动盘加载后,会出现四个选择框,选择Disk Utility点击进入

mac1

进入后可以看到有三个盘和一个镜像,找到那个盘大小大于40G且名字叫QEMU HARDDISK Media的盘,点击Erase

mac2

此时会出现一个弹窗,需要给name重命名为macos方便后续识别使用,然后点击Erase继续初始化

mac3

初始化完毕后,点击Done

mac4

此时需要退出Disk Utility界面,右上角点击Disk Utility选择Quit Disk Utility退出当前选择框

mac5

然后回到了之前那四个选择框那里,选择Install macOS XXXX(由于我在以Big Sur为示例安装,所以XXXX为Big Sur系统),点击continue

mac6

后续就是继续点击continue,然后点击Agree,然后又是点击Agree

mac7

mac8

mac9

直到又出现那三个盘,但在这块可以那个盘大小大于40G且名字叫macos的盘,选择它,然后点击continue

mac10

一段时间的文件复制硬盘加载(大概跑个12分钟)后,正式进入系统安装环节,这块看你宿主机在哪个地区选哪个

mac11

选择完地区后一路点击continue

mac12

mac13

直到出现数据迁移选项Migration Assistant,选择左下角的Not Now不导入用户数据

mac14

然后就会提示你创建用户,填写用户名和账户名,还有登录所需的密码,设置完毕后点击continue

mac15

然后后面就会一路畅通点击continue,直到系统安装完毕了

网络配置

由于是离线环境进行的系统安装,所以这块需要手动配置静态网络连接宿主机的网桥

右上角点击WIFI按钮,关闭WIFI后,点击Network Preferences ...

mac16

进入设置界面后,点击Advanced按钮,进入高级设置界面

mac17

TCP/IP这一栏填写静态网络配置

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

如果你需要配置IPV6网络,类比上面的IPV4设置,需要填写的会是虚拟机绑定的公网IPV6地址(PVE面板中的Note框有写),子网掩码填128,默认网关填写cat /usr/local/bin/pve_check_ipv6在宿主机执行后显示的地址。

mac18

DNS这一栏填写静态网络的DNS配置

一般加入8.8.8.81.1.1.1足够了,中国境内使用114.114.114.114即可。

mac19

填写完毕且apply后,设置的左上角会显示网络已连通

mac20

此时打开默认的浏览器,随便打开一个网址,都是可访问公网资源的,证明网络已配置成功

mac21

卸载iso镜像

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

Macos系统就是卸载opencore.isoxxxx(安装使用的系统镜像).iso,类似上面示例图片的Windows系统卸载win镜像和virtio镜像一样。

',100)]))}const z=a(M,[["render",q]]);export{O as __pageData,z as default}; diff --git a/assets/guide_pve_pve_macos.md.CRq8lCuz.lean.js b/assets/guide_pve_pve_macos.md.CRq8lCuz.lean.js new file mode 100644 index 0000000000..6d3eb11a52 --- /dev/null +++ b/assets/guide_pve_pve_macos.md.CRq8lCuz.lean.js @@ -0,0 +1 @@ +import{_ as i}from"./chunks/wk7.Bl1-W8YX.js";import{_ as a,c as t,o as e,ag as p}from"./chunks/framework.CSeR4K32.js";const l="/assets/mac0.CofQ9vw_.png",n="/assets/mac00.DelKhhmr.png",h="/assets/mac1.D7yJtJrl.png",c="/assets/mac2.du7V_m90.png",o="/assets/mac3.BCWQuf_Q.png",d="/assets/mac4.B0L5oLF9.png",r="/assets/mac5.QrcmrZyS.png",k="/assets/mac6.CEnQahaC.png",m="/assets/mac7.Cq44sm3y.png",g="/assets/mac8.CfhgXZ8s.png",F="/assets/mac9.DIA9P3VH.png",u="/assets/mac10.CZg7Yifb.png",C="/assets/mac11.P11nsmhn.png",_="/assets/mac12.DHTBO7ih.png",y="/assets/mac13.DDrsH3zK.png",b="/assets/mac14.dLHoMtJy.png",v="/assets/mac15.vkr7IxY1.png",B="/assets/mac16.CeB_3pKz.png",E="/assets/mac17.qkqeaTbW.png",x="/assets/mac18.ChbyoMxq.png",f="/assets/mac19.C_d085-7.png",P="/assets/mac20.DsWyqQaw.png",S="/assets/mac21.XZ5wILhH.png",O=JSON.parse('{"title":"开设MacOS虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_macos.md","filePath":"guide/pve/pve_macos.md","lastUpdated":1747984962000}'),M={name:"guide/pve/pve_macos.md"};function q(I,s,D,V,A,w){return e(),t("div",null,s[0]||(s[0]=[p("",100)]))}const z=a(M,[["render",q]]);export{O as __pageData,z as default}; diff --git a/assets/guide_pve_pve_precheck.md.2c856c99.js b/assets/guide_pve_pve_precheck.md.2c856c99.js deleted file mode 100644 index 40dbcff0e7..0000000000 --- a/assets/guide_pve_pve_precheck.md.2c856c99.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as s,v as a,b as p,R as l}from"./chunks/framework.70afa331.js";const n="/assets/pve_kvm_1.0f7e84f0.png",e="/assets/pve_kvm_2.cefb9578.png",o="/assets/pve_kvm_3.1d307586.png",b=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_precheck.md","filePath":"guide/pve/pve_precheck.md","lastUpdated":1747972048000}'),t={name:"guide/pve/pve_precheck.md"},c=l(`

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果有未适配的商家或机器欢迎联系@spiritlhl_bot,有空会尝试支持一下

WARNING

会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/pve

各种要求

建议debian在使用前尽量使用最新的稳定版本的系统

不要在动态IP的服务器上使用本套脚本(重启机器后自动切换本机IP的服务器暂不支持,重启机器后IP不自动切换的支持)

本项目的一键安装脚本只适配Debian系统,非Debian无法通过APT源安装,官方只给了Debian的镜像,其他系统只能使用ISO安装,或使用自定义分区和常见问题分区中的其他方式解决问题。

  • 系统要求:Debian 8+

TIP

建议debian12而不是debian11,debian11在部分独立服务器上有网络重启的BUG。

  • 硬件要求:2核2G内存x86_64arm架构服务器硬盘至少20G
  • 可开KVM的硬件要求:VM-X或AMD-V支持 (部分VPS和全部独服支持)
  • 如果硬件或系统需求不满足,可使用incus批量开LXC容器跳转

如果使用IPV6隧道进行宿主机的IPV6子网附加,务必在PVE安装成功但网关未自动设置时在对应文件添加内容,不要在一开始(未安装PVE)就进行IPV6隧道的添加。

开设虚拟内存(SWAP)(非必须的可选项)

TIP

内存开点swap免得机器炸了,如果你的宿主机内存不够用硬盘又很多空闲的话

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

检测环境

  • 本项目相关脚本执行前务必执行本脚本检测环境,如果不符合安装PVE的要求则无法使用后续的脚本
  • 检测本机IPV6的网络配置情况(有无IPV6都可安装,只是查询一下罢了)
  • 检测硬件配置是否满足最低要求
  • 检测硬件环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 检测系统环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 不可嵌套虚拟化KVM的服务器不推荐安装PVE,不如使用incus性能更好

国际

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

国内

bash
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

如果你需要更新IPV6信息再查询,那么执行以下命令后再查询

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

执行本项目的检测环境的命令,展示如下

图片

查询如上的只需使用下面的一键脚本自动创建虚拟机即可,无需手动再修改WEB端设置

图片

查询如上的在使用后续脚本创建了虚拟机后,可能需要手动修改WEB端设置,需要关闭对应每个虚拟机的硬件嵌套虚拟化,如下图

图片

先停止虚拟机再修改,修改完后再开机才能使用NOVNC,不关闭可能导致这个虚拟机有BUG无法使用

如果强行安装PVE开KVM,启动不了的也可以关闭这个选项试试能不能启动虚拟机,导致这些问题的原因就是上面说的,宿主机不支持嵌套虚拟化KVM进行加速

TIP

开设虚拟机前请使用screen挂起执行,避免开设时间过长,SSH不稳定导致中间执行中断



',40),r=[c];function i(C,h,d,y,D,A){return a(),p("div",null,r)}const m=s(t,[["render",i]]);export{b as __pageData,m as default}; diff --git a/assets/guide_pve_pve_precheck.md.2c856c99.lean.js b/assets/guide_pve_pve_precheck.md.2c856c99.lean.js deleted file mode 100644 index 40dbcff0e7..0000000000 --- a/assets/guide_pve_pve_precheck.md.2c856c99.lean.js +++ /dev/null @@ -1,3 +0,0 @@ -import{_ as s,v as a,b as p,R as l}from"./chunks/framework.70afa331.js";const n="/assets/pve_kvm_1.0f7e84f0.png",e="/assets/pve_kvm_2.cefb9578.png",o="/assets/pve_kvm_3.1d307586.png",b=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_precheck.md","filePath":"guide/pve/pve_precheck.md","lastUpdated":1747972048000}'),t={name:"guide/pve/pve_precheck.md"},c=l(`

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果有未适配的商家或机器欢迎联系@spiritlhl_bot,有空会尝试支持一下

WARNING

会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/pve

各种要求

建议debian在使用前尽量使用最新的稳定版本的系统

不要在动态IP的服务器上使用本套脚本(重启机器后自动切换本机IP的服务器暂不支持,重启机器后IP不自动切换的支持)

本项目的一键安装脚本只适配Debian系统,非Debian无法通过APT源安装,官方只给了Debian的镜像,其他系统只能使用ISO安装,或使用自定义分区和常见问题分区中的其他方式解决问题。

  • 系统要求:Debian 8+

TIP

建议debian12而不是debian11,debian11在部分独立服务器上有网络重启的BUG。

  • 硬件要求:2核2G内存x86_64arm架构服务器硬盘至少20G
  • 可开KVM的硬件要求:VM-X或AMD-V支持 (部分VPS和全部独服支持)
  • 如果硬件或系统需求不满足,可使用incus批量开LXC容器跳转

如果使用IPV6隧道进行宿主机的IPV6子网附加,务必在PVE安装成功但网关未自动设置时在对应文件添加内容,不要在一开始(未安装PVE)就进行IPV6隧道的添加。

开设虚拟内存(SWAP)(非必须的可选项)

TIP

内存开点swap免得机器炸了,如果你的宿主机内存不够用硬盘又很多空闲的话

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

检测环境

  • 本项目相关脚本执行前务必执行本脚本检测环境,如果不符合安装PVE的要求则无法使用后续的脚本
  • 检测本机IPV6的网络配置情况(有无IPV6都可安装,只是查询一下罢了)
  • 检测硬件配置是否满足最低要求
  • 检测硬件环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 检测系统环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 不可嵌套虚拟化KVM的服务器不推荐安装PVE,不如使用incus性能更好

国际

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

国内

bash
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

如果你需要更新IPV6信息再查询,那么执行以下命令后再查询

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

执行本项目的检测环境的命令,展示如下

图片

查询如上的只需使用下面的一键脚本自动创建虚拟机即可,无需手动再修改WEB端设置

图片

查询如上的在使用后续脚本创建了虚拟机后,可能需要手动修改WEB端设置,需要关闭对应每个虚拟机的硬件嵌套虚拟化,如下图

图片

先停止虚拟机再修改,修改完后再开机才能使用NOVNC,不关闭可能导致这个虚拟机有BUG无法使用

如果强行安装PVE开KVM,启动不了的也可以关闭这个选项试试能不能启动虚拟机,导致这些问题的原因就是上面说的,宿主机不支持嵌套虚拟化KVM进行加速

TIP

开设虚拟机前请使用screen挂起执行,避免开设时间过长,SSH不稳定导致中间执行中断



',40),r=[c];function i(C,h,d,y,D,A){return a(),p("div",null,r)}const m=s(t,[["render",i]]);export{b as __pageData,m as default}; diff --git a/assets/guide_pve_pve_precheck.md.Bwa9qWce.js b/assets/guide_pve_pve_precheck.md.Bwa9qWce.js new file mode 100644 index 0000000000..e9ef4ac830 --- /dev/null +++ b/assets/guide_pve_pve_precheck.md.Bwa9qWce.js @@ -0,0 +1,3 @@ +import{_ as i,c as a,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const e="/assets/pve_kvm_1.BEDy-Dxt.png",l="/assets/pve_kvm_2.C98l0GO8.png",h="/assets/pve_kvm_3.DzuyyWMo.png",b=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_precheck.md","filePath":"guide/pve/pve_precheck.md","lastUpdated":1747984962000}'),n={name:"guide/pve/pve_precheck.md"};function k(r,s,c,d,o,g){return t(),a("div",null,s[0]||(s[0]=[p(`

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果有未适配的商家或机器欢迎联系@spiritlhl_bot,有空会尝试支持一下

WARNING

会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/pve

各种要求

建议debian在使用前尽量使用最新的稳定版本的系统

不要在动态IP的服务器上使用本套脚本(重启机器后自动切换本机IP的服务器暂不支持,重启机器后IP不自动切换的支持)

本项目的一键安装脚本只适配Debian系统,非Debian无法通过APT源安装,官方只给了Debian的镜像,其他系统只能使用ISO安装,或使用自定义分区和常见问题分区中的其他方式解决问题。

  • 系统要求:Debian 8+

TIP

建议debian12而不是debian11,debian11在部分独立服务器上有网络重启的BUG。

  • 硬件要求:2核2G内存x86_64arm架构服务器硬盘至少20G
  • 可开KVM的硬件要求:VM-X或AMD-V支持 (部分VPS和全部独服支持)
  • 如果硬件或系统需求不满足,可使用incus批量开LXC容器跳转

如果使用IPV6隧道进行宿主机的IPV6子网附加,务必在PVE安装成功但网关未自动设置时在对应文件添加内容,不要在一开始(未安装PVE)就进行IPV6隧道的添加。

开设虚拟内存(SWAP)(非必须的可选项)

TIP

内存开点swap免得机器炸了,如果你的宿主机内存不够用硬盘又很多空闲的话

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

检测环境

  • 本项目相关脚本执行前务必执行本脚本检测环境,如果不符合安装PVE的要求则无法使用后续的脚本
  • 检测本机IPV6的网络配置情况(有无IPV6都可安装,只是查询一下罢了)
  • 检测硬件配置是否满足最低要求
  • 检测硬件环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 检测系统环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 不可嵌套虚拟化KVM的服务器不推荐安装PVE,不如使用incus性能更好

国际

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

国内

bash
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

如果你需要更新IPV6信息再查询,那么执行以下命令后再查询

bash
rm -rf /usr/local/bin/pve_ipv6*
+rm -rf /usr/local/bin/pve_check_ipv6*
+rm -rf /usr/local/bin/pve_last_ipv6*

执行本项目的检测环境的命令,展示如下

图片

查询如上的只需使用下面的一键脚本自动创建虚拟机即可,无需手动再修改WEB端设置

图片

查询如上的在使用后续脚本创建了虚拟机后,可能需要手动修改WEB端设置,需要关闭对应每个虚拟机的硬件嵌套虚拟化,如下图

图片

先停止虚拟机再修改,修改完后再开机才能使用NOVNC,不关闭可能导致这个虚拟机有BUG无法使用

如果强行安装PVE开KVM,启动不了的也可以关闭这个选项试试能不能启动虚拟机,导致这些问题的原因就是上面说的,宿主机不支持嵌套虚拟化KVM进行加速

TIP

开设虚拟机前请使用screen挂起执行,避免开设时间过长,SSH不稳定导致中间执行中断



',40)]))}const u=i(n,[["render",k]]);export{b as __pageData,u as default}; diff --git a/assets/guide_pve_pve_precheck.md.Bwa9qWce.lean.js b/assets/guide_pve_pve_precheck.md.Bwa9qWce.lean.js new file mode 100644 index 0000000000..364af26a7b --- /dev/null +++ b/assets/guide_pve_pve_precheck.md.Bwa9qWce.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as p}from"./chunks/framework.CSeR4K32.js";const e="/assets/pve_kvm_1.BEDy-Dxt.png",l="/assets/pve_kvm_2.C98l0GO8.png",h="/assets/pve_kvm_3.DzuyyWMo.png",b=JSON.parse('{"title":"前言","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_precheck.md","filePath":"guide/pve/pve_precheck.md","lastUpdated":1747984962000}'),n={name:"guide/pve/pve_precheck.md"};function k(r,s,c,d,o,g){return t(),a("div",null,s[0]||(s[0]=[p("",40)]))}const u=i(n,[["render",k]]);export{b as __pageData,u as default}; diff --git a/assets/guide_pve_pve_qa.md.76a49097.js b/assets/guide_pve_pve_qa.md.76a49097.js deleted file mode 100644 index 106159d9bd..0000000000 --- a/assets/guide_pve_pve_qa.md.76a49097.js +++ /dev/null @@ -1,13 +0,0 @@ -import{_ as s,v as a,b as e,R as l}from"./chunks/framework.70afa331.js";const o="/assets/onlinepkg.30da8d76.png",n="/assets/dns0.1beb9fa7.png",u=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_qa.md","filePath":"guide/pve/pve_qa.md","lastUpdated":1747972048000}'),p={name:"guide/pve/pve_qa.md"},t=l(`

解惑

执行脚本不到30秒机器就掉线了

原装系统执行

systemctl restart networking

看看是不是直接掉线,如果是那就是机器原生有问题,热插拔或者dhcp导致的网络无法自重启,此时建议更换宿主机的系统或DD一个新系统尝试

一般来说这种情况都是出现在独服的Debian11系统上,切换为Debian12系统就没问题了

安装PVE失败且报错显示某些安装包不存在

执行下述命令查询apt的源

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

如果看到

deb file://
-deb cdrom:[

这种开头的行,那么证明宿主机使用的是本地源而不是网络源,需要替换/etc/apt/sources.list的源,如

图片

一样替换为网络源才可使用PVE一键安装脚本进行安装。

替换网络源

国内服务器可使用

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)

国外服务器可使用

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

进行apt源的替换

安装PVE成功但重启后失联

如果什么机器安装PVE成功后WEB可用,但重启失联,请安装成功PVE后,重启前执行以下命令再重启

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

然后将重启失联的机器报给 @spiritlhl_bot 待更新脚本自动修复

安装PVE成功但重启后无法解析网址

常见于低版本的Debian系统(云服务器)安装PVE重启后无论访问什么网址都报错

curl: (6) Could not resolve host:

此时查看文件

cat /etc/resolv.conf

可发现无nameserver开头的语句

需要在web端这个页面设置DNS

screenshot-1708136079861

设置完成后再次查看文件会发现有如下内容

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

此时再去请求网址就能解析成功了

安装PVE失败或非Debian系统

如果有什么机器安装不了,着急的可以尝试使用以下仓库的脚本先重装为debian12先

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明,一个常见的问题是机器是raid0不是raid10,需要加参数指定raid的值

如果有空或者还是不行,请联系 @spiritlhl_bot 尝试

非Debian系统也可使用自定义分区的内容自行尝试

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

不小心删除了NAT的映射规则怎么办

先查看

cat /etc/iptables/rules.v4

检测是否有问题,且备份数据到本地避免被覆盖

然后再使用下面的命令映射回来

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

检测是不是商家虚标IPV6子网大小导致无法开设独立IPV6地址的虚拟机/容器

使用以下命令在纯净的未安装ProxmoxVE的机器上测试实际的子网掩码大小

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

如果检测结果为128证明商家虚标子网大小,仅一个IPV6地址无法额外分配给虚拟机/容器。

在现有的 PVE 中纳管新的 PVE(创建 / 加入集群)

为了将两个独立的 Proxmox VE 实例组成一个集群,需满足以下前提条件:

集群前提条件

  1. 主机名唯一
    两个节点的 hostname 不可相同,避免命名冲突。建议使用诸如 pve1pve2 等命名方式。

  2. VMID 唯一
    两台 PVE 上不能存在相同 VMID 的虚拟机或容器。若存在冲突,请调整 VMID 以避免合并时发生冲突。

  3. 网络互通、延迟低
    两台主机之间必须能互相 ping 通,建议网络延迟低(局域网或高速公网),以保障集群通信质量。

创建集群(在任意节点执行)

  1. 登录主节点(如 pve1)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Create Cluster
  3. 输入集群名称(Cluster Name)。
  4. 选择要用于集群通信的网卡(如仅有公网 IP,可选择此网卡)。
  5. 点击 Create 创建集群。
  6. 创建成功后,点击 Join Information,复制该页面显示的信息备用。

PS: 在哪个节点上创建集群都可以,集群中不分主从节点。

加入集群(在第二个节点执行)

  1. 登录待加入节点(如 pve2)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Join Cluster
  3. pve1Join Information 粘贴到输入框中。
  4. 填入 pve1 上具的 root 用户密码到 Peer Password
  5. 点击 Join 开始加入过程。
  6. 等待页面提示成功后,刷新页面或重新登录,即可看到两个节点已组成集群。

集群优势

  • 集群节点间可共享资源、迁移虚拟机。
  • 互传 ISO 镜像或模板更加便捷。

目前已验证的VPS商家

可开设KVM虚拟化的NAT的商家

spartanhost 中的独立服务器的Debian12(Debian11有问题)

interserver 中的VPS或独立服务器

frantech 中的拉斯维加斯第二档

eugamehost 中的美国凤凰城黑五促销款

amhost 中的测试款

digitalocean 中的 Perminu Intel 和 Regular 4核款

skrime 中的 AMD Ryzen KVM Server 最低配款

webdock 中的 AMD KVM Server

4vps 中的 俄罗斯和希腊 测试款

adtaq 中的最低配存储KVM服务器

nocix 中的独立服务器

online.net 中的低配独立服务器的Debian12(Debian11有问题)

OVH 中的 Public Cloud 服务器 需要使用以下命令dd为纯净系统后安装

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明。一个常见的问题是OVH独立服务器进行dd,需要源系统默认重装为raid1的debian12,然后用参数指定dd为raid0,才能成功,使用如下命令

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

只可开设LXC虚拟化的NAT的商家

腾讯云 中的无忧款和特惠款(学生机)

spectraip 中的KVM服务器

Linode 中美国专用CPU的最低配

hosthatch 中的特价高配服务器

hetzner 的cloud服务器

rackdog 的浮动IP的服务器

vultr 的Cloud普通服务器

azure 的普通机器

scaleway 中的ARM架构的服务器

aws 中的ec2实例

Google cloud platform - GCP 的 AMD 服务器

`,106),r=[t];function c(i,C,h,y,d,D){return a(),e("div",null,r)}const b=s(p,[["render",c]]);export{u as __pageData,b as default}; diff --git a/assets/guide_pve_pve_qa.md.76a49097.lean.js b/assets/guide_pve_pve_qa.md.76a49097.lean.js deleted file mode 100644 index 106159d9bd..0000000000 --- a/assets/guide_pve_pve_qa.md.76a49097.lean.js +++ /dev/null @@ -1,13 +0,0 @@ -import{_ as s,v as a,b as e,R as l}from"./chunks/framework.70afa331.js";const o="/assets/onlinepkg.30da8d76.png",n="/assets/dns0.1beb9fa7.png",u=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_qa.md","filePath":"guide/pve/pve_qa.md","lastUpdated":1747972048000}'),p={name:"guide/pve/pve_qa.md"},t=l(`

解惑

执行脚本不到30秒机器就掉线了

原装系统执行

systemctl restart networking

看看是不是直接掉线,如果是那就是机器原生有问题,热插拔或者dhcp导致的网络无法自重启,此时建议更换宿主机的系统或DD一个新系统尝试

一般来说这种情况都是出现在独服的Debian11系统上,切换为Debian12系统就没问题了

安装PVE失败且报错显示某些安装包不存在

执行下述命令查询apt的源

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

如果看到

deb file://
-deb cdrom:[

这种开头的行,那么证明宿主机使用的是本地源而不是网络源,需要替换/etc/apt/sources.list的源,如

图片

一样替换为网络源才可使用PVE一键安装脚本进行安装。

替换网络源

国内服务器可使用

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)

国外服务器可使用

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

进行apt源的替换

安装PVE成功但重启后失联

如果什么机器安装PVE成功后WEB可用,但重启失联,请安装成功PVE后,重启前执行以下命令再重启

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

然后将重启失联的机器报给 @spiritlhl_bot 待更新脚本自动修复

安装PVE成功但重启后无法解析网址

常见于低版本的Debian系统(云服务器)安装PVE重启后无论访问什么网址都报错

curl: (6) Could not resolve host:

此时查看文件

cat /etc/resolv.conf

可发现无nameserver开头的语句

需要在web端这个页面设置DNS

screenshot-1708136079861

设置完成后再次查看文件会发现有如下内容

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

此时再去请求网址就能解析成功了

安装PVE失败或非Debian系统

如果有什么机器安装不了,着急的可以尝试使用以下仓库的脚本先重装为debian12先

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明,一个常见的问题是机器是raid0不是raid10,需要加参数指定raid的值

如果有空或者还是不行,请联系 @spiritlhl_bot 尝试

非Debian系统也可使用自定义分区的内容自行尝试

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

不小心删除了NAT的映射规则怎么办

先查看

cat /etc/iptables/rules.v4

检测是否有问题,且备份数据到本地避免被覆盖

然后再使用下面的命令映射回来

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

检测是不是商家虚标IPV6子网大小导致无法开设独立IPV6地址的虚拟机/容器

使用以下命令在纯净的未安装ProxmoxVE的机器上测试实际的子网掩码大小

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

如果检测结果为128证明商家虚标子网大小,仅一个IPV6地址无法额外分配给虚拟机/容器。

在现有的 PVE 中纳管新的 PVE(创建 / 加入集群)

为了将两个独立的 Proxmox VE 实例组成一个集群,需满足以下前提条件:

集群前提条件

  1. 主机名唯一
    两个节点的 hostname 不可相同,避免命名冲突。建议使用诸如 pve1pve2 等命名方式。

  2. VMID 唯一
    两台 PVE 上不能存在相同 VMID 的虚拟机或容器。若存在冲突,请调整 VMID 以避免合并时发生冲突。

  3. 网络互通、延迟低
    两台主机之间必须能互相 ping 通,建议网络延迟低(局域网或高速公网),以保障集群通信质量。

创建集群(在任意节点执行)

  1. 登录主节点(如 pve1)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Create Cluster
  3. 输入集群名称(Cluster Name)。
  4. 选择要用于集群通信的网卡(如仅有公网 IP,可选择此网卡)。
  5. 点击 Create 创建集群。
  6. 创建成功后,点击 Join Information,复制该页面显示的信息备用。

PS: 在哪个节点上创建集群都可以,集群中不分主从节点。

加入集群(在第二个节点执行)

  1. 登录待加入节点(如 pve2)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Join Cluster
  3. pve1Join Information 粘贴到输入框中。
  4. 填入 pve1 上具的 root 用户密码到 Peer Password
  5. 点击 Join 开始加入过程。
  6. 等待页面提示成功后,刷新页面或重新登录,即可看到两个节点已组成集群。

集群优势

  • 集群节点间可共享资源、迁移虚拟机。
  • 互传 ISO 镜像或模板更加便捷。

目前已验证的VPS商家

可开设KVM虚拟化的NAT的商家

spartanhost 中的独立服务器的Debian12(Debian11有问题)

interserver 中的VPS或独立服务器

frantech 中的拉斯维加斯第二档

eugamehost 中的美国凤凰城黑五促销款

amhost 中的测试款

digitalocean 中的 Perminu Intel 和 Regular 4核款

skrime 中的 AMD Ryzen KVM Server 最低配款

webdock 中的 AMD KVM Server

4vps 中的 俄罗斯和希腊 测试款

adtaq 中的最低配存储KVM服务器

nocix 中的独立服务器

online.net 中的低配独立服务器的Debian12(Debian11有问题)

OVH 中的 Public Cloud 服务器 需要使用以下命令dd为纯净系统后安装

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明。一个常见的问题是OVH独立服务器进行dd,需要源系统默认重装为raid1的debian12,然后用参数指定dd为raid0,才能成功,使用如下命令

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

只可开设LXC虚拟化的NAT的商家

腾讯云 中的无忧款和特惠款(学生机)

spectraip 中的KVM服务器

Linode 中美国专用CPU的最低配

hosthatch 中的特价高配服务器

hetzner 的cloud服务器

rackdog 的浮动IP的服务器

vultr 的Cloud普通服务器

azure 的普通机器

scaleway 中的ARM架构的服务器

aws 中的ec2实例

Google cloud platform - GCP 的 AMD 服务器

`,106),r=[t];function c(i,C,h,y,d,D){return a(),e("div",null,r)}const b=s(p,[["render",c]]);export{u as __pageData,b as default}; diff --git a/assets/guide_pve_pve_qa.md.KEIUXkXN.js b/assets/guide_pve_pve_qa.md.KEIUXkXN.js new file mode 100644 index 0000000000..d6618d253a --- /dev/null +++ b/assets/guide_pve_pve_qa.md.KEIUXkXN.js @@ -0,0 +1,13 @@ +import{_ as a,c as i,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/onlinepkg.-C5qKOrj.png",p="/assets/dns0.DDagSewr.png",F=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_qa.md","filePath":"guide/pve/pve_qa.md","lastUpdated":1747984962000}'),l={name:"guide/pve/pve_qa.md"};function h(r,s,o,k,d,c){return e(),i("div",null,s[0]||(s[0]=[t(`

解惑

执行脚本不到30秒机器就掉线了

原装系统执行

systemctl restart networking

看看是不是直接掉线,如果是那就是机器原生有问题,热插拔或者dhcp导致的网络无法自重启,此时建议更换宿主机的系统或DD一个新系统尝试

一般来说这种情况都是出现在独服的Debian11系统上,切换为Debian12系统就没问题了

安装PVE失败且报错显示某些安装包不存在

执行下述命令查询apt的源

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

如果看到

deb file://
+deb cdrom:[

这种开头的行,那么证明宿主机使用的是本地源而不是网络源,需要替换/etc/apt/sources.list的源,如

图片

一样替换为网络源才可使用PVE一键安装脚本进行安装。

替换网络源

国内服务器可使用

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)

国外服务器可使用

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

进行apt源的替换

安装PVE成功但重启后失联

如果什么机器安装PVE成功后WEB可用,但重启失联,请安装成功PVE后,重启前执行以下命令再重启

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
+if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
+    chattr -i /etc/network/interfaces
+    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
+    chattr +i /etc/network/interfaces
+fi

然后将重启失联的机器报给 @spiritlhl_bot 待更新脚本自动修复

安装PVE成功但重启后无法解析网址

常见于低版本的Debian系统(云服务器)安装PVE重启后无论访问什么网址都报错

curl: (6) Could not resolve host:

此时查看文件

cat /etc/resolv.conf

可发现无nameserver开头的语句

需要在web端这个页面设置DNS

screenshot-1708136079861

设置完成后再次查看文件会发现有如下内容

search .
+nameserver 8.8.8.8
+nameserver 8.8.4.4

此时再去请求网址就能解析成功了

安装PVE失败或非Debian系统

如果有什么机器安装不了,着急的可以尝试使用以下仓库的脚本先重装为debian12先

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明,一个常见的问题是机器是raid0不是raid10,需要加参数指定raid的值

如果有空或者还是不行,请联系 @spiritlhl_bot 尝试

非Debian系统也可使用自定义分区的内容自行尝试

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

不小心删除了NAT的映射规则怎么办

先查看

cat /etc/iptables/rules.v4

检测是否有问题,且备份数据到本地避免被覆盖

然后再使用下面的命令映射回来

shell
iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+cat /etc/iptables/rules.v4 | iptables-restore

检测是不是商家虚标IPV6子网大小导致无法开设独立IPV6地址的虚拟机/容器

使用以下命令在纯净的未安装ProxmoxVE的机器上测试实际的子网掩码大小

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

如果检测结果为128证明商家虚标子网大小,仅一个IPV6地址无法额外分配给虚拟机/容器。

在现有的 PVE 中纳管新的 PVE(创建 / 加入集群)

为了将两个独立的 Proxmox VE 实例组成一个集群,需满足以下前提条件:

集群前提条件

  1. 主机名唯一
    两个节点的 hostname 不可相同,避免命名冲突。建议使用诸如 pve1pve2 等命名方式。

  2. VMID 唯一
    两台 PVE 上不能存在相同 VMID 的虚拟机或容器。若存在冲突,请调整 VMID 以避免合并时发生冲突。

  3. 网络互通、延迟低
    两台主机之间必须能互相 ping 通,建议网络延迟低(局域网或高速公网),以保障集群通信质量。

创建集群(在任意节点执行)

  1. 登录主节点(如 pve1)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Create Cluster
  3. 输入集群名称(Cluster Name)。
  4. 选择要用于集群通信的网卡(如仅有公网 IP,可选择此网卡)。
  5. 点击 Create 创建集群。
  6. 创建成功后,点击 Join Information,复制该页面显示的信息备用。

PS: 在哪个节点上创建集群都可以,集群中不分主从节点。

加入集群(在第二个节点执行)

  1. 登录待加入节点(如 pve2)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Join Cluster
  3. pve1Join Information 粘贴到输入框中。
  4. 填入 pve1 上具的 root 用户密码到 Peer Password
  5. 点击 Join 开始加入过程。
  6. 等待页面提示成功后,刷新页面或重新登录,即可看到两个节点已组成集群。

集群优势

  • 集群节点间可共享资源、迁移虚拟机。
  • 互传 ISO 镜像或模板更加便捷。

目前已验证的VPS商家

可开设KVM虚拟化的NAT的商家

spartanhost 中的独立服务器的Debian12(Debian11有问题)

interserver 中的VPS或独立服务器

frantech 中的拉斯维加斯第二档

eugamehost 中的美国凤凰城黑五促销款

amhost 中的测试款

digitalocean 中的 Perminu Intel 和 Regular 4核款

skrime 中的 AMD Ryzen KVM Server 最低配款

webdock 中的 AMD KVM Server

4vps 中的 俄罗斯和希腊 测试款

adtaq 中的最低配存储KVM服务器

nocix 中的独立服务器

online.net 中的低配独立服务器的Debian12(Debian11有问题)

OVH 中的 Public Cloud 服务器 需要使用以下命令dd为纯净系统后安装

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明。一个常见的问题是OVH独立服务器进行dd,需要源系统默认重装为raid1的debian12,然后用参数指定dd为raid0,才能成功,使用如下命令

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

只可开设LXC虚拟化的NAT的商家

腾讯云 中的无忧款和特惠款(学生机)

spectraip 中的KVM服务器

Linode 中美国专用CPU的最低配

hosthatch 中的特价高配服务器

hetzner 的cloud服务器

rackdog 的浮动IP的服务器

vultr 的Cloud普通服务器

azure 的普通机器

scaleway 中的ARM架构的服务器

aws 中的ec2实例

Google cloud platform - GCP 的 AMD 服务器

`,106)]))}const u=a(l,[["render",h]]);export{F as __pageData,u as default}; diff --git a/assets/guide_pve_pve_qa.md.KEIUXkXN.lean.js b/assets/guide_pve_pve_qa.md.KEIUXkXN.lean.js new file mode 100644 index 0000000000..b612433632 --- /dev/null +++ b/assets/guide_pve_pve_qa.md.KEIUXkXN.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as e,ag as t}from"./chunks/framework.CSeR4K32.js";const n="/assets/onlinepkg.-C5qKOrj.png",p="/assets/dns0.DDagSewr.png",F=JSON.parse('{"title":"解惑","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_qa.md","filePath":"guide/pve/pve_qa.md","lastUpdated":1747984962000}'),l={name:"guide/pve/pve_qa.md"};function h(r,s,o,k,d,c){return e(),i("div",null,s[0]||(s[0]=[t("",106)]))}const u=a(l,[["render",h]]);export{F as __pageData,u as default}; diff --git a/assets/guide_pve_pve_thanks.md.3bbf24dc.js b/assets/guide_pve_pve_thanks.md.3bbf24dc.js deleted file mode 100644 index bd58b04f21..0000000000 --- a/assets/guide_pve_pve_thanks.md.3bbf24dc.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/pve_thanks.md","filePath":"guide/pve/pve_thanks.md","lastUpdated":1747972048000}'),a={name:"guide/pve/pve_thanks.md"},p=o('

致谢

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 提供的PVE指导

',16),n=[p];function i(s,h,l,m,c,b){return e(),t("div",null,n)}const f=r(a,[["render",i]]);export{u as __pageData,f as default}; diff --git a/assets/guide_pve_pve_thanks.md.3bbf24dc.lean.js b/assets/guide_pve_pve_thanks.md.3bbf24dc.lean.js deleted file mode 100644 index bd58b04f21..0000000000 --- a/assets/guide_pve_pve_thanks.md.3bbf24dc.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as r,v as e,b as t,R as o}from"./chunks/framework.70afa331.js";const u=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/pve_thanks.md","filePath":"guide/pve/pve_thanks.md","lastUpdated":1747972048000}'),a={name:"guide/pve/pve_thanks.md"},p=o('

致谢

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 提供的PVE指导

',16),n=[p];function i(s,h,l,m,c,b){return e(),t("div",null,n)}const f=r(a,[["render",i]]);export{u as __pageData,f as default}; diff --git a/assets/guide_pve_pve_thanks.md.DqgEZrWa.js b/assets/guide_pve_pve_thanks.md.DqgEZrWa.js new file mode 100644 index 0000000000..a7a9b95f14 --- /dev/null +++ b/assets/guide_pve_pve_thanks.md.DqgEZrWa.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/pve_thanks.md","filePath":"guide/pve/pve_thanks.md","lastUpdated":1747984962000}'),p={name:"guide/pve/pve_thanks.md"};function n(i,r,h,s,l,m){return a(),t("div",null,r[0]||(r[0]=[o('

致谢

https://forum.proxmox.com/

https://blog.ilolicon.com/archives/615

https://github.com/Ella-Alinda/somescripts/blob/main/nat.sh

https://pve.proxmox.com/pve-docs/qm.1.html

https://down.idc.wiki/Image/realServer-Template/

https://mirrors.tuna.tsinghua.edu.cn/proxmox/

https://github.com/roacn/pve/blob/main/pve.sh

https://github.com/spiritLHLS/lxc

https://github.com/leitbogioro/Tools

https://github.com/jiangcuo/Proxmox-Port

https://gitlab.com/minkebox/pimox

https://github.com/jiangcuo/run_proxmox_in_docker

https://github.com/yoursunny/ndpresponder

https://github.com/SuperManito/LinuxMirrors

感谢 @Ella-Alinda 提供的PVE指导

',16)]))}const b=e(p,[["render",n]]);export{g as __pageData,b as default}; diff --git a/assets/guide_pve_pve_thanks.md.DqgEZrWa.lean.js b/assets/guide_pve_pve_thanks.md.DqgEZrWa.lean.js new file mode 100644 index 0000000000..79185767dc --- /dev/null +++ b/assets/guide_pve_pve_thanks.md.DqgEZrWa.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a,ag as o}from"./chunks/framework.CSeR4K32.js";const g=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pve/pve_thanks.md","filePath":"guide/pve/pve_thanks.md","lastUpdated":1747984962000}'),p={name:"guide/pve/pve_thanks.md"};function n(i,r,h,s,l,m){return a(),t("div",null,r[0]||(r[0]=[o("",16)]))}const b=e(p,[["render",n]]);export{g as __pageData,b as default}; diff --git a/assets/guide_pve_pve_windows.md.37289db4.js b/assets/guide_pve_pve_windows.md.37289db4.js deleted file mode 100644 index b81c793917..0000000000 --- a/assets/guide_pve_pve_windows.md.37289db4.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as e,v as c,b as s,R as t}from"./chunks/framework.70afa331.js";import{_ as o}from"./chunks/wk7.6fe7513d.js";const d="/assets/kvm.d81063e5.png",i="/assets/dlwiniso.a2c0c1ef.png",p="/assets/dlwiniso1.4fa2fea0.png",a="/assets/general.ea03923c.png",r="/assets/os.b2be1a5c.png",n="/assets/system.8e69987e.png",l="/assets/disks.8065a143.png",m="/assets/cpu.4618bc7b.png",g="/assets/memory.c4992870.png",_="/assets/network.48037353.png",h="/assets/finish.0c3eac87.png",w="/assets/start.3aebbfd4.png",k="/assets/gic1.42bfd260.png",v="/assets/gic2.ff78c941.png",u="/assets/gic3.4a04cf3d.png",b="/assets/gic4.e2343160.png",f="/assets/gic5.54522dff.png",x="/assets/gic6.97561122.png",q="/assets/gic7.a8679083.png",C="/assets/gic8.fe7d0b3c.png",P="/assets/gic9.4cdf4daa.png",I="/assets/net1.4f166207.png",S="/assets/net2.e2773ada.png",O="/assets/net3.40e8a226.png",V="/assets/net4.a81e777c.png",D="/assets/virtio.b42d8275.png",N="/assets/lower2.e782a20a.png",M="/assets/lower1.28498396.png",y="/assets/nodisk.5ec86f3b.png",U="/assets/nodisk1.671c1309.png",E="/assets/nodisk2.ff20bb76.png",W="/assets/nodisk3.71534a11.png",B="/assets/nodisk4.b08d75e3.png",R="/assets/wk4.004be17f.png",G="/assets/wk5.6cdba880.png",K="/assets/wk6.667c5c95.png",A="/assets/wk1.7d9f24d7.png",L="/assets/wk2.2e88d91a.png",T="/assets/wk3.975bc38e.png",co=JSON.parse('{"title":"开设Windows虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_windows.md","filePath":"guide/pve/pve_windows.md","lastUpdated":1747972048000}'),H={name:"guide/pve/pve_windows.md"},$=t('

开设Windows虚拟机

开设时选择KVM虚拟化还是QEMU的TCG仿真

宿主机本身如果支持嵌套虚拟化,那么就可用hostkvm64qemu64类型的CPU

从性能上来说,host > kvm64 > qemu64

qemu类型虚拟化性能损耗很多

如果本身不支持嵌套虚拟化,那么只能用qemu64类型的CPU,且需要在启动虚拟机前修改Options[选项]中的KVM hardware virtualization[KVM硬件虚拟化]

设置为no取消Enabled[启用]的勾选

kvm

如果你实在不清楚本机是否支持嵌套虚拟化,那么查看 系统与硬件配置要求 --> 检测环境 检测确保可用(含尝试性启用功能)

它的主体逻辑在

https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh

这块的逻辑中,主要检测

egrep -c '(vmx|svm)' /proc/cpuinfo 检测是否为1

cat /sys/module/kvm_intel/parameters/nested是否存在且为1

lsmod | grep -q kvm检测是否已加载

这些都支持的时候,才可选host类型。

使用带virtio的iso镜像文件开设

1.下载镜像

安装需要提前下载镜像文件local(pve) --> ISO images --> Download from URL

下载链接URL:可使用

https://github.com/ILLKX/Windows-VirtIO

中的文件链接,文件名字File Name:win.iso

download

点击下载Download,下载完成后当前的页面可见win.iso的文件大小,可见格式为iso。

downloaded

2.设置模板

页面顶部右上角点击Create VM

General窗口中,Resource Pool:勾选mypoolName填写win,然后点击Next

general

OS窗口中,ISO image勾选win.isoGuest OS勾选TypeMicrosoft Windows类型,Version选择当前ISOwin的版本,示例下载是2022,就选11/2022类型,然后点击Next

OS

System窗口中,Graphic card勾选VirtIO-GPU类型,Machine勾选q35类型,SCSI Controller勾选VirtIO SCSI类型,BIOS勾选Default (SeaBIOS)类型,然后点击Next

system

Disk窗口中,Cache勾选Write Back类型,Disk size (GiB)填写你要分配的硬盘大小,一般不小于20Storage选择存储在哪个盘,示例只有系统盘local所以就选loacl,然后点击Next

disk

CPU窗口中,Cores填写所需核数,CPU类型按照前面描述的方法选择,然后点击Next

cpu

Memory窗口中,Memory (MiB)填写所需内存大小,然后点击Next

memory

Network窗口中,Bridge勾选vmbr1类型,Model勾选VirtIO (paravirtualized)类型,Firewall取消勾选,然后点击Next

Network

Confirm窗口中,点击Finish

finish

3.图形化配置安装

左侧点击设置好的模板,右上角点击Start启动虚拟机,然后点击Console进入VNC界面,等待操作系统启动。

console

然后在VNC中点击下一页,然后点击现在安装,然后点击我没有产品密钥,然后勾选接受许可,点击下一页,然后勾选自定义安装

win0

win1

win2

win3

win4

然后如果镜像本身带virtio,那么应该可见可选系统存储的硬盘及其大小,选中后点击下一页

win5

win6

然后等待系统安装,应该会自动重启几次,大概耗时10分钟以上。

win7

安装完成后首次登录会要求设置密码,正常设置即可

win8

设置完成后,NOVNC页面左侧有一个弹出框,点击第一个按钮,然后根据登录提示,点击Ctrl+Alt+最后一个按钮,进入登录页面。

4.初始化网络

由于通过本项目设置的PVE是静态网络,所以登陆后需要手动修改绑定的IP地址,不通过DHCP

在桌面右下角右击点出打开 网络和Internet设置,点击后,在弹出的设置页面中点击更改适配器设置

win9

然后在网络链接中勾选以太网,点击更改此连接的设置

win10

在弹出框中点击Internet协议版本4(TCP/IPV4)选中后点击属性

win11

在新弹出的弹出框中,选择并点击使用下面的IP地址(s),然后分别填入

IP地址(I):172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码(U):255.255.255.0

默认网关(D):172.16.1.1

然后选择点击使用下面的DNS服务器地址(E),分别填入

8.8.8.8
-144.144.144.144

然后右下角点击确定,注意不要勾选退出时验证

win12

然后其他弹出框都选确定就行了,然后本虚拟机就有网络了。

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

使用不带virtio的iso镜像开设

1.下载镜像

无virtio的win镜像下载可使用

https://down.idc.wiki/ISOS/Windows/

这块的镜像

virtio的iso镜像可使用

https://down.idc.wiki/ISOS/Toolkit/

或者

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

下载

virtio也可以只下载msi包,本地用软件打包成iso压缩格式再本地上传到ProxmoxVE中也可以

这样的话包小一些,前者官方的是包含所有WIN镜像支持的包总计500MB左右,后者自己打包5MB左右

2.virtio导入

注意这里的导入在ProxmoxVE的8.x及之后的版本中,OS这一栏默认可选择virtio启动加载,如图所示

virtio

而在更低版本的ProxmoxVE中,比如7.x和6.x的版本,OS这一栏默认无法选择virtio启动加载

lower

需要手动在Hardware[硬件]中点击Add[添加]添加CD/DVD Drive选择下载好的virtioISO文件

lower

然后其他的一切照常,直到

nodisk

这块找不到硬盘,需要选择加载驱动程序

nodisk

然后选择驱动盘virtio的,点击打开,从amd64那导入对应系统名字的驱动

nodisk

我的是windows server 2019的镜像所以导入的是2k19的驱动,导入完毕后选择导入的驱动,点击下一页

nodisk

nodisk

这样就能看得到硬盘了,选中后继续后续的安装步骤,选中后继续后续的安装步骤如同前面的教程,直到系统安装完毕,进入桌面。

3.通过virtio-win-guest-tools安装驱动

此时安装成功,出现桌面后,还需要手动安装驱动

打开VirtIO驱动所在的CD光驱目录,最下面有一个virtio-win-guest-tools程序,会安装用到的virtio驱动,这个驱动也会包含virtio的网卡驱动

wk

wk

wk

点击安装完毕后就安装上网卡驱动了,后续网络设置参考前面的初始化网络的教程

4.安装网卡驱动(备选)

此时安装成功,出现桌面后,还需要手动安装网卡驱动才能连通网络:

  1. 打开 控制面板设备管理器
  2. 找到 以太网控制器,右键选择 更新驱动程序
  3. 选择 浏览我的计算机以查找驱动程序软件 (R)
  4. 浏览到VirtIO驱动所在的CD光驱目录
  5. 打开其中的 NetKVM 文件夹
  6. 根据当前系统版本选择对应的驱动文件夹(和上面相同的操作,我会选择2k19文件夹,里面的amd64驱动)
  7. 确认安装,完成后即可成功加载VirtIO的网卡驱动

wk

wk

wk

后续网络设置参考前面的初始化网络的教程

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

',126),z=[$];function F(Q,X,J,j,Y,Z){return c(),s("div",null,z)}const so=e(H,[["render",F]]);export{co as __pageData,so as default}; diff --git a/assets/guide_pve_pve_windows.md.37289db4.lean.js b/assets/guide_pve_pve_windows.md.37289db4.lean.js deleted file mode 100644 index b81c793917..0000000000 --- a/assets/guide_pve_pve_windows.md.37289db4.lean.js +++ /dev/null @@ -1,2 +0,0 @@ -import{_ as e,v as c,b as s,R as t}from"./chunks/framework.70afa331.js";import{_ as o}from"./chunks/wk7.6fe7513d.js";const d="/assets/kvm.d81063e5.png",i="/assets/dlwiniso.a2c0c1ef.png",p="/assets/dlwiniso1.4fa2fea0.png",a="/assets/general.ea03923c.png",r="/assets/os.b2be1a5c.png",n="/assets/system.8e69987e.png",l="/assets/disks.8065a143.png",m="/assets/cpu.4618bc7b.png",g="/assets/memory.c4992870.png",_="/assets/network.48037353.png",h="/assets/finish.0c3eac87.png",w="/assets/start.3aebbfd4.png",k="/assets/gic1.42bfd260.png",v="/assets/gic2.ff78c941.png",u="/assets/gic3.4a04cf3d.png",b="/assets/gic4.e2343160.png",f="/assets/gic5.54522dff.png",x="/assets/gic6.97561122.png",q="/assets/gic7.a8679083.png",C="/assets/gic8.fe7d0b3c.png",P="/assets/gic9.4cdf4daa.png",I="/assets/net1.4f166207.png",S="/assets/net2.e2773ada.png",O="/assets/net3.40e8a226.png",V="/assets/net4.a81e777c.png",D="/assets/virtio.b42d8275.png",N="/assets/lower2.e782a20a.png",M="/assets/lower1.28498396.png",y="/assets/nodisk.5ec86f3b.png",U="/assets/nodisk1.671c1309.png",E="/assets/nodisk2.ff20bb76.png",W="/assets/nodisk3.71534a11.png",B="/assets/nodisk4.b08d75e3.png",R="/assets/wk4.004be17f.png",G="/assets/wk5.6cdba880.png",K="/assets/wk6.667c5c95.png",A="/assets/wk1.7d9f24d7.png",L="/assets/wk2.2e88d91a.png",T="/assets/wk3.975bc38e.png",co=JSON.parse('{"title":"开设Windows虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_windows.md","filePath":"guide/pve/pve_windows.md","lastUpdated":1747972048000}'),H={name:"guide/pve/pve_windows.md"},$=t('

开设Windows虚拟机

开设时选择KVM虚拟化还是QEMU的TCG仿真

宿主机本身如果支持嵌套虚拟化,那么就可用hostkvm64qemu64类型的CPU

从性能上来说,host > kvm64 > qemu64

qemu类型虚拟化性能损耗很多

如果本身不支持嵌套虚拟化,那么只能用qemu64类型的CPU,且需要在启动虚拟机前修改Options[选项]中的KVM hardware virtualization[KVM硬件虚拟化]

设置为no取消Enabled[启用]的勾选

kvm

如果你实在不清楚本机是否支持嵌套虚拟化,那么查看 系统与硬件配置要求 --> 检测环境 检测确保可用(含尝试性启用功能)

它的主体逻辑在

https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh

这块的逻辑中,主要检测

egrep -c '(vmx|svm)' /proc/cpuinfo 检测是否为1

cat /sys/module/kvm_intel/parameters/nested是否存在且为1

lsmod | grep -q kvm检测是否已加载

这些都支持的时候,才可选host类型。

使用带virtio的iso镜像文件开设

1.下载镜像

安装需要提前下载镜像文件local(pve) --> ISO images --> Download from URL

下载链接URL:可使用

https://github.com/ILLKX/Windows-VirtIO

中的文件链接,文件名字File Name:win.iso

download

点击下载Download,下载完成后当前的页面可见win.iso的文件大小,可见格式为iso。

downloaded

2.设置模板

页面顶部右上角点击Create VM

General窗口中,Resource Pool:勾选mypoolName填写win,然后点击Next

general

OS窗口中,ISO image勾选win.isoGuest OS勾选TypeMicrosoft Windows类型,Version选择当前ISOwin的版本,示例下载是2022,就选11/2022类型,然后点击Next

OS

System窗口中,Graphic card勾选VirtIO-GPU类型,Machine勾选q35类型,SCSI Controller勾选VirtIO SCSI类型,BIOS勾选Default (SeaBIOS)类型,然后点击Next

system

Disk窗口中,Cache勾选Write Back类型,Disk size (GiB)填写你要分配的硬盘大小,一般不小于20Storage选择存储在哪个盘,示例只有系统盘local所以就选loacl,然后点击Next

disk

CPU窗口中,Cores填写所需核数,CPU类型按照前面描述的方法选择,然后点击Next

cpu

Memory窗口中,Memory (MiB)填写所需内存大小,然后点击Next

memory

Network窗口中,Bridge勾选vmbr1类型,Model勾选VirtIO (paravirtualized)类型,Firewall取消勾选,然后点击Next

Network

Confirm窗口中,点击Finish

finish

3.图形化配置安装

左侧点击设置好的模板,右上角点击Start启动虚拟机,然后点击Console进入VNC界面,等待操作系统启动。

console

然后在VNC中点击下一页,然后点击现在安装,然后点击我没有产品密钥,然后勾选接受许可,点击下一页,然后勾选自定义安装

win0

win1

win2

win3

win4

然后如果镜像本身带virtio,那么应该可见可选系统存储的硬盘及其大小,选中后点击下一页

win5

win6

然后等待系统安装,应该会自动重启几次,大概耗时10分钟以上。

win7

安装完成后首次登录会要求设置密码,正常设置即可

win8

设置完成后,NOVNC页面左侧有一个弹出框,点击第一个按钮,然后根据登录提示,点击Ctrl+Alt+最后一个按钮,进入登录页面。

4.初始化网络

由于通过本项目设置的PVE是静态网络,所以登陆后需要手动修改绑定的IP地址,不通过DHCP

在桌面右下角右击点出打开 网络和Internet设置,点击后,在弹出的设置页面中点击更改适配器设置

win9

然后在网络链接中勾选以太网,点击更改此连接的设置

win10

在弹出框中点击Internet协议版本4(TCP/IPV4)选中后点击属性

win11

在新弹出的弹出框中,选择并点击使用下面的IP地址(s),然后分别填入

IP地址(I):172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码(U):255.255.255.0

默认网关(D):172.16.1.1

然后选择点击使用下面的DNS服务器地址(E),分别填入

8.8.8.8
-144.144.144.144

然后右下角点击确定,注意不要勾选退出时验证

win12

然后其他弹出框都选确定就行了,然后本虚拟机就有网络了。

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

使用不带virtio的iso镜像开设

1.下载镜像

无virtio的win镜像下载可使用

https://down.idc.wiki/ISOS/Windows/

这块的镜像

virtio的iso镜像可使用

https://down.idc.wiki/ISOS/Toolkit/

或者

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

下载

virtio也可以只下载msi包,本地用软件打包成iso压缩格式再本地上传到ProxmoxVE中也可以

这样的话包小一些,前者官方的是包含所有WIN镜像支持的包总计500MB左右,后者自己打包5MB左右

2.virtio导入

注意这里的导入在ProxmoxVE的8.x及之后的版本中,OS这一栏默认可选择virtio启动加载,如图所示

virtio

而在更低版本的ProxmoxVE中,比如7.x和6.x的版本,OS这一栏默认无法选择virtio启动加载

lower

需要手动在Hardware[硬件]中点击Add[添加]添加CD/DVD Drive选择下载好的virtioISO文件

lower

然后其他的一切照常,直到

nodisk

这块找不到硬盘,需要选择加载驱动程序

nodisk

然后选择驱动盘virtio的,点击打开,从amd64那导入对应系统名字的驱动

nodisk

我的是windows server 2019的镜像所以导入的是2k19的驱动,导入完毕后选择导入的驱动,点击下一页

nodisk

nodisk

这样就能看得到硬盘了,选中后继续后续的安装步骤,选中后继续后续的安装步骤如同前面的教程,直到系统安装完毕,进入桌面。

3.通过virtio-win-guest-tools安装驱动

此时安装成功,出现桌面后,还需要手动安装驱动

打开VirtIO驱动所在的CD光驱目录,最下面有一个virtio-win-guest-tools程序,会安装用到的virtio驱动,这个驱动也会包含virtio的网卡驱动

wk

wk

wk

点击安装完毕后就安装上网卡驱动了,后续网络设置参考前面的初始化网络的教程

4.安装网卡驱动(备选)

此时安装成功,出现桌面后,还需要手动安装网卡驱动才能连通网络:

  1. 打开 控制面板设备管理器
  2. 找到 以太网控制器,右键选择 更新驱动程序
  3. 选择 浏览我的计算机以查找驱动程序软件 (R)
  4. 浏览到VirtIO驱动所在的CD光驱目录
  5. 打开其中的 NetKVM 文件夹
  6. 根据当前系统版本选择对应的驱动文件夹(和上面相同的操作,我会选择2k19文件夹,里面的amd64驱动)
  7. 确认安装,完成后即可成功加载VirtIO的网卡驱动

wk

wk

wk

后续网络设置参考前面的初始化网络的教程

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

',126),z=[$];function F(Q,X,J,j,Y,Z){return c(),s("div",null,z)}const so=e(H,[["render",F]]);export{co as __pageData,so as default}; diff --git a/assets/guide_pve_pve_windows.md.CLu8AekJ.js b/assets/guide_pve_pve_windows.md.CLu8AekJ.js new file mode 100644 index 0000000000..086e043de4 --- /dev/null +++ b/assets/guide_pve_pve_windows.md.CLu8AekJ.js @@ -0,0 +1,2 @@ +import{_ as e}from"./chunks/wk7.Bl1-W8YX.js";import{_ as c,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const d="/assets/kvm.CI48mv3H.png",p="/assets/dlwiniso.BxXucu9m.png",a="/assets/dlwiniso1.CQyxWlSu.png",r="/assets/general.BkOp2iK4.png",n="/assets/os.CX7bMEp5.png",l="/assets/system.C_AmkiPg.png",m="/assets/disks.BJniy5pO.png",g="/assets/cpu.DedcVQ_T.png",_="/assets/memory.CH7Gxf76.png",h="/assets/network.DPXM5W42.png",w="/assets/finish.Cf6DgPp1.png",k="/assets/start.vjgB4hml.png",v="/assets/gic1.XkdPXihx.png",u="/assets/gic2.s5VB7-xp.png",x="/assets/gic3.2zLznATL.png",b="/assets/gic4.CX3t8C19.png",C="/assets/gic5.pjwHWuhn.png",f="/assets/gic6.BnmyenL0.png",P="/assets/gic7.ZYHWzF5W.png",S="/assets/gic8.BwCbmRgC.png",q="/assets/gic9.62-9wTBo.png",I="/assets/net1.CUyp8ayS.png",V="/assets/net2.BP2m5XnQ.png",O="/assets/net3.BJFg7Me5.png",D="/assets/net4.CANZtcPE.png",B="/assets/virtio.CUVhk14O.png",N="/assets/lower2.SPGPKJ4N.png",M="/assets/lower1.DFw6c1iw.png",W="/assets/nodisk.CH47I8Tu.png",y="/assets/nodisk1.gZ09o2py.png",E="/assets/nodisk2.Do6XEKMW.png",T="/assets/nodisk3.1vBQc75S.png",K="/assets/nodisk4.CJjHGgtp.png",U="/assets/wk4.K5XvE6uQ.png",H="/assets/wk5.BEJ5BAWW.png",G="/assets/wk6.D9MKwk3w.png",X="/assets/wk1.BGnwsbrE.png",L="/assets/wk2.BasdNK2d.png",A="/assets/wk3.CWstwLHH.png",oo=JSON.parse('{"title":"开设Windows虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_windows.md","filePath":"guide/pve/pve_windows.md","lastUpdated":1747984962000}'),R={name:"guide/pve/pve_windows.md"};function Q(z,o,F,J,$,j){return t(),s("div",null,o[0]||(o[0]=[i('

开设Windows虚拟机

开设时选择KVM虚拟化还是QEMU的TCG仿真

宿主机本身如果支持嵌套虚拟化,那么就可用hostkvm64qemu64类型的CPU

从性能上来说,host > kvm64 > qemu64

qemu类型虚拟化性能损耗很多

如果本身不支持嵌套虚拟化,那么只能用qemu64类型的CPU,且需要在启动虚拟机前修改Options[选项]中的KVM hardware virtualization[KVM硬件虚拟化]

设置为no取消Enabled[启用]的勾选

kvm

如果你实在不清楚本机是否支持嵌套虚拟化,那么查看 系统与硬件配置要求 --> 检测环境 检测确保可用(含尝试性启用功能)

它的主体逻辑在

https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh

这块的逻辑中,主要检测

egrep -c '(vmx|svm)' /proc/cpuinfo 检测是否为1

cat /sys/module/kvm_intel/parameters/nested是否存在且为1

lsmod | grep -q kvm检测是否已加载

这些都支持的时候,才可选host类型。

使用带virtio的iso镜像文件开设

1.下载镜像

安装需要提前下载镜像文件local(pve) --> ISO images --> Download from URL

下载链接URL:可使用

https://github.com/ILLKX/Windows-VirtIO

中的文件链接,文件名字File Name:win.iso

download

点击下载Download,下载完成后当前的页面可见win.iso的文件大小,可见格式为iso。

downloaded

2.设置模板

页面顶部右上角点击Create VM

General窗口中,Resource Pool:勾选mypoolName填写win,然后点击Next

general

OS窗口中,ISO image勾选win.isoGuest OS勾选TypeMicrosoft Windows类型,Version选择当前ISOwin的版本,示例下载是2022,就选11/2022类型,然后点击Next

OS

System窗口中,Graphic card勾选VirtIO-GPU类型,Machine勾选q35类型,SCSI Controller勾选VirtIO SCSI类型,BIOS勾选Default (SeaBIOS)类型,然后点击Next

system

Disk窗口中,Cache勾选Write Back类型,Disk size (GiB)填写你要分配的硬盘大小,一般不小于20Storage选择存储在哪个盘,示例只有系统盘local所以就选loacl,然后点击Next

disk

CPU窗口中,Cores填写所需核数,CPU类型按照前面描述的方法选择,然后点击Next

cpu

Memory窗口中,Memory (MiB)填写所需内存大小,然后点击Next

memory

Network窗口中,Bridge勾选vmbr1类型,Model勾选VirtIO (paravirtualized)类型,Firewall取消勾选,然后点击Next

Network

Confirm窗口中,点击Finish

finish

3.图形化配置安装

左侧点击设置好的模板,右上角点击Start启动虚拟机,然后点击Console进入VNC界面,等待操作系统启动。

console

然后在VNC中点击下一页,然后点击现在安装,然后点击我没有产品密钥,然后勾选接受许可,点击下一页,然后勾选自定义安装

win0

win1

win2

win3

win4

然后如果镜像本身带virtio,那么应该可见可选系统存储的硬盘及其大小,选中后点击下一页

win5

win6

然后等待系统安装,应该会自动重启几次,大概耗时10分钟以上。

win7

安装完成后首次登录会要求设置密码,正常设置即可

win8

设置完成后,NOVNC页面左侧有一个弹出框,点击第一个按钮,然后根据登录提示,点击Ctrl+Alt+最后一个按钮,进入登录页面。

4.初始化网络

由于通过本项目设置的PVE是静态网络,所以登陆后需要手动修改绑定的IP地址,不通过DHCP

在桌面右下角右击点出打开 网络和Internet设置,点击后,在弹出的设置页面中点击更改适配器设置

win9

然后在网络链接中勾选以太网,点击更改此连接的设置

win10

在弹出框中点击Internet协议版本4(TCP/IPV4)选中后点击属性

win11

在新弹出的弹出框中,选择并点击使用下面的IP地址(s),然后分别填入

IP地址(I):172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码(U):255.255.255.0

默认网关(D):172.16.1.1

然后选择点击使用下面的DNS服务器地址(E),分别填入

8.8.8.8
+144.144.144.144

然后右下角点击确定,注意不要勾选退出时验证

win12

然后其他弹出框都选确定就行了,然后本虚拟机就有网络了。

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

使用不带virtio的iso镜像开设

1.下载镜像

无virtio的win镜像下载可使用

https://down.idc.wiki/ISOS/Windows/

这块的镜像

virtio的iso镜像可使用

https://down.idc.wiki/ISOS/Toolkit/

或者

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

下载

virtio也可以只下载msi包,本地用软件打包成iso压缩格式再本地上传到ProxmoxVE中也可以

这样的话包小一些,前者官方的是包含所有WIN镜像支持的包总计500MB左右,后者自己打包5MB左右

2.virtio导入

注意这里的导入在ProxmoxVE的8.x及之后的版本中,OS这一栏默认可选择virtio启动加载,如图所示

virtio

而在更低版本的ProxmoxVE中,比如7.x和6.x的版本,OS这一栏默认无法选择virtio启动加载

lower

需要手动在Hardware[硬件]中点击Add[添加]添加CD/DVD Drive选择下载好的virtioISO文件

lower

然后其他的一切照常,直到

nodisk

这块找不到硬盘,需要选择加载驱动程序

nodisk

然后选择驱动盘virtio的,点击打开,从amd64那导入对应系统名字的驱动

nodisk

我的是windows server 2019的镜像所以导入的是2k19的驱动,导入完毕后选择导入的驱动,点击下一页

nodisk

nodisk

这样就能看得到硬盘了,选中后继续后续的安装步骤,选中后继续后续的安装步骤如同前面的教程,直到系统安装完毕,进入桌面。

3.通过virtio-win-guest-tools安装驱动

此时安装成功,出现桌面后,还需要手动安装驱动

打开VirtIO驱动所在的CD光驱目录,最下面有一个virtio-win-guest-tools程序,会安装用到的virtio驱动,这个驱动也会包含virtio的网卡驱动

wk

wk

wk

点击安装完毕后就安装上网卡驱动了,后续网络设置参考前面的初始化网络的教程

4.安装网卡驱动(备选)

此时安装成功,出现桌面后,还需要手动安装网卡驱动才能连通网络:

  1. 打开 控制面板设备管理器
  2. 找到 以太网控制器,右键选择 更新驱动程序
  3. 选择 浏览我的计算机以查找驱动程序软件 (R)
  4. 浏览到VirtIO驱动所在的CD光驱目录
  5. 打开其中的 NetKVM 文件夹
  6. 根据当前系统版本选择对应的驱动文件夹(和上面相同的操作,我会选择2k19文件夹,里面的amd64驱动)
  7. 确认安装,完成后即可成功加载VirtIO的网卡驱动

wk

wk

wk

后续网络设置参考前面的初始化网络的教程

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

',126)]))}const eo=c(R,[["render",Q]]);export{oo as __pageData,eo as default}; diff --git a/assets/guide_pve_pve_windows.md.CLu8AekJ.lean.js b/assets/guide_pve_pve_windows.md.CLu8AekJ.lean.js new file mode 100644 index 0000000000..8e546b4f74 --- /dev/null +++ b/assets/guide_pve_pve_windows.md.CLu8AekJ.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/wk7.Bl1-W8YX.js";import{_ as c,c as s,o as t,ag as i}from"./chunks/framework.CSeR4K32.js";const d="/assets/kvm.CI48mv3H.png",p="/assets/dlwiniso.BxXucu9m.png",a="/assets/dlwiniso1.CQyxWlSu.png",r="/assets/general.BkOp2iK4.png",n="/assets/os.CX7bMEp5.png",l="/assets/system.C_AmkiPg.png",m="/assets/disks.BJniy5pO.png",g="/assets/cpu.DedcVQ_T.png",_="/assets/memory.CH7Gxf76.png",h="/assets/network.DPXM5W42.png",w="/assets/finish.Cf6DgPp1.png",k="/assets/start.vjgB4hml.png",v="/assets/gic1.XkdPXihx.png",u="/assets/gic2.s5VB7-xp.png",x="/assets/gic3.2zLznATL.png",b="/assets/gic4.CX3t8C19.png",C="/assets/gic5.pjwHWuhn.png",f="/assets/gic6.BnmyenL0.png",P="/assets/gic7.ZYHWzF5W.png",S="/assets/gic8.BwCbmRgC.png",q="/assets/gic9.62-9wTBo.png",I="/assets/net1.CUyp8ayS.png",V="/assets/net2.BP2m5XnQ.png",O="/assets/net3.BJFg7Me5.png",D="/assets/net4.CANZtcPE.png",B="/assets/virtio.CUVhk14O.png",N="/assets/lower2.SPGPKJ4N.png",M="/assets/lower1.DFw6c1iw.png",W="/assets/nodisk.CH47I8Tu.png",y="/assets/nodisk1.gZ09o2py.png",E="/assets/nodisk2.Do6XEKMW.png",T="/assets/nodisk3.1vBQc75S.png",K="/assets/nodisk4.CJjHGgtp.png",U="/assets/wk4.K5XvE6uQ.png",H="/assets/wk5.BEJ5BAWW.png",G="/assets/wk6.D9MKwk3w.png",X="/assets/wk1.BGnwsbrE.png",L="/assets/wk2.BasdNK2d.png",A="/assets/wk3.CWstwLHH.png",oo=JSON.parse('{"title":"开设Windows虚拟机","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"guide/pve/pve_windows.md","filePath":"guide/pve/pve_windows.md","lastUpdated":1747984962000}'),R={name:"guide/pve/pve_windows.md"};function Q(z,o,F,J,$,j){return t(),s("div",null,o[0]||(o[0]=[i("",126)]))}const eo=c(R,[["render",Q]]);export{oo as __pageData,eo as default}; diff --git a/assets/incomplete_bashvm.md.B5fMrqJh.js b/assets/incomplete_bashvm.md.B5fMrqJh.js new file mode 100644 index 0000000000..764c241e9e --- /dev/null +++ b/assets/incomplete_bashvm.md.B5fMrqJh.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,ag as o}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/bashvm.md","filePath":"incomplete/bashvm.md","lastUpdated":1747984962000}'),s={name:"incomplete/bashvm.md"};function h(n,a,l,i,p,m){return r(),t("div",null,a[0]||(a[0]=[o('

仓库

https://github.com/babywhale321/bashvm

https://bashvm.com/

说明

如果你想深入了解怎么开设一个虚拟机,怎么转发端口,那么这个项目将完全从底层开始,一步步教你如何开设虚拟机

缺点

非常的繁琐,非常的耗时,不如别的项目快速设置网络和开设

',7)]))}const _=e(s,[["render",h]]);export{d as __pageData,_ as default}; diff --git a/assets/incomplete_bashvm.md.B5fMrqJh.lean.js b/assets/incomplete_bashvm.md.B5fMrqJh.lean.js new file mode 100644 index 0000000000..0494bf52e8 --- /dev/null +++ b/assets/incomplete_bashvm.md.B5fMrqJh.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,ag as o}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/bashvm.md","filePath":"incomplete/bashvm.md","lastUpdated":1747984962000}'),s={name:"incomplete/bashvm.md"};function h(n,a,l,i,p,m){return r(),t("div",null,a[0]||(a[0]=[o("",7)]))}const _=e(s,[["render",h]]);export{d as __pageData,_ as default}; diff --git a/assets/incomplete_bashvm.md.e680b5ae.js b/assets/incomplete_bashvm.md.e680b5ae.js deleted file mode 100644 index 46ed4f4499..0000000000 --- a/assets/incomplete_bashvm.md.e680b5ae.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as r}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/bashvm.md","filePath":"incomplete/bashvm.md","lastUpdated":1747972048000}'),s={name:"incomplete/bashvm.md"},h=r('

仓库

https://github.com/babywhale321/bashvm

https://bashvm.com/

说明

如果你想深入了解怎么开设一个虚拟机,怎么转发端口,那么这个项目将完全从底层开始,一步步教你如何开设虚拟机

缺点

非常的繁琐,非常的耗时,不如别的项目快速设置网络和开设

',7),o=[h];function n(i,l,p,c,m,b){return e(),t("div",null,o)}const f=a(s,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/assets/incomplete_bashvm.md.e680b5ae.lean.js b/assets/incomplete_bashvm.md.e680b5ae.lean.js deleted file mode 100644 index 46ed4f4499..0000000000 --- a/assets/incomplete_bashvm.md.e680b5ae.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as a,v as e,b as t,R as r}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/bashvm.md","filePath":"incomplete/bashvm.md","lastUpdated":1747972048000}'),s={name:"incomplete/bashvm.md"},h=r('

仓库

https://github.com/babywhale321/bashvm

https://bashvm.com/

说明

如果你想深入了解怎么开设一个虚拟机,怎么转发端口,那么这个项目将完全从底层开始,一步步教你如何开设虚拟机

缺点

非常的繁琐,非常的耗时,不如别的项目快速设置网络和开设

',7),o=[h];function n(i,l,p,c,m,b){return e(),t("div",null,o)}const f=a(s,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/assets/incomplete_cockpit.md.77e4fe67.js b/assets/incomplete_cockpit.md.77e4fe67.js deleted file mode 100644 index 4ec8ec5bea..0000000000 --- a/assets/incomplete_cockpit.md.77e4fe67.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/cockpit.md","filePath":"incomplete/cockpit.md","lastUpdated":1747972048000}'),e={name:"incomplete/cockpit.md"},n=t('

仓库

hits

https://github.com/oneclickvirt/cockpit

安装

支持的系统:Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

只安装带容器的

shell
bash install.sh --ct

只安装带虚拟机的

shell
bash install.sh --vm

仅安装面板

shell
bash install.sh

容器和虚拟机依赖都进行安装

shell
bash install.sh --all

缺点

网络自行配置,镜像自行导入,端口自行映射,只是比纯命令行多了一个GUI界面罢了

致谢

https://cockpit-project.org/running.html

',21),p=[n];function o(c,r,i,h,C,y){return a(),l("div",null,p)}const A=s(e,[["render",o]]);export{m as __pageData,A as default}; diff --git a/assets/incomplete_cockpit.md.77e4fe67.lean.js b/assets/incomplete_cockpit.md.77e4fe67.lean.js deleted file mode 100644 index 4ec8ec5bea..0000000000 --- a/assets/incomplete_cockpit.md.77e4fe67.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as t}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/cockpit.md","filePath":"incomplete/cockpit.md","lastUpdated":1747972048000}'),e={name:"incomplete/cockpit.md"},n=t('

仓库

hits

https://github.com/oneclickvirt/cockpit

安装

支持的系统:Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

只安装带容器的

shell
bash install.sh --ct

只安装带虚拟机的

shell
bash install.sh --vm

仅安装面板

shell
bash install.sh

容器和虚拟机依赖都进行安装

shell
bash install.sh --all

缺点

网络自行配置,镜像自行导入,端口自行映射,只是比纯命令行多了一个GUI界面罢了

致谢

https://cockpit-project.org/running.html

',21),p=[n];function o(c,r,i,h,C,y){return a(),l("div",null,p)}const A=s(e,[["render",o]]);export{m as __pageData,A as default}; diff --git a/assets/incomplete_cockpit.md.HGnaxkEA.js b/assets/incomplete_cockpit.md.HGnaxkEA.js new file mode 100644 index 0000000000..0fdef5313c --- /dev/null +++ b/assets/incomplete_cockpit.md.HGnaxkEA.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/cockpit.md","filePath":"incomplete/cockpit.md","lastUpdated":1747984962000}'),l={name:"incomplete/cockpit.md"};function h(p,s,n,r,k,c){return t(),a("div",null,s[0]||(s[0]=[e('

仓库

hits

https://github.com/oneclickvirt/cockpit

安装

支持的系统:Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

只安装带容器的

shell
bash install.sh --ct

只安装带虚拟机的

shell
bash install.sh --vm

仅安装面板

shell
bash install.sh

容器和虚拟机依赖都进行安装

shell
bash install.sh --all

缺点

网络自行配置,镜像自行导入,端口自行映射,只是比纯命令行多了一个GUI界面罢了

致谢

https://cockpit-project.org/running.html

',21)]))}const g=i(l,[["render",h]]);export{d as __pageData,g as default}; diff --git a/assets/incomplete_cockpit.md.HGnaxkEA.lean.js b/assets/incomplete_cockpit.md.HGnaxkEA.lean.js new file mode 100644 index 0000000000..100add6893 --- /dev/null +++ b/assets/incomplete_cockpit.md.HGnaxkEA.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/cockpit.md","filePath":"incomplete/cockpit.md","lastUpdated":1747984962000}'),l={name:"incomplete/cockpit.md"};function h(p,s,n,r,k,c){return t(),a("div",null,s[0]||(s[0]=[e("",21)]))}const g=i(l,[["render",h]]);export{d as __pageData,g as default}; diff --git a/assets/incomplete_convoy.md.CxPU1hOM.js b/assets/incomplete_convoy.md.CxPU1hOM.js new file mode 100644 index 0000000000..a2e6339413 --- /dev/null +++ b/assets/incomplete_convoy.md.CxPU1hOM.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/convoy.md","filePath":"incomplete/convoy.md","lastUpdated":1747984962000}'),n={name:"incomplete/convoy.md"};function l(p,s,h,o,r,c){return t(),a("div",null,s[0]||(s[0]=[e('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

安装前提条件:

  • 已安装 PVE,但不能是同一节点(不能是同一台机器)
  • 系统为 Debian 11
  • CPU 至少 2 核,硬盘至少 20G,内存至少 4G(内存包含 swap)

我不保证这个脚本没有错误,本项目未完整

国际

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',15)]))}const g=i(n,[["render",l]]);export{d as __pageData,g as default}; diff --git a/assets/incomplete_convoy.md.CxPU1hOM.lean.js b/assets/incomplete_convoy.md.CxPU1hOM.lean.js new file mode 100644 index 0000000000..caa344d45f --- /dev/null +++ b/assets/incomplete_convoy.md.CxPU1hOM.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const d=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/convoy.md","filePath":"incomplete/convoy.md","lastUpdated":1747984962000}'),n={name:"incomplete/convoy.md"};function l(p,s,h,o,r,c){return t(),a("div",null,s[0]||(s[0]=[e("",15)]))}const g=i(n,[["render",l]]);export{d as __pageData,g as default}; diff --git a/assets/incomplete_convoy.md.f7a4bd52.js b/assets/incomplete_convoy.md.f7a4bd52.js deleted file mode 100644 index aac8eb2a94..0000000000 --- a/assets/incomplete_convoy.md.f7a4bd52.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as o,R as n}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/convoy.md","filePath":"incomplete/convoy.md","lastUpdated":1747972048000}'),l={name:"incomplete/convoy.md"},t=n('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

安装前提条件:

  • 已安装 PVE,但不能是同一节点(不能是同一台机器)
  • 系统为 Debian 11
  • CPU 至少 2 核,硬盘至少 20G,内存至少 4G(内存包含 swap)

我不保证这个脚本没有错误,本项目未完整

国际

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',15),e=[t];function p(c,r,i,h,y,C){return a(),o("div",null,e)}const d=s(l,[["render",p]]);export{D as __pageData,d as default}; diff --git a/assets/incomplete_convoy.md.f7a4bd52.lean.js b/assets/incomplete_convoy.md.f7a4bd52.lean.js deleted file mode 100644 index aac8eb2a94..0000000000 --- a/assets/incomplete_convoy.md.f7a4bd52.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as o,R as n}from"./chunks/framework.70afa331.js";const D=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/convoy.md","filePath":"incomplete/convoy.md","lastUpdated":1747972048000}'),l={name:"incomplete/convoy.md"},t=n('

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

安装前提条件:

  • 已安装 PVE,但不能是同一节点(不能是同一台机器)
  • 系统为 Debian 11
  • CPU 至少 2 核,硬盘至少 20G,内存至少 4G(内存包含 swap)

我不保证这个脚本没有错误,本项目未完整

国际

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

',15),e=[t];function p(c,r,i,h,y,C){return a(),o("div",null,e)}const d=s(l,[["render",p]]);export{D as __pageData,d as default}; diff --git a/assets/incomplete_index.md.13d9bf0c.js b/assets/incomplete_index.md.CYVk98K2.js similarity index 85% rename from assets/incomplete_index.md.13d9bf0c.js rename to assets/incomplete_index.md.CYVk98K2.js index 75e28b08d3..e3e5c3093d 100644 --- a/assets/incomplete_index.md.13d9bf0c.js +++ b/assets/incomplete_index.md.CYVk98K2.js @@ -1 +1 @@ -import{_ as t,v as e,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","description":"","frontmatter":{"layout":"home","title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","hero":{"name":"其他虚拟化项目","text":"一些不完整的虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/incomplete/webvirtcloud"}]},"features":[{"title":"注意事项","details":"这块每个项目都有对应的缺点,每个项目都不像之前的项目一样简单好用,有一定的学习成本。"},{"title":"难易程度","details":"基于项目本身的使用难度,由易到难排序,越往后你能得到本指南的引导越少。"},{"title":"项目缺点","details":"每个项目都有部分缺点导致不被认为是完整的一键项目,有一些操作需要手动执行命令无法一键化。"}]},"headers":[],"relativePath":"incomplete/index.md","filePath":"incomplete/index.md","lastUpdated":1747972048000}'),a={name:"incomplete/index.md"};function n(s,l,o,r,p,d){return e(),i("div")}const h=t(a,[["render",n]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as i}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","description":"","frontmatter":{"layout":"home","title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","hero":{"name":"其他虚拟化项目","text":"一些不完整的虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/incomplete/webvirtcloud"}]},"features":[{"title":"注意事项","details":"这块每个项目都有对应的缺点,每个项目都不像之前的项目一样简单好用,有一定的学习成本。"},{"title":"难易程度","details":"基于项目本身的使用难度,由易到难排序,越往后你能得到本指南的引导越少。"},{"title":"项目缺点","details":"每个项目都有部分缺点导致不被认为是完整的一键项目,有一些操作需要手动执行命令无法一键化。"}]},"headers":[],"relativePath":"incomplete/index.md","filePath":"incomplete/index.md","lastUpdated":1747984962000}'),a={name:"incomplete/index.md"};function n(l,o,s,r,c,p){return i(),t("div")}const h=e(a,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/incomplete_index.md.13d9bf0c.lean.js b/assets/incomplete_index.md.CYVk98K2.lean.js similarity index 85% rename from assets/incomplete_index.md.13d9bf0c.lean.js rename to assets/incomplete_index.md.CYVk98K2.lean.js index 75e28b08d3..e3e5c3093d 100644 --- a/assets/incomplete_index.md.13d9bf0c.lean.js +++ b/assets/incomplete_index.md.CYVk98K2.lean.js @@ -1 +1 @@ -import{_ as t,v as e,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","description":"","frontmatter":{"layout":"home","title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","hero":{"name":"其他虚拟化项目","text":"一些不完整的虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/incomplete/webvirtcloud"}]},"features":[{"title":"注意事项","details":"这块每个项目都有对应的缺点,每个项目都不像之前的项目一样简单好用,有一定的学习成本。"},{"title":"难易程度","details":"基于项目本身的使用难度,由易到难排序,越往后你能得到本指南的引导越少。"},{"title":"项目缺点","details":"每个项目都有部分缺点导致不被认为是完整的一键项目,有一些操作需要手动执行命令无法一键化。"}]},"headers":[],"relativePath":"incomplete/index.md","filePath":"incomplete/index.md","lastUpdated":1747972048000}'),a={name:"incomplete/index.md"};function n(s,l,o,r,p,d){return e(),i("div")}const h=t(a,[["render",n]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as i}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","description":"","frontmatter":{"layout":"home","title":"其他虚拟化项目","titleTemplate":"其他不完整的虚拟化项目","hero":{"name":"其他虚拟化项目","text":"一些不完整的虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"查看项目 →","link":"/incomplete/webvirtcloud"}]},"features":[{"title":"注意事项","details":"这块每个项目都有对应的缺点,每个项目都不像之前的项目一样简单好用,有一定的学习成本。"},{"title":"难易程度","details":"基于项目本身的使用难度,由易到难排序,越往后你能得到本指南的引导越少。"},{"title":"项目缺点","details":"每个项目都有部分缺点导致不被认为是完整的一键项目,有一些操作需要手动执行命令无法一键化。"}]},"headers":[],"relativePath":"incomplete/index.md","filePath":"incomplete/index.md","lastUpdated":1747984962000}'),a={name:"incomplete/index.md"};function n(l,o,s,r,c,p){return i(),t("div")}const h=e(a,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/incomplete_pterodactyl.md.16ac57df.js b/assets/incomplete_pterodactyl.md.16ac57df.js deleted file mode 100644 index 43f6756edd..0000000000 --- a/assets/incomplete_pterodactyl.md.16ac57df.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/pterodactyl.md","filePath":"incomplete/pterodactyl.md","lastUpdated":1747972048000}'),n={name:"incomplete/pterodactyl.md"},o=p('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

进一步调研发现开设servers和绑定用户极麻烦,不如原生直接docker方便,故而暂不做后续开发了

说明

目前支持的系统

系统类型版本范围备注
Ubuntu20.04(推荐), 22.04, 24.04已支持
Debian11(Bullseye), 12(Bookworm)已支持

Panel

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

wings端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

会生成需要在wings端执行的命令

生成的命令执行完毕后等待20秒以上,避免一些初始化流程未走完,然后wings端再执行:

shell
bash install_wings.sh

然后在http://<your_ip>/admin/nodes就能看到你的节点已经被自动添加纳管,心跳是绿色的

Thanks

https://pterodactyl.io/

',32),t=[o];function e(r,c,C,i,y,h){return a(),l("div",null,t)}const D=s(n,[["render",e]]);export{A as __pageData,D as default}; diff --git a/assets/incomplete_pterodactyl.md.16ac57df.lean.js b/assets/incomplete_pterodactyl.md.16ac57df.lean.js deleted file mode 100644 index 43f6756edd..0000000000 --- a/assets/incomplete_pterodactyl.md.16ac57df.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as s,v as a,b as l,R as p}from"./chunks/framework.70afa331.js";const A=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/pterodactyl.md","filePath":"incomplete/pterodactyl.md","lastUpdated":1747972048000}'),n={name:"incomplete/pterodactyl.md"},o=p('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

进一步调研发现开设servers和绑定用户极麻烦,不如原生直接docker方便,故而暂不做后续开发了

说明

目前支持的系统

系统类型版本范围备注
Ubuntu20.04(推荐), 22.04, 24.04已支持
Debian11(Bullseye), 12(Bookworm)已支持

Panel

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

wings端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

会生成需要在wings端执行的命令

生成的命令执行完毕后等待20秒以上,避免一些初始化流程未走完,然后wings端再执行:

shell
bash install_wings.sh

然后在http://<your_ip>/admin/nodes就能看到你的节点已经被自动添加纳管,心跳是绿色的

Thanks

https://pterodactyl.io/

',32),t=[o];function e(r,c,C,i,y,h){return a(),l("div",null,t)}const D=s(n,[["render",e]]);export{A as __pageData,D as default}; diff --git a/assets/incomplete_pterodactyl.md.ywtPLv_5.js b/assets/incomplete_pterodactyl.md.ywtPLv_5.js new file mode 100644 index 0000000000..4db0363c23 --- /dev/null +++ b/assets/incomplete_pterodactyl.md.ywtPLv_5.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/pterodactyl.md","filePath":"incomplete/pterodactyl.md","lastUpdated":1747984962000}'),l={name:"incomplete/pterodactyl.md"};function e(p,s,n,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h('

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

进一步调研发现开设servers和绑定用户极麻烦,不如原生直接docker方便,故而暂不做后续开发了

说明

目前支持的系统

系统类型版本范围备注
Ubuntu20.04(推荐), 22.04, 24.04已支持
Debian11(Bullseye), 12(Bookworm)已支持

Panel

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

wings端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

会生成需要在wings端执行的命令

生成的命令执行完毕后等待20秒以上,避免一些初始化流程未走完,然后wings端再执行:

shell
bash install_wings.sh

然后在http://<your_ip>/admin/nodes就能看到你的节点已经被自动添加纳管,心跳是绿色的

Thanks

https://pterodactyl.io/

',32)]))}const g=i(l,[["render",e]]);export{c as __pageData,g as default}; diff --git a/assets/incomplete_pterodactyl.md.ywtPLv_5.lean.js b/assets/incomplete_pterodactyl.md.ywtPLv_5.lean.js new file mode 100644 index 0000000000..4b951fb285 --- /dev/null +++ b/assets/incomplete_pterodactyl.md.ywtPLv_5.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as h}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/pterodactyl.md","filePath":"incomplete/pterodactyl.md","lastUpdated":1747984962000}'),l={name:"incomplete/pterodactyl.md"};function e(p,s,n,k,r,d){return t(),a("div",null,s[0]||(s[0]=[h("",32)]))}const g=i(l,[["render",e]]);export{c as __pageData,g as default}; diff --git a/assets/incomplete_virtfusion.md.DnaD-J8U.js b/assets/incomplete_virtfusion.md.DnaD-J8U.js new file mode 100644 index 0000000000..888a158d2b --- /dev/null +++ b/assets/incomplete_virtfusion.md.DnaD-J8U.js @@ -0,0 +1,7 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtfusion.md","filePath":"incomplete/virtfusion.md","lastUpdated":1747984962000}'),n={name:"incomplete/virtfusion.md"};function h(e,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[l(`

官方文档

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

一键安装

debian11

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

缺点

每台服务器每个邮箱只有一次30天试用的证书,无永久的免费的证书

`,17)]))}const c=i(n,[["render",h]]);export{o as __pageData,c as default}; diff --git a/assets/incomplete_virtfusion.md.DnaD-J8U.lean.js b/assets/incomplete_virtfusion.md.DnaD-J8U.lean.js new file mode 100644 index 0000000000..d40648c14f --- /dev/null +++ b/assets/incomplete_virtfusion.md.DnaD-J8U.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const o=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtfusion.md","filePath":"incomplete/virtfusion.md","lastUpdated":1747984962000}'),n={name:"incomplete/virtfusion.md"};function h(e,s,p,k,r,d){return t(),a("div",null,s[0]||(s[0]=[l("",17)]))}const c=i(n,[["render",h]]);export{o as __pageData,c as default}; diff --git a/assets/incomplete_virtfusion.md.a22bdacd.js b/assets/incomplete_virtfusion.md.a22bdacd.js deleted file mode 100644 index 38c4142695..0000000000 --- a/assets/incomplete_virtfusion.md.a22bdacd.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtfusion.md","filePath":"incomplete/virtfusion.md","lastUpdated":1747972048000}'),o={name:"incomplete/virtfusion.md"},p=n(`

官方文档

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

一键安装

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

缺点

每台服务器每个邮箱只有一次30天试用的证书,无永久的免费的证书

`,17),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/incomplete_virtfusion.md.a22bdacd.lean.js b/assets/incomplete_virtfusion.md.a22bdacd.lean.js deleted file mode 100644 index 38c4142695..0000000000 --- a/assets/incomplete_virtfusion.md.a22bdacd.lean.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const h=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtfusion.md","filePath":"incomplete/virtfusion.md","lastUpdated":1747972048000}'),o={name:"incomplete/virtfusion.md"},p=n(`

官方文档

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

一键安装

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

缺点

每台服务器每个邮箱只有一次30天试用的证书,无永久的免费的证书

`,17),e=[p];function t(c,r,C,i,y,D){return a(),l("div",null,e)}const u=s(o,[["render",t]]);export{h as __pageData,u as default}; diff --git a/assets/incomplete_virtualizor-docker.md.BgClRxGW.js b/assets/incomplete_virtualizor-docker.md.BgClRxGW.js new file mode 100644 index 0000000000..748f1cbd53 --- /dev/null +++ b/assets/incomplete_virtualizor-docker.md.BgClRxGW.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,ag as o}from"./chunks/framework.CSeR4K32.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtualizor-docker.md","filePath":"incomplete/virtualizor-docker.md","lastUpdated":1747984962000}'),i={name:"incomplete/virtualizor-docker.md"};function l(n,e,c,d,p,s){return r(),t("div",null,e[0]||(e[0]=[o('

仓库

https://github.com/ivstiv/virtualizor-docker

说明

在docker中开设的 virtualizor

证书用的是试用的证书,有效期一天,且默认只安装了OpenVZ的虚拟化方式

缺点

毫无社区,一切自行摸索

admin面板的端口不要看脚本的提示信息,以仓库说明为准。

',8)]))}const u=a(i,[["render",l]]);export{_ as __pageData,u as default}; diff --git a/assets/incomplete_virtualizor-docker.md.BgClRxGW.lean.js b/assets/incomplete_virtualizor-docker.md.BgClRxGW.lean.js new file mode 100644 index 0000000000..a4abe416f3 --- /dev/null +++ b/assets/incomplete_virtualizor-docker.md.BgClRxGW.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o as r,ag as o}from"./chunks/framework.CSeR4K32.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtualizor-docker.md","filePath":"incomplete/virtualizor-docker.md","lastUpdated":1747984962000}'),i={name:"incomplete/virtualizor-docker.md"};function l(n,e,c,d,p,s){return r(),t("div",null,e[0]||(e[0]=[o("",8)]))}const u=a(i,[["render",l]]);export{_ as __pageData,u as default}; diff --git a/assets/incomplete_virtualizor-docker.md.a05fb0f7.js b/assets/incomplete_virtualizor-docker.md.a05fb0f7.js deleted file mode 100644 index d27a5ba7c1..0000000000 --- a/assets/incomplete_virtualizor-docker.md.a05fb0f7.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,R as r}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtualizor-docker.md","filePath":"incomplete/virtualizor-docker.md","lastUpdated":1747972048000}'),o={name:"incomplete/virtualizor-docker.md"},i=r('

仓库

https://github.com/ivstiv/virtualizor-docker

说明

在docker中开设的 virtualizor

证书用的是试用的证书,有效期一天,且默认只安装了OpenVZ的虚拟化方式

缺点

毫无社区,一切自行摸索

admin面板的端口不要看脚本的提示信息,以仓库说明为准。

',8),s=[i];function n(l,c,d,p,h,u){return a(),t("div",null,s)}const v=e(o,[["render",n]]);export{_ as __pageData,v as default}; diff --git a/assets/incomplete_virtualizor-docker.md.a05fb0f7.lean.js b/assets/incomplete_virtualizor-docker.md.a05fb0f7.lean.js deleted file mode 100644 index d27a5ba7c1..0000000000 --- a/assets/incomplete_virtualizor-docker.md.a05fb0f7.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,v as a,b as t,R as r}from"./chunks/framework.70afa331.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/virtualizor-docker.md","filePath":"incomplete/virtualizor-docker.md","lastUpdated":1747972048000}'),o={name:"incomplete/virtualizor-docker.md"},i=r('

仓库

https://github.com/ivstiv/virtualizor-docker

说明

在docker中开设的 virtualizor

证书用的是试用的证书,有效期一天,且默认只安装了OpenVZ的虚拟化方式

缺点

毫无社区,一切自行摸索

admin面板的端口不要看脚本的提示信息,以仓库说明为准。

',8),s=[i];function n(l,c,d,p,h,u){return a(),t("div",null,s)}const v=e(o,[["render",n]]);export{_ as __pageData,v as default}; diff --git a/assets/incomplete_webvirtcloud.md.2369e889.js b/assets/incomplete_webvirtcloud.md.2369e889.js deleted file mode 100644 index 9833c35c84..0000000000 --- a/assets/incomplete_webvirtcloud.md.2369e889.js +++ /dev/null @@ -1,48 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const o="/assets/wv1.5ac4a026.png",h=JSON.parse('{"title":"WebVirtCloud 安装指南","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud.md","filePath":"incomplete/webvirtcloud.md","lastUpdated":1747972048000}'),p={name:"incomplete/webvirtcloud.md"},e=n(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/webvirtcloud/webvirtcloud

应该算是全网中文第一份完整的部署指南,官方的指南实际上有很多地方是和本项目部署的方式有出入的。

1. 控制端安装

系统要求

最低配置要求:

  • CPU: 1 核
  • 内存: 1 GB RAM
  • 硬盘: 空余 10 GB
  • 系统:Debian11+,Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

默认登录信息

  • 用户名: admin@webvirt.cloud
  • 密码: admin

面板地址

  • 用户面板: https://192-168-0-114.nip.io
  • 管理后台: https://192-168-0-114.nip.io/admin

注意: 请将 192.168.0.114 替换为你的公网 IP,以获取真实可访问地址。

安装命令

国际版本:

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

国内版本:

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

TIP

执行过程中可能会卡在clone仓库后一直不动,此时按ctrl+c退出执行后,重新执行安装脚本就行了,系Docker安装后卡在build项目的阶段了。

2. 计算节点安装

重要提示: Hypervisor 和 Controller 不能在同一虚拟机上安装,否则网络会出现冲突。

系统要求

建议配置:

  • CPU: 2 核
  • 内存: 4 GB RAM
  • 硬盘: 空余 40 GB
  • 系统:AlmaLinux8+,RockyLinux8+

额外说明:

  • 实际使用建议更高配置,测试环境只够开 4 台最小的虚拟机。
  • 服务器推荐支持 KVM 嵌套虚拟化的,若VM-x/AMD-V/Hyper-V未启用也可以,会自动切换为QEMU使用TCG仿真开设虚拟机,只不过性能会有所损耗。
  • 跳过 env 检测安装,直接使用二进制文件,无需安装依赖。

环境检测

检测服务器是否支持 KVM 嵌套虚拟化:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

选择硬件单项测试

计算节点安装步骤

  1. 下载安装脚本:

    国际版本:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh

    国内版本:

    bash
    curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh
  2. 执行安装(替换为你的 Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    请将 x.x.x.x 替换为你的 Controller 控制端的实际 IP 地址。

  3. 面板纳管节点
    执行完毕后会有提示需要在Controller面板端需要填写的内容。
    面板端要填入Hostname的是当前计算节点的IPV4地址,还有要填入Token识别节点。

NetworkManager 版本问题

安装过程中可能会出现以下错误:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

解决方法: 重启服务器后重新执行安装命令。

安装耗时提示

  • 整个过程大约耗时 10~25 分钟
  • 大部分时间用于下载 finnix-125.iso/var/lib/libvirt/isos/finnix-125.iso
  • 该部分无法加速,建议使用 tmux 或 screen 等工具防止中断。

添加计算节点到控制面板

安装完成后会生成一个 Token,用于在控制端(Admin 面板)中添加计算节点:

路径: Admin Panel > Computers > Add Computer

  • HostName 需要填写计算节点的公网IPV4地址
  • Token 填在计算节点上获取到的token密钥

3. 公网IPV4端口映射

3.1 自动映射

自动映射功能特点:

  • 自动监控:实时监控虚拟机状态变化,自动应用或清理端口映射规则
  • 智能端口分配:根据虚拟机IP地址自动计算和分配不冲突的端口
  • 规则持久化:使用firewall-cmd确保端口映射规则在宿主机重启后依然有效
  • 映射记录:自动维护映射信息记录文件,便于查看和管理
  • 冲突防护:智能检测并避免端口冲突,确保每个虚拟机都有唯一的端口映射

安装方法

  1. 下载脚本到临时目录: 国际版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh

    国内版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. 添加执行权限:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. 运行安装程序:

    bash
    /tmp/vm_port_mapping_setup.sh

脚本会自动完成以下操作:

  • 将自身复制到系统目录 /usr/local/sbin/vm_port_mapping_daemon.sh
  • 创建systemd服务单元文件
  • 启用并启动服务

端口映射规则

守护进程会为每个虚拟机分配以下端口:

  1. SSH端口

    • 计算公式:(IP最后一段) × 100 + 22 + 10000
    • 示例:对于IP地址 192.168.33.114,映射的SSH端口为 114×100+22+10000 = 21422
  2. 额外端口

    • 每个虚拟机分配10个额外端口
    • 起始端口:20000 + (IP最后一段) × 100
    • 结束端口:起始端口 + 9
    • 示例:对于IP地址 192.168.33.114,额外端口范围为 20000+(114×100) 至 20000+(114×100)+9

如果计算出的端口已被占用,程序会自动寻找下一个可用端口,确保不发生冲突。

映射文件

所有端口映射信息保存在 /etc/vm_port_mapping/mapping.txt 文件中,格式为:

虚拟机名字 IP地址 MAC地址 SSH映射端口 额外端口起始 额外端口结束

例如:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

服务管理

  • 查看服务状态

    bash
    systemctl status vm-port-mapping
  • 启动服务

    bash
    systemctl start vm-port-mapping
  • 停止服务

    bash
    systemctl stop vm-port-mapping
  • 禁用自启动

    bash
    systemctl disable vm-port-mapping
  • 查看日志

    bash
    journalctl -u vm-port-mapping
    -# 或
    -cat /var/log/vm_port_mapping.log
  • 手动触发规则更新

    bash
    systemctl restart vm-port-mapping

常见问题

端口映射不生效

检查以下内容:

  • 确认服务正在运行:systemctl status vm-port-mapping
  • 检查日志文件:cat /var/log/vm_port_mapping.log
  • 确认防火墙服务正常:systemctl status firewalld
  • 验证虚拟机网络接口配置:virsh domiflist 虚拟机名称
手动添加映射规则

通常不需要手动添加规则,但如果需要,可以这样操作:

  1. 停止服务:

    bash
    systemctl stop vm-port-mapping
  2. 编辑映射文件:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. 启动服务:

    bash
    systemctl start vm-port-mapping
清理所有规则
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
安全建议
  • 定期检查映射文件和日志,确保没有未授权的映射
  • 不要手动修改 /etc/vm_port_mapping/ 目录下的文件,除非你完全了解其影响
  • 确保 firewalld 服务正常运行,以便规则能够正确持久化

卸载方法

如需卸载此服务:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 手动映射

假设此时你的虚拟机在用户端控制面板显示为

wv1

且宿主机的命令执行ip a | head -n 15结果为

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet 你的公网IPV4地址/对应的子网掩码 scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

可见公网IPV4地址绑定的接口是ens3,所以后面的命令这里用ens3

那么映射当前虚拟机的22端口到公网IPV4的3322端口的命令为:

shell
# 添加 DNAT 规则:将公网3322流量转发到宿主机本地的192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# 添加 POSTROUTING:本机 NAT 伪装,以便连接正常返回
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# 需要允许 INPUT 的3322端口通过(firewalld 默认是开启了的)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

这样内网的虚拟机就被映射出来,可以直接远程登录使用了。

4. 问题排查

添加计算节点错误排查

在Controller控制端执行:

shell
telnet <node ip> 8884

在计算节点执行:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

如果以上都查不出问题,那么就需要到Controller控制端执行:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

DEBUG=False 改成 DEBUG=True,然后保存文件后,容器内执行:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

然后exit退出容器后,执行:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

然后前端去触发错误的位置,这块日志实时加载就会看到对应的报错了。

Controller 重启后 Docker 容器不自重启

如果 Docker 容器在系统重启后没有自动重启,执行以下命令:

bash
docker start $(docker ps -a -q)

5. 缺点

系统镜像是写死的,没法使用自己制作的自定义镜像,也没办法导出使用。

https://github.com/retspen/webvirtcloud 不是同一个项目,不要搞混淆了。

致谢

https://webvirt.cloud/

`,105),t=[e];function r(c,C,i,y,A,D){return a(),l("div",null,t)}const u=s(p,[["render",r]]);export{h as __pageData,u as default}; diff --git a/assets/incomplete_webvirtcloud.md.2369e889.lean.js b/assets/incomplete_webvirtcloud.md.2369e889.lean.js deleted file mode 100644 index 9833c35c84..0000000000 --- a/assets/incomplete_webvirtcloud.md.2369e889.lean.js +++ /dev/null @@ -1,48 +0,0 @@ -import{_ as s,v as a,b as l,R as n}from"./chunks/framework.70afa331.js";const o="/assets/wv1.5ac4a026.png",h=JSON.parse('{"title":"WebVirtCloud 安装指南","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud.md","filePath":"incomplete/webvirtcloud.md","lastUpdated":1747972048000}'),p={name:"incomplete/webvirtcloud.md"},e=n(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/webvirtcloud/webvirtcloud

应该算是全网中文第一份完整的部署指南,官方的指南实际上有很多地方是和本项目部署的方式有出入的。

1. 控制端安装

系统要求

最低配置要求:

  • CPU: 1 核
  • 内存: 1 GB RAM
  • 硬盘: 空余 10 GB
  • 系统:Debian11+,Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

默认登录信息

  • 用户名: admin@webvirt.cloud
  • 密码: admin

面板地址

  • 用户面板: https://192-168-0-114.nip.io
  • 管理后台: https://192-168-0-114.nip.io/admin

注意: 请将 192.168.0.114 替换为你的公网 IP,以获取真实可访问地址。

安装命令

国际版本:

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

国内版本:

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
-&& chmod +x install_webvirt_cloud.sh \\
-&& bash install_webvirt_cloud.sh

TIP

执行过程中可能会卡在clone仓库后一直不动,此时按ctrl+c退出执行后,重新执行安装脚本就行了,系Docker安装后卡在build项目的阶段了。

2. 计算节点安装

重要提示: Hypervisor 和 Controller 不能在同一虚拟机上安装,否则网络会出现冲突。

系统要求

建议配置:

  • CPU: 2 核
  • 内存: 4 GB RAM
  • 硬盘: 空余 40 GB
  • 系统:AlmaLinux8+,RockyLinux8+

额外说明:

  • 实际使用建议更高配置,测试环境只够开 4 台最小的虚拟机。
  • 服务器推荐支持 KVM 嵌套虚拟化的,若VM-x/AMD-V/Hyper-V未启用也可以,会自动切换为QEMU使用TCG仿真开设虚拟机,只不过性能会有所损耗。
  • 跳过 env 检测安装,直接使用二进制文件,无需安装依赖。

环境检测

检测服务器是否支持 KVM 嵌套虚拟化:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

选择硬件单项测试

计算节点安装步骤

  1. 下载安装脚本:

    国际版本:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh

    国内版本:

    bash
    curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    -&& chmod +x install_hypervisor.sh
  2. 执行安装(替换为你的 Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    请将 x.x.x.x 替换为你的 Controller 控制端的实际 IP 地址。

  3. 面板纳管节点
    执行完毕后会有提示需要在Controller面板端需要填写的内容。
    面板端要填入Hostname的是当前计算节点的IPV4地址,还有要填入Token识别节点。

NetworkManager 版本问题

安装过程中可能会出现以下错误:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

解决方法: 重启服务器后重新执行安装命令。

安装耗时提示

  • 整个过程大约耗时 10~25 分钟
  • 大部分时间用于下载 finnix-125.iso/var/lib/libvirt/isos/finnix-125.iso
  • 该部分无法加速,建议使用 tmux 或 screen 等工具防止中断。

添加计算节点到控制面板

安装完成后会生成一个 Token,用于在控制端(Admin 面板)中添加计算节点:

路径: Admin Panel > Computers > Add Computer

  • HostName 需要填写计算节点的公网IPV4地址
  • Token 填在计算节点上获取到的token密钥

3. 公网IPV4端口映射

3.1 自动映射

自动映射功能特点:

  • 自动监控:实时监控虚拟机状态变化,自动应用或清理端口映射规则
  • 智能端口分配:根据虚拟机IP地址自动计算和分配不冲突的端口
  • 规则持久化:使用firewall-cmd确保端口映射规则在宿主机重启后依然有效
  • 映射记录:自动维护映射信息记录文件,便于查看和管理
  • 冲突防护:智能检测并避免端口冲突,确保每个虚拟机都有唯一的端口映射

安装方法

  1. 下载脚本到临时目录: 国际版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh

    国内版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. 添加执行权限:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. 运行安装程序:

    bash
    /tmp/vm_port_mapping_setup.sh

脚本会自动完成以下操作:

  • 将自身复制到系统目录 /usr/local/sbin/vm_port_mapping_daemon.sh
  • 创建systemd服务单元文件
  • 启用并启动服务

端口映射规则

守护进程会为每个虚拟机分配以下端口:

  1. SSH端口

    • 计算公式:(IP最后一段) × 100 + 22 + 10000
    • 示例:对于IP地址 192.168.33.114,映射的SSH端口为 114×100+22+10000 = 21422
  2. 额外端口

    • 每个虚拟机分配10个额外端口
    • 起始端口:20000 + (IP最后一段) × 100
    • 结束端口:起始端口 + 9
    • 示例:对于IP地址 192.168.33.114,额外端口范围为 20000+(114×100) 至 20000+(114×100)+9

如果计算出的端口已被占用,程序会自动寻找下一个可用端口,确保不发生冲突。

映射文件

所有端口映射信息保存在 /etc/vm_port_mapping/mapping.txt 文件中,格式为:

虚拟机名字 IP地址 MAC地址 SSH映射端口 额外端口起始 额外端口结束

例如:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

服务管理

  • 查看服务状态

    bash
    systemctl status vm-port-mapping
  • 启动服务

    bash
    systemctl start vm-port-mapping
  • 停止服务

    bash
    systemctl stop vm-port-mapping
  • 禁用自启动

    bash
    systemctl disable vm-port-mapping
  • 查看日志

    bash
    journalctl -u vm-port-mapping
    -# 或
    -cat /var/log/vm_port_mapping.log
  • 手动触发规则更新

    bash
    systemctl restart vm-port-mapping

常见问题

端口映射不生效

检查以下内容:

  • 确认服务正在运行:systemctl status vm-port-mapping
  • 检查日志文件:cat /var/log/vm_port_mapping.log
  • 确认防火墙服务正常:systemctl status firewalld
  • 验证虚拟机网络接口配置:virsh domiflist 虚拟机名称
手动添加映射规则

通常不需要手动添加规则,但如果需要,可以这样操作:

  1. 停止服务:

    bash
    systemctl stop vm-port-mapping
  2. 编辑映射文件:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. 启动服务:

    bash
    systemctl start vm-port-mapping
清理所有规则
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
安全建议
  • 定期检查映射文件和日志,确保没有未授权的映射
  • 不要手动修改 /etc/vm_port_mapping/ 目录下的文件,除非你完全了解其影响
  • 确保 firewalld 服务正常运行,以便规则能够正确持久化

卸载方法

如需卸载此服务:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 手动映射

假设此时你的虚拟机在用户端控制面板显示为

wv1

且宿主机的命令执行ip a | head -n 15结果为

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet 你的公网IPV4地址/对应的子网掩码 scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

可见公网IPV4地址绑定的接口是ens3,所以后面的命令这里用ens3

那么映射当前虚拟机的22端口到公网IPV4的3322端口的命令为:

shell
# 添加 DNAT 规则:将公网3322流量转发到宿主机本地的192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# 添加 POSTROUTING:本机 NAT 伪装,以便连接正常返回
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# 需要允许 INPUT 的3322端口通过(firewalld 默认是开启了的)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

这样内网的虚拟机就被映射出来,可以直接远程登录使用了。

4. 问题排查

添加计算节点错误排查

在Controller控制端执行:

shell
telnet <node ip> 8884

在计算节点执行:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

如果以上都查不出问题,那么就需要到Controller控制端执行:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

DEBUG=False 改成 DEBUG=True,然后保存文件后,容器内执行:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

然后exit退出容器后,执行:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

然后前端去触发错误的位置,这块日志实时加载就会看到对应的报错了。

Controller 重启后 Docker 容器不自重启

如果 Docker 容器在系统重启后没有自动重启,执行以下命令:

bash
docker start $(docker ps -a -q)

5. 缺点

系统镜像是写死的,没法使用自己制作的自定义镜像,也没办法导出使用。

https://github.com/retspen/webvirtcloud 不是同一个项目,不要搞混淆了。

致谢

https://webvirt.cloud/

`,105),t=[e];function r(c,C,i,y,A,D){return a(),l("div",null,t)}const u=s(p,[["render",r]]);export{h as __pageData,u as default}; diff --git a/assets/incomplete_webvirtcloud.md.4rNDyChD.js b/assets/incomplete_webvirtcloud.md.4rNDyChD.js new file mode 100644 index 0000000000..6741556fef --- /dev/null +++ b/assets/incomplete_webvirtcloud.md.4rNDyChD.js @@ -0,0 +1,48 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const n="/assets/wv1.8ARiSJ9x.png",c=JSON.parse('{"title":"WebVirtCloud 安装指南","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud.md","filePath":"incomplete/webvirtcloud.md","lastUpdated":1747984962000}'),h={name:"incomplete/webvirtcloud.md"};function p(e,s,k,r,d,o){return t(),a("div",null,s[0]||(s[0]=[l(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/webvirtcloud/webvirtcloud

应该算是全网中文第一份完整的部署指南,官方的指南实际上有很多地方是和本项目部署的方式有出入的。

1. 控制端安装

系统要求

最低配置要求:

  • CPU: 1 核
  • 内存: 1 GB RAM
  • 硬盘: 空余 10 GB
  • 系统:Debian11+,Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

默认登录信息

  • 用户名: admin@webvirt.cloud
  • 密码: admin

面板地址

  • 用户面板: https://192-168-0-114.nip.io
  • 管理后台: https://192-168-0-114.nip.io/admin

注意: 请将 192.168.0.114 替换为你的公网 IP,以获取真实可访问地址。

安装命令

国际版本:

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
+&& chmod +x install_webvirt_cloud.sh \\
+&& bash install_webvirt_cloud.sh

国内版本:

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \\
+&& chmod +x install_webvirt_cloud.sh \\
+&& bash install_webvirt_cloud.sh

TIP

执行过程中可能会卡在clone仓库后一直不动,此时按ctrl+c退出执行后,重新执行安装脚本就行了,系Docker安装后卡在build项目的阶段了。

2. 计算节点安装

重要提示: Hypervisor 和 Controller 不能在同一虚拟机上安装,否则网络会出现冲突。

系统要求

建议配置:

  • CPU: 2 核
  • 内存: 4 GB RAM
  • 硬盘: 空余 40 GB
  • 系统:AlmaLinux8+,RockyLinux8+

额外说明:

  • 实际使用建议更高配置,测试环境只够开 4 台最小的虚拟机。
  • 服务器推荐支持 KVM 嵌套虚拟化的,若VM-x/AMD-V/Hyper-V未启用也可以,会自动切换为QEMU使用TCG仿真开设虚拟机,只不过性能会有所损耗。
  • 跳过 env 检测安装,直接使用二进制文件,无需安装依赖。

环境检测

检测服务器是否支持 KVM 嵌套虚拟化:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

选择硬件单项测试

计算节点安装步骤

  1. 下载安装脚本:

    国际版本:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    +&& chmod +x install_hypervisor.sh

    国内版本:

    bash
    curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \\
    +&& chmod +x install_hypervisor.sh
  2. 执行安装(替换为你的 Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    请将 x.x.x.x 替换为你的 Controller 控制端的实际 IP 地址。

  3. 面板纳管节点
    执行完毕后会有提示需要在Controller面板端需要填写的内容。
    面板端要填入Hostname的是当前计算节点的IPV4地址,还有要填入Token识别节点。

NetworkManager 版本问题

安装过程中可能会出现以下错误:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
+Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
+Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

解决方法: 重启服务器后重新执行安装命令。

安装耗时提示

  • 整个过程大约耗时 10~25 分钟
  • 大部分时间用于下载 finnix-125.iso/var/lib/libvirt/isos/finnix-125.iso
  • 该部分无法加速,建议使用 tmux 或 screen 等工具防止中断。

添加计算节点到控制面板

安装完成后会生成一个 Token,用于在控制端(Admin 面板)中添加计算节点:

路径: Admin Panel > Computers > Add Computer

  • HostName 需要填写计算节点的公网IPV4地址
  • Token 填在计算节点上获取到的token密钥

3. 公网IPV4端口映射

3.1 自动映射

自动映射功能特点:

  • 自动监控:实时监控虚拟机状态变化,自动应用或清理端口映射规则
  • 智能端口分配:根据虚拟机IP地址自动计算和分配不冲突的端口
  • 规则持久化:使用firewall-cmd确保端口映射规则在宿主机重启后依然有效
  • 映射记录:自动维护映射信息记录文件,便于查看和管理
  • 冲突防护:智能检测并避免端口冲突,确保每个虚拟机都有唯一的端口映射

安装方法

  1. 下载脚本到临时目录: 国际版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh

    国内版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. 添加执行权限:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. 运行安装程序:

    bash
    /tmp/vm_port_mapping_setup.sh

脚本会自动完成以下操作:

  • 将自身复制到系统目录 /usr/local/sbin/vm_port_mapping_daemon.sh
  • 创建systemd服务单元文件
  • 启用并启动服务

端口映射规则

守护进程会为每个虚拟机分配以下端口:

  1. SSH端口

    • 计算公式:(IP最后一段) × 100 + 22 + 10000
    • 示例:对于IP地址 192.168.33.114,映射的SSH端口为 114×100+22+10000 = 21422
  2. 额外端口

    • 每个虚拟机分配10个额外端口
    • 起始端口:20000 + (IP最后一段) × 100
    • 结束端口:起始端口 + 9
    • 示例:对于IP地址 192.168.33.114,额外端口范围为 20000+(114×100) 至 20000+(114×100)+9

如果计算出的端口已被占用,程序会自动寻找下一个可用端口,确保不发生冲突。

映射文件

所有端口映射信息保存在 /etc/vm_port_mapping/mapping.txt 文件中,格式为:

虚拟机名字 IP地址 MAC地址 SSH映射端口 额外端口起始 额外端口结束

例如:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

服务管理

  • 查看服务状态

    bash
    systemctl status vm-port-mapping
  • 启动服务

    bash
    systemctl start vm-port-mapping
  • 停止服务

    bash
    systemctl stop vm-port-mapping
  • 禁用自启动

    bash
    systemctl disable vm-port-mapping
  • 查看日志

    bash
    journalctl -u vm-port-mapping
    +# 或
    +cat /var/log/vm_port_mapping.log
  • 手动触发规则更新

    bash
    systemctl restart vm-port-mapping

常见问题

端口映射不生效

检查以下内容:

  • 确认服务正在运行:systemctl status vm-port-mapping
  • 检查日志文件:cat /var/log/vm_port_mapping.log
  • 确认防火墙服务正常:systemctl status firewalld
  • 验证虚拟机网络接口配置:virsh domiflist 虚拟机名称
手动添加映射规则

通常不需要手动添加规则,但如果需要,可以这样操作:

  1. 停止服务:

    bash
    systemctl stop vm-port-mapping
  2. 编辑映射文件:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. 启动服务:

    bash
    systemctl start vm-port-mapping
清理所有规则
bash
systemctl stop vm-port-mapping
+grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
+  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
+  for ((port=port_start; port<=port_end; port++)); do
+    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
+  done
+done
+firewall-cmd --reload
安全建议
  • 定期检查映射文件和日志,确保没有未授权的映射
  • 不要手动修改 /etc/vm_port_mapping/ 目录下的文件,除非你完全了解其影响
  • 确保 firewalld 服务正常运行,以便规则能够正确持久化

卸载方法

如需卸载此服务:

bash
systemctl stop vm-port-mapping
+systemctl disable vm-port-mapping
+rm -f /etc/systemd/system/vm-port-mapping.service
+rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
+rm -rf /etc/vm_port_mapping
+systemctl daemon-reload

3.2 手动映射

假设此时你的虚拟机在用户端控制面板显示为

wv1

且宿主机的命令执行ip a | head -n 15结果为

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    inet 127.0.0.1/8 scope host lo
+       valid_lft forever preferred_lft forever
+    inet6 ::1/128 scope host
+       valid_lft forever preferred_lft forever
+2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
+    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
+    altname enp0s3
+    inet 你的公网IPV4地址/对应的子网掩码 scope global noprefixroute ens3
+       valid_lft forever preferred_lft forever
+    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
+       valid_lft forever preferred_lft forever
+    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
+       valid_lft forever preferred_lft forever

可见公网IPV4地址绑定的接口是ens3,所以后面的命令这里用ens3

那么映射当前虚拟机的22端口到公网IPV4的3322端口的命令为:

shell
# 添加 DNAT 规则:将公网3322流量转发到宿主机本地的192.168.33.130:22
+iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
+# 添加 POSTROUTING:本机 NAT 伪装,以便连接正常返回
+iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
+# 需要允许 INPUT 的3322端口通过(firewalld 默认是开启了的)
+iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

这样内网的虚拟机就被映射出来,可以直接远程登录使用了。

4. 问题排查

添加计算节点错误排查

在Controller控制端执行:

shell
telnet <node ip> 8884

在计算节点执行:

shell
systemctl status webvirtcompute
+systemctl status libvirtd
+systemctl status prometheus
+systemctl status prometheus-libvirt-exporter

如果以上都查不出问题,那么就需要到Controller控制端执行:

shell
docker exec -it webvirtcloud-backend /bin/sh
+vi webvirtcloud/settings/production.py

DEBUG=False 改成 DEBUG=True,然后保存文件后,容器内执行:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

然后exit退出容器后,执行:

shell
docker restart webvirtcloud-backend
+sleep 3
+docker logs webvirtcloud-backend -f

然后前端去触发错误的位置,这块日志实时加载就会看到对应的报错了。

Controller 重启后 Docker 容器不自重启

如果 Docker 容器在系统重启后没有自动重启,执行以下命令:

bash
docker start $(docker ps -a -q)

5. 缺点

系统镜像是写死的,没法使用自己制作的自定义镜像,也没办法导出使用。

https://github.com/retspen/webvirtcloud 不是同一个项目,不要搞混淆了。

致谢

https://webvirt.cloud/

`,105)]))}const g=i(h,[["render",p]]);export{c as __pageData,g as default}; diff --git a/assets/incomplete_webvirtcloud.md.4rNDyChD.lean.js b/assets/incomplete_webvirtcloud.md.4rNDyChD.lean.js new file mode 100644 index 0000000000..da9e436747 --- /dev/null +++ b/assets/incomplete_webvirtcloud.md.4rNDyChD.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as l}from"./chunks/framework.CSeR4K32.js";const n="/assets/wv1.8ARiSJ9x.png",c=JSON.parse('{"title":"WebVirtCloud 安装指南","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud.md","filePath":"incomplete/webvirtcloud.md","lastUpdated":1747984962000}'),h={name:"incomplete/webvirtcloud.md"};function p(e,s,k,r,d,o){return t(),a("div",null,s[0]||(s[0]=[l("",105)]))}const g=i(h,[["render",p]]);export{c as __pageData,g as default}; diff --git a/assets/incomplete_webvirtcloud_retspen.md.8469ad25.js b/assets/incomplete_webvirtcloud_retspen.md.8469ad25.js deleted file mode 100644 index 77771e028c..0000000000 --- a/assets/incomplete_webvirtcloud_retspen.md.8469ad25.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as e,R as p}from"./chunks/framework.70afa331.js";const t="/assets/vcr1.30d933ab.jpg",l="/assets/vcr2.9b30a319.jpg",o="/assets/vcr3.0aa5a564.jpg",n="/assets/vcr4.18a1487e.jpg",c="/assets/vcr5.97deb479.jpg",r="/assets/vcr6.e706123b.jpg",i="/assets/vcr7.43c60335.jpg",d="/assets/vcr8.1bf1f353.jpg",m="/assets/vcr9.b5afa4b4.jpg",h="/assets/vcr10.548c566e.jpg",C="/assets/vcr11.58ce8ace.jpg",_="/assets/vcr12.3aa69b2a.jpg",b="/assets/vcr13.fcbcc557.jpg",v="/assets/vcr14.7009c833.jpg",q=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud_retspen.md","filePath":"incomplete/webvirtcloud_retspen.md","lastUpdated":1747972048000}'),u={name:"incomplete/webvirtcloud_retspen.md"},g=p(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtcloud

控制节点和计算节点同时安装

  • 支持系统:Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • 推荐系统:Debian12+,Ubuntu22.04+
  • 低版本系统会自动编译python新版本的安装包后再进行部署,所以推荐使用新系统不必编译直接安装

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

安装完成后打开公网IP地址,就能看到登录页面。

登录信息用户名和密码都是admin,记得登录后自行修改。

开设Linux虚拟机

进入控制面板后,修改完admin的密码后,需要自行设置计算节点。

vcr1

选择本地类型,添加命名为local。

vcr2

创建完成后,点击眼睛按钮,进入查看

vcr3

存储一栏中添加存储,选择Dir类型,添加名字叫local。如果你需要使用ISO类型的系统引导,那么需要创建ISO类型的存储,如果不需要的话跟着本指南走,就仅需要创建Dir类型。

vcr4

vcr5

创建完毕后,下载对应系统的qcow2文件,使用下面这个仓库的链接

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

示例中下载使用debian12的qcow2镜像使用

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

回到实例页面创建实例

vcr6

计算节点选择local

vcr7

芯片组使用默认的就行,换不换都没问题

vcr8

创建虚拟机可以使用预定义的配置大小,也可以自行使用自定义大小,看你的选择。

vcr9

注意这块填写的实例名字不能和系统名字重复,比如示例中就不能填写debian12

vcr10

创建成功后不能立即点击开机。

vcr11

需要修改磁盘设置。

vcr12

这块修改qcow2文件为debian12.qcow2,对应之前下载的qcow2的文件的名字,使用镜像。

vcr13

修改完成确认无误后,才可回到电源页面开机。

vcr14

镜像的默认登录的用户名是root,密码是password或者是 oneclickvirt

缺点

网络还是没有自动配置,不如上一个项目智能,还得手动配置一下。

',47),y=[g];function D(A,w,F,f,k,E){return a(),e("div",null,y)}const x=s(u,[["render",D]]);export{q as __pageData,x as default}; diff --git a/assets/incomplete_webvirtcloud_retspen.md.8469ad25.lean.js b/assets/incomplete_webvirtcloud_retspen.md.8469ad25.lean.js deleted file mode 100644 index 77771e028c..0000000000 --- a/assets/incomplete_webvirtcloud_retspen.md.8469ad25.lean.js +++ /dev/null @@ -1,7 +0,0 @@ -import{_ as s,v as a,b as e,R as p}from"./chunks/framework.70afa331.js";const t="/assets/vcr1.30d933ab.jpg",l="/assets/vcr2.9b30a319.jpg",o="/assets/vcr3.0aa5a564.jpg",n="/assets/vcr4.18a1487e.jpg",c="/assets/vcr5.97deb479.jpg",r="/assets/vcr6.e706123b.jpg",i="/assets/vcr7.43c60335.jpg",d="/assets/vcr8.1bf1f353.jpg",m="/assets/vcr9.b5afa4b4.jpg",h="/assets/vcr10.548c566e.jpg",C="/assets/vcr11.58ce8ace.jpg",_="/assets/vcr12.3aa69b2a.jpg",b="/assets/vcr13.fcbcc557.jpg",v="/assets/vcr14.7009c833.jpg",q=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud_retspen.md","filePath":"incomplete/webvirtcloud_retspen.md","lastUpdated":1747972048000}'),u={name:"incomplete/webvirtcloud_retspen.md"},g=p(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtcloud

控制节点和计算节点同时安装

  • 支持系统:Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • 推荐系统:Debian12+,Ubuntu22.04+
  • 低版本系统会自动编译python新版本的安装包后再进行部署,所以推荐使用新系统不必编译直接安装

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
-&& chmod +x install_webvirt_cloud_retspen.sh \\
-&& bash install_webvirt_cloud_retspen.sh

安装完成后打开公网IP地址,就能看到登录页面。

登录信息用户名和密码都是admin,记得登录后自行修改。

开设Linux虚拟机

进入控制面板后,修改完admin的密码后,需要自行设置计算节点。

vcr1

选择本地类型,添加命名为local。

vcr2

创建完成后,点击眼睛按钮,进入查看

vcr3

存储一栏中添加存储,选择Dir类型,添加名字叫local。如果你需要使用ISO类型的系统引导,那么需要创建ISO类型的存储,如果不需要的话跟着本指南走,就仅需要创建Dir类型。

vcr4

vcr5

创建完毕后,下载对应系统的qcow2文件,使用下面这个仓库的链接

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

示例中下载使用debian12的qcow2镜像使用

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

回到实例页面创建实例

vcr6

计算节点选择local

vcr7

芯片组使用默认的就行,换不换都没问题

vcr8

创建虚拟机可以使用预定义的配置大小,也可以自行使用自定义大小,看你的选择。

vcr9

注意这块填写的实例名字不能和系统名字重复,比如示例中就不能填写debian12

vcr10

创建成功后不能立即点击开机。

vcr11

需要修改磁盘设置。

vcr12

这块修改qcow2文件为debian12.qcow2,对应之前下载的qcow2的文件的名字,使用镜像。

vcr13

修改完成确认无误后,才可回到电源页面开机。

vcr14

镜像的默认登录的用户名是root,密码是password或者是 oneclickvirt

缺点

网络还是没有自动配置,不如上一个项目智能,还得手动配置一下。

',47),y=[g];function D(A,w,F,f,k,E){return a(),e("div",null,y)}const x=s(u,[["render",D]]);export{q as __pageData,x as default}; diff --git a/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.js b/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.js new file mode 100644 index 0000000000..5979d0e2e6 --- /dev/null +++ b/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.js @@ -0,0 +1,7 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const p="/assets/vcr1.NRLOOynQ.jpg",l="/assets/vcr2.DC9j-Ib5.jpg",n="/assets/vcr3.Ea5Km6nQ.jpg",r="/assets/vcr4.B9DOiqQ8.jpg",c="/assets/vcr5.BajXu8XE.jpg",h="/assets/vcr6.CxN-b1o3.jpg",o="/assets/vcr7.D4aYKhIW.jpg",d="/assets/vcr8.ByRFpMlF.jpg",k="/assets/vcr9.B4apCqgi.jpg",g="/assets/vcr10.D8t6cQ5v.jpg",m="/assets/vcr11.Cz1VMbIx.jpg",_="/assets/vcr12.BNQe5j_u.jpg",v="/assets/vcr13.JV3PfcCZ.jpg",b="/assets/vcr14.Cjyr65Qp.jpg",x=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud_retspen.md","filePath":"incomplete/webvirtcloud_retspen.md","lastUpdated":1747984962000}'),u={name:"incomplete/webvirtcloud_retspen.md"};function F(C,s,y,B,w,E){return t(),a("div",null,s[0]||(s[0]=[e(`

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtcloud

控制节点和计算节点同时安装

  • 支持系统:Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • 推荐系统:Debian12+,Ubuntu22.04+
  • 低版本系统会自动编译python新版本的安装包后再进行部署,所以推荐使用新系统不必编译直接安装

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
+&& chmod +x install_webvirt_cloud_retspen.sh \\
+&& bash install_webvirt_cloud_retspen.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \\
+&& chmod +x install_webvirt_cloud_retspen.sh \\
+&& bash install_webvirt_cloud_retspen.sh

安装完成后打开公网IP地址,就能看到登录页面。

登录信息用户名和密码都是admin,记得登录后自行修改。

开设Linux虚拟机

进入控制面板后,修改完admin的密码后,需要自行设置计算节点。

vcr1

选择本地类型,添加命名为local。

vcr2

创建完成后,点击眼睛按钮,进入查看

vcr3

存储一栏中添加存储,选择Dir类型,添加名字叫local。如果你需要使用ISO类型的系统引导,那么需要创建ISO类型的存储,如果不需要的话跟着本指南走,就仅需要创建Dir类型。

vcr4

vcr5

创建完毕后,下载对应系统的qcow2文件,使用下面这个仓库的链接

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

示例中下载使用debian12的qcow2镜像使用

shell
cd /var/lib/libvirt/images
+wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
+chmod 777 debian12.qcow2

回到实例页面创建实例

vcr6

计算节点选择local

vcr7

芯片组使用默认的就行,换不换都没问题

vcr8

创建虚拟机可以使用预定义的配置大小,也可以自行使用自定义大小,看你的选择。

vcr9

注意这块填写的实例名字不能和系统名字重复,比如示例中就不能填写debian12

vcr10

创建成功后不能立即点击开机。

vcr11

需要修改磁盘设置。

vcr12

这块修改qcow2文件为debian12.qcow2,对应之前下载的qcow2的文件的名字,使用镜像。

vcr13

修改完成确认无误后,才可回到电源页面开机。

vcr14

镜像的默认登录的用户名是root,密码是password或者是 oneclickvirt

缺点

网络还是没有自动配置,不如上一个项目智能,还得手动配置一下。

',47)]))}const j=i(u,[["render",F]]);export{x as __pageData,j as default}; diff --git a/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.lean.js b/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.lean.js new file mode 100644 index 0000000000..658d1c840f --- /dev/null +++ b/assets/incomplete_webvirtcloud_retspen.md.BzOOyV6B.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const p="/assets/vcr1.NRLOOynQ.jpg",l="/assets/vcr2.DC9j-Ib5.jpg",n="/assets/vcr3.Ea5Km6nQ.jpg",r="/assets/vcr4.B9DOiqQ8.jpg",c="/assets/vcr5.BajXu8XE.jpg",h="/assets/vcr6.CxN-b1o3.jpg",o="/assets/vcr7.D4aYKhIW.jpg",d="/assets/vcr8.ByRFpMlF.jpg",k="/assets/vcr9.B4apCqgi.jpg",g="/assets/vcr10.D8t6cQ5v.jpg",m="/assets/vcr11.Cz1VMbIx.jpg",_="/assets/vcr12.BNQe5j_u.jpg",v="/assets/vcr13.JV3PfcCZ.jpg",b="/assets/vcr14.Cjyr65Qp.jpg",x=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtcloud_retspen.md","filePath":"incomplete/webvirtcloud_retspen.md","lastUpdated":1747984962000}'),u={name:"incomplete/webvirtcloud_retspen.md"};function F(C,s,y,B,w,E){return t(),a("div",null,s[0]||(s[0]=[e("",47)]))}const j=i(u,[["render",F]]);export{x as __pageData,j as default}; diff --git a/assets/incomplete_webvirtmgr.md.d2161404.js b/assets/incomplete_webvirtmgr.md.d2161404.js deleted file mode 100644 index 2fdbb02b31..0000000000 --- a/assets/incomplete_webvirtmgr.md.d2161404.js +++ /dev/null @@ -1,5 +0,0 @@ -import{_ as s,v as a,b as t,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtmgr.md","filePath":"incomplete/webvirtmgr.md","lastUpdated":1747972048000}'),n={name:"incomplete/webvirtmgr.md"},e=l(`

WebVirtMgr 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtmgr

控制节点和计算节点同时安装

  • 支持系统:Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • 系统会自动编译python的2.7的安装包后再进行部署,编译过程中会有报错提示但不用理会,只要脚本还在跑就说明一切正常

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

缺点

原项目已经不再有维护,完全不推荐使用。

`,12),p=[e];function o(r,c,i,h,C,m){return a(),t("div",null,p)}const D=s(n,[["render",o]]);export{y as __pageData,D as default}; diff --git a/assets/incomplete_webvirtmgr.md.d2161404.lean.js b/assets/incomplete_webvirtmgr.md.d2161404.lean.js deleted file mode 100644 index 2fdbb02b31..0000000000 --- a/assets/incomplete_webvirtmgr.md.d2161404.lean.js +++ /dev/null @@ -1,5 +0,0 @@ -import{_ as s,v as a,b as t,R as l}from"./chunks/framework.70afa331.js";const y=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtmgr.md","filePath":"incomplete/webvirtmgr.md","lastUpdated":1747972048000}'),n={name:"incomplete/webvirtmgr.md"},e=l(`

WebVirtMgr 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtmgr

控制节点和计算节点同时安装

  • 支持系统:Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • 系统会自动编译python的2.7的安装包后再进行部署,编译过程中会有报错提示但不用理会,只要脚本还在跑就说明一切正常

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
-&& chmod +x install_webvirtmgr.sh \\
-&& bash install_webvirtmgr.sh

缺点

原项目已经不再有维护,完全不推荐使用。

`,12),p=[e];function o(r,c,i,h,C,m){return a(),t("div",null,p)}const D=s(n,[["render",o]]);export{y as __pageData,D as default}; diff --git a/assets/incomplete_webvirtmgr.md.y6DQ_-c0.js b/assets/incomplete_webvirtmgr.md.y6DQ_-c0.js new file mode 100644 index 0000000000..9b76b2f122 --- /dev/null +++ b/assets/incomplete_webvirtmgr.md.y6DQ_-c0.js @@ -0,0 +1,5 @@ +import{_ as s,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtmgr.md","filePath":"incomplete/webvirtmgr.md","lastUpdated":1747984962000}'),l={name:"incomplete/webvirtmgr.md"};function h(n,i,r,p,k,d){return t(),a("div",null,i[0]||(i[0]=[e(`

WebVirtMgr 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtmgr

控制节点和计算节点同时安装

  • 支持系统:Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • 系统会自动编译python的2.7的安装包后再进行部署,编译过程中会有报错提示但不用理会,只要脚本还在跑就说明一切正常

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
+&& chmod +x install_webvirtmgr.sh \\
+&& bash install_webvirtmgr.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \\
+&& chmod +x install_webvirtmgr.sh \\
+&& bash install_webvirtmgr.sh

缺点

原项目已经不再有维护,完全不推荐使用。

`,12)]))}const g=s(l,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/incomplete_webvirtmgr.md.y6DQ_-c0.lean.js b/assets/incomplete_webvirtmgr.md.y6DQ_-c0.lean.js new file mode 100644 index 0000000000..0262b89046 --- /dev/null +++ b/assets/incomplete_webvirtmgr.md.y6DQ_-c0.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as t,ag as e}from"./chunks/framework.CSeR4K32.js";const c=JSON.parse('{"title":"","description":"","frontmatter":{"outline":"deep"},"headers":[],"relativePath":"incomplete/webvirtmgr.md","filePath":"incomplete/webvirtmgr.md","lastUpdated":1747984962000}'),l={name:"incomplete/webvirtmgr.md"};function h(n,i,r,p,k,d){return t(),a("div",null,i[0]||(i[0]=[e("",12)]))}const g=s(l,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/index.md.33ff85ee.js b/assets/index.md.BVw2CyLu.js similarity index 89% rename from assets/index.md.33ff85ee.js rename to assets/index.md.BVw2CyLu.js index ac6bc5d6c4..d31e8d84a0 100644 --- a/assets/index.md.33ff85ee.js +++ b/assets/index.md.BVw2CyLu.js @@ -1 +1 @@ -import{_ as t,v as e,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"库苏恩","titleTemplate":"一键虚拟化项目","description":"","frontmatter":{"layout":"home","title":"库苏恩","titleTemplate":"一键虚拟化项目","tagline":"开源、易于使用的服务器虚拟化项目","hero":{"name":"一键虚拟化项目","text":"开源、易于使用的服务器虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/guide/dashboard"}]},"features":[{"title":"一键使用","details":"支持一键命令安装使用,轻松在X86_64和ARM架构的服务器上创建虚拟机或容器"},{"title":"基于主流系统开发","details":"基于 Debian、Ubuntu、Centos 等系统的长期维护版本开发,无论是什么系统总有一个方法能让你虚拟化出容器或虚拟机"},{"title":"端口转发和IP分配自动化","details":"自带内外网端口转发和IP地址自动分配(含IPV6、IPV4),支持TCP/UDP、VNC/RDP等协议,无需人工管理"},{"title":"批量虚拟化","details":"支持使用 QEMU、KVM、LXC、Docker 虚拟化批量开设容器或虚拟机"},{"title":"多系统多环境支持","details":"开设出的容器或虚拟机已支持主流系统,涵盖 Linux、Windows、MacOS、Android 系统,也支持纯粹的浏览器环境或桌面环境"},{"title":"自限制滥用","details":"部分虚拟化开设的容器或虚拟机支持设置屏蔽和装载限制,避免被用于滥用"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1747972048000}'),a={name:"index.md"};function s(n,d,l,r,o,p){return e(),i("div")}const h=t(a,[["render",s]]);export{m as __pageData,h as default}; +import{_ as t,c as e,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"库苏恩","titleTemplate":"一键虚拟化项目","description":"","frontmatter":{"layout":"home","title":"库苏恩","titleTemplate":"一键虚拟化项目","tagline":"开源、易于使用的服务器虚拟化项目","hero":{"name":"一键虚拟化项目","text":"开源、易于使用的服务器虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/guide/dashboard"}]},"features":[{"title":"一键使用","details":"支持一键命令安装使用,轻松在X86_64和ARM架构的服务器上创建虚拟机或容器"},{"title":"基于主流系统开发","details":"基于 Debian、Ubuntu、Centos 等系统的长期维护版本开发,无论是什么系统总有一个方法能让你虚拟化出容器或虚拟机"},{"title":"端口转发和IP分配自动化","details":"自带内外网端口转发和IP地址自动分配(含IPV6、IPV4),支持TCP/UDP、VNC/RDP等协议,无需人工管理"},{"title":"批量虚拟化","details":"支持使用 QEMU、KVM、LXC、Docker 虚拟化批量开设容器或虚拟机"},{"title":"多系统多环境支持","details":"开设出的容器或虚拟机已支持主流系统,涵盖 Linux、Windows、MacOS、Android 系统,也支持纯粹的浏览器环境或桌面环境"},{"title":"自限制滥用","details":"部分虚拟化开设的容器或虚拟机支持设置屏蔽和装载限制,避免被用于滥用"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1747984962000}'),i={name:"index.md"};function n(s,l,d,o,r,c){return a(),e("div")}const h=t(i,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/index.md.33ff85ee.lean.js b/assets/index.md.BVw2CyLu.lean.js similarity index 89% rename from assets/index.md.33ff85ee.lean.js rename to assets/index.md.BVw2CyLu.lean.js index ac6bc5d6c4..d31e8d84a0 100644 --- a/assets/index.md.33ff85ee.lean.js +++ b/assets/index.md.BVw2CyLu.lean.js @@ -1 +1 @@ -import{_ as t,v as e,b as i}from"./chunks/framework.70afa331.js";const m=JSON.parse('{"title":"库苏恩","titleTemplate":"一键虚拟化项目","description":"","frontmatter":{"layout":"home","title":"库苏恩","titleTemplate":"一键虚拟化项目","tagline":"开源、易于使用的服务器虚拟化项目","hero":{"name":"一键虚拟化项目","text":"开源、易于使用的服务器虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/guide/dashboard"}]},"features":[{"title":"一键使用","details":"支持一键命令安装使用,轻松在X86_64和ARM架构的服务器上创建虚拟机或容器"},{"title":"基于主流系统开发","details":"基于 Debian、Ubuntu、Centos 等系统的长期维护版本开发,无论是什么系统总有一个方法能让你虚拟化出容器或虚拟机"},{"title":"端口转发和IP分配自动化","details":"自带内外网端口转发和IP地址自动分配(含IPV6、IPV4),支持TCP/UDP、VNC/RDP等协议,无需人工管理"},{"title":"批量虚拟化","details":"支持使用 QEMU、KVM、LXC、Docker 虚拟化批量开设容器或虚拟机"},{"title":"多系统多环境支持","details":"开设出的容器或虚拟机已支持主流系统,涵盖 Linux、Windows、MacOS、Android 系统,也支持纯粹的浏览器环境或桌面环境"},{"title":"自限制滥用","details":"部分虚拟化开设的容器或虚拟机支持设置屏蔽和装载限制,避免被用于滥用"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1747972048000}'),a={name:"index.md"};function s(n,d,l,r,o,p){return e(),i("div")}const h=t(a,[["render",s]]);export{m as __pageData,h as default}; +import{_ as t,c as e,o as a}from"./chunks/framework.CSeR4K32.js";const m=JSON.parse('{"title":"库苏恩","titleTemplate":"一键虚拟化项目","description":"","frontmatter":{"layout":"home","title":"库苏恩","titleTemplate":"一键虚拟化项目","tagline":"开源、易于使用的服务器虚拟化项目","hero":{"name":"一键虚拟化项目","text":"开源、易于使用的服务器虚拟化项目","image":"https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritlhls/pages/main/logo.png","actions":[{"theme":"brand","text":"开始使用 →","link":"/guide/dashboard"}]},"features":[{"title":"一键使用","details":"支持一键命令安装使用,轻松在X86_64和ARM架构的服务器上创建虚拟机或容器"},{"title":"基于主流系统开发","details":"基于 Debian、Ubuntu、Centos 等系统的长期维护版本开发,无论是什么系统总有一个方法能让你虚拟化出容器或虚拟机"},{"title":"端口转发和IP分配自动化","details":"自带内外网端口转发和IP地址自动分配(含IPV6、IPV4),支持TCP/UDP、VNC/RDP等协议,无需人工管理"},{"title":"批量虚拟化","details":"支持使用 QEMU、KVM、LXC、Docker 虚拟化批量开设容器或虚拟机"},{"title":"多系统多环境支持","details":"开设出的容器或虚拟机已支持主流系统,涵盖 Linux、Windows、MacOS、Android 系统,也支持纯粹的浏览器环境或桌面环境"},{"title":"自限制滥用","details":"部分虚拟化开设的容器或虚拟机支持设置屏蔽和装载限制,避免被用于滥用"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1747984962000}'),i={name:"index.md"};function n(s,l,d,o,r,c){return a(),e("div")}const h=t(i,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 b/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2 deleted file mode 100644 index 2a687296748f6b8bc8076cd11bde49cd27e4442b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28332 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 HNCp4^t1hY; diff --git a/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 b/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b6b603d596933f026dfecf98550bbe4d0876276b GIT binary patch literal 43112 zcmV)0K+eB+Pew8T0RR910H|mH6951J0UBrk0H^f;1ONa400000000000000000000 z0000Qh94W4P8=#fNLE2oicCLERzXsMC9Sl=Wtg7rQD zHUcCAhIk8uJ^%zD1&nkDAX_XBaRL>&)ao+mHU!|MHg&0Sk(r3xtq{uU6G{_q3_WZd zz$4~nWdHwvQc@X1lj_qJ0YMzwArDGrm?4A}aeA@jS5;H51$Rmqq#B7?95rGNFI6|` z(duP%6x?sdXY}Y#s9rZs%E9gt*iIp=b<@Jk>{j<_xevtcR7&(U5-;uTq`#Y&E@}{k zxXD^Fqqte*BDqT}Zi&Gk#Mf|h=y0-}o&213t9j~q$RXM{YPjder~HLJ8%==k(;qKy3K{IUB%xm zDsIE$bp1=}X`05gnzX6aJxy{j56_L zLQcd%;`&~HJsDrJW_a4>d&hA{Nt%hyNLF?&qFj~s+^=YLS&kL0B0b+-|x3)hD5eTXjF;sBks*LGK6BDNMxvx zf|hib=bz^O@zGfYh`X z_yO`CpzH1h+3#A#v=GwJw%XAHfK^=;*-mAPcLQr)8z=5K2SAKwOuZg zEIkBx`o`Ma`R<)3hruP|mFgw)`p0S_K~j+b?7%_r`0alX==Lw2eWm@}R*n6=;Qq*3 zgvu!-in6Wl*KJF!mcAwXgKW+4g1zXOC9($XS*BwO$ukGY(S;jc#uVfiBn_PL z9Gx%6j}LO$Xpo}@NZ9}=jhoPDs|l{gAK(NKBzH-rqDI;jfpO2xNouqwb3n(O_lR=g*F`__{ zCV;vqT-Ou6uDVuNcvXwB-~Z3-2Glj5Yn(!_nj(_#_qR6Q{LGqGytKz5;ul#&WWNkz zTKgGmeWFo+e>2sb&2?Mrm>^IxYKr&-V%lA%6A2YxFl+tVGMsLH*D6{~fMBy*BXBzW zBnd6Xy`0QJ1R^kvW){y9Qr3Z44`=gow#u+mI(@chHuo``2U)y8*mE)mS>~#VdGXdn zG6e#d0zsTC7=?ukXHlpu4qY?I6kst0l9>W*PL?Kvab+_;J`>7eg^E}S5tERxS~AwG zm+e(K@rsL-ShIFy1po^||78yZI0@h)fExhr19%w_05S^5qJW$OkedL;qlhwKNnQZp zu>k-}N~l~qk=?#|LGk+VKSlC0wv6T!&$U1S02lx;{MHxqAAjRkfLs#zs&_9Q9vsKU zTm6F6fkEhp`_o&GuQ5KhYq$rFe-Ojx{F6VQebG-#-anqd{l$V$Ki&B0Z*IjO(EFZ1 z9-o{(binlw?J~Ogp$#7cMgT`1)T9ahe?JB?+7B7Oy*(X)z5+2c{tbVrx(WR|D+tM^ z)tG^g@JD~EH-E}_nf(0sPa^;Pvmf;Pm;XX#@#KB%%4%!qYV`5g2J4C8i|+fT{AB-3 z+4ZYy-FD&U2A9>Q!@u1>MvfMXUDY#;&8Rs8$5&?W2XNCYBz`gOcl6f)IKfoPeaydm zqVHS%&wcjGJ6~Aizp^X;hxWC-uVp*gf1k4brR@vrW>kFIwmFm6=)MbUoEb!c6i}u<)j0k$J^p=<&RBHpZiHcw0VT2q-9N#uT(7~ zGrJycUNI?Yc?G9vVztEZbri*lmo?2E7XcHiW=e*?zxa9FA;w3=i znFcJr%KUrV{1JPXK(jc(U#48<^T07*f;%-b<{X;LH-vxo$E~lidxtMa?8M8b0W`Xt zO=H&n*<$(g=APx8UB`0zt_y&=xoDr6Hvh)$W%Jzf5v$0B_UH8MP5}OZ?dNI+H<;hD zdIa<7a&CYd?Z2rN_a9E5?XQOhdE-A@eq(;ba)|k-#lPlX&}#mV_ITs0S$899GFukj zPxhD_i%q64dHb@W5sqxfOSg@$(o*23U`vxO16QUj*?9OLq;$TAVqHoENWWY;1tkp~J%dh0CT6zxqA$*)mzPgO zOux8<0fX;ONzTwa)KVv$wCt3djzqe5l0d<+&i#%7_UQrc__%5=!a}eosAvF*=nB1Q zM=9t*0Q2R++V130ZFHgCQ@|TX!^x-=4%UlMR&M&=`T)RiAqs z-n%~T(OaIl47utIZ`o*Mo?Q@~JP_RCN#xceAlGgTol;PO%V=^^6v?O9A35*yPw*s$ z+9T3)&z~h*SZ3R2F9)?aeV#;MXVzM%S&wPn+vtx@9x^PP`=pYqbGmf)?$)pJB&IQB zX;TY%U>_LIqM-f*o6&dgx+P8EP-SA!E+0M%#!vXAi;t4q#UJ@E&?jz;rYEe&@SZ62 zWFQ`z_pLq@+piN|b@j||#cb)7d*d8?FFHSMmwtD9mKl7<{m*dde_sE2>@lVs*)sew z|1Ng)4&}4msFBij&rvg@+rrrG&@VRQpW#;h z1-touxffRFPvh5O3&%arMHjB*pR@TQucdcrtCkC|gsW!zSF=X1{TG~9(+5sQARz}H z`X9K3U(FxvjnBXE`^UbxefjsNzql)#{LEJ$%>5Wy`%LNgpa1r8*%Rl#%Wma2g#crcxI$;zV9*hYrn~R zYv`BXVe#gh%V9PE(9gzSTzrcZ{`dwk!n~UY;RMfV9|rQM@zw74~{5b0M9=-uRaSte#Cn7<6!<{t_^eW{Biw}A7Je9?n_s| zr;mq@d;xs)q>(0qlTS(S&Oz7H#Isqj@U-d9B{2W#{)tb4U!RHHE`j`6U+Dv2$#e2& zF<|#|?><;(^T-QJKVJrazx4A<5X4{p%P`hWVdP~2UW*LFhQ<8YfnzCT%@ z@nJJ{()FJyEIaru8Iu{v&7qRa3~v|9Uo5#>oGM)M%{yLF2EM`xmVh^KtWN87-F?HJ`@Own>TRGr-wFS-{d^;r8Je#DwRSC%u!@kjASGY7r>~cuOLHjpIIDLb+i!xolsaoU6Kv^TOKG^Ez zh{V^~f%tK5yjXnxNBUfpNRKAX48Enqm&NH+EVuH}wKPk0`+gJ&5{jQb7Eb|YyxHk* z(&g~`6g6u7PEYJ3!e70gVC)kC|gOm%HYi3saDJGgpl)=}tQ#^jfHw}$c)z@XgDhf@mxA9L-i4iC!P?rSb( z*8SfJaQoz4`ad3abGHUyoD~HWi1EMpZYY2Pc#l2h9$^U_aI>Hg+8{SU-x8q@Mvp3~ z$p}%B@sy~c=cL$fy<}mfuqwv`3hVODSy%8oD<%Yj?TS*$#|O+q`H^zWSXU{VyQ}4O zwd%#{^>r4Y=nW_7PyD?~?DzQS(+B` zuLtZww$}o;J24*vueo%20oW~Vnf>_y{hj_<_|xv%)or_P8O1gw4*t_WP9K?r>Ub&m zDEX-bs0C?+vNLQ_Ea`wGJ$^}pED*Bo zHmJcx?7^5YV9JC!D^{jD#3s!y!y)VIwnO{IO5a)|P4u00zSpnFLqSDRlad#eNO-uE zd86Cl3PUOs0JOWZFJSZp#H*QetzY@L_F znjt%f)7FgGCH%U2%r<$m;hG7%frnO4*8wsa1R<6kk1^6zWfe*_i}3Dv?Bu(drLFHw zT)rDGX}IKrO9Gy95L{yr;9x(w2D!`ps~!(<8jH5t%Q?t84O{gvOg|31K;x-kd(A#@+df8PTyH}M)}}V&bLzH!7GBrg8!~Y~ zUm4AEm+lc>P0o*BUt~O^hKJz7X!Kn*5vr{kflLq1;x>Qgj6ZhW-tN=?&TmiVt=2iL zn5Vr?4W-SV4=LToz+iJf;_TuYdod4_4nhAWC_xV}{rOJ+CMu4>e@*M(jGruHPu0w@ z#f@6uF(`Mnzc{lqkWV;?j0zZD2wbh$Z%8SKBOE{<)q9g_-s8qYhJwth3vLq*D+*RZ zc&z(vFu!dV!yGhrflanAzpZXuIg4<}&c0#pm>XX?~gzx#B;mpQQ4S2YDe zG`gF?7In};|K^PA+y>Vdt|q~&U)BsISZExKP^oEXvM4Gd4DhujQezi#eDm1BIX7sD z=rrENTZLJF8>Ktgwj*4Rp<}hs!EwsErUf&)gAqiG&r#7?m3K_P7uH!r1=_IgydHF| z|G}*+?!Sdy4KgCJ79BB;hjgOtcykGCimmP-m33UY;T51ou!{mDZd=5eUStQkwN>u8 z7k>)~5OrJ%O3Btf(;fJq5NpSjWF!(~5U!fB*@#GTt@3IMAz?GY!C2 zh8>$T2NoXv5u_&uK||tlQF7?iQ*E*_aEqa0bn&3p$U9^sCTTT%Ly+l>G@GPku}|q3 zp{+V&xE7{bEf+{6&M9&Uo+6By70&SoBbL@9rT*m^2WCB zOqXDC<97jJY;U(sI)d7U-$19jp7msVF zG*}bLiB!y#mIosg=95?zlV^1TcYO059wd7OmJSPxALez^VMhRmM!}Ve{9Cwi@hn-T z?;IdNyg2-kXooRZ1Ajc^VNxdr=0qmx$xgSr!R^$;L^;HO_#!E6)3@qTvLVKv#HjP= z;#mkTE6m)|HkkMrTT`sLd>uQP&X;?m^~nrb8ig9JcN70EDW6U9*4YIY_dEh)od|Yu ziHFfPGsM8}bp4LNT!iZlw#mN0r&op5Oyxt&K`t)%YxORixK&FB`7X8wneS1p&_E>A zGb5<-{;GWcmYonF9eA3$R;J43c(cOg*GS?rOn{@+W4OS;BZX7{1`6zrduTn}T~%x}R&| zqnv!!`6Ohx_8A#s;3euY@ji*-P{vd0;|%#Q{P_dI%7L_YPwV=!C5@IG2xsw+zng~5 z7yPvf*H6l+kYZ(jF#xcNb6z_OH+(+qO)qYwH~ihrIJXVDV8L}Vvsm57bh{m*#(p=| zLXPas48EXd(z9Q<#4r#&QR1bjf%{qfzo18RuuR{M9v#v?xUy+_u(~+VHH37euhpeod4r;)JF)*IG4~ z!)u-mUOD+MkPO|)8X8FbFeqV?k4Q!cVNHrP%US3m*vLX`5KhAL8+%0UWF%j^Sg%sA ztOK!uBc3jABvPgA|reCyEiN%S*T*IN>l|hUsP8=_$F7o8o|cam>Cq>k)UFR7*%#(riI%_Fn3 zE~*)KPt5>4AWY+_h6H((de6;p_1|S!@<|qmsC4TG{Q@CaT6EbbSH4sqEt_pgNQ0|u z|DQTn5_Da=3SG7H*4MJ>blfnraCbyZBQzT7x2mlOD{z4>*Z|DTX4ho*@vAdSUikl` zYN(R8P6HNYaP`GaCcd^zlQ^`O(F~CulHfsv>mP<&bad)*!hox%3jbQujAR5>?DIKSgrO0$D3Iy|O3zkXqs&$JQNh=L)aZ0aTzLm9|D-EL7#4{4A&P8r9 zf525A_=?`?ur<=tDNOG>-3OtNH!EkL34plg9D#$Oz}Eq7XJ`m~I_9jNekJ z(FrWm^6E};($4Ns@goXDQZq(2I;l6ScOIU*HlI;pNJuLwX?BU^OXARhe(4(EJ z`Jr@n59Odpwiix-?_yNGI8**pntKTT4TO|gb$-;gdSXWL9EWwLz9RTf^SQM`NoGNi z8}lMEF|yh^xs#RF?<9{eD;O+K>0l)HIxe!rg?&KZw?emeQ}Sx+Ez3x!W&daA3h&4e73<$pE3^KsKkij_aBHsNG1n*Gq>R;!-%qJ{VtC9s_ds>Y0pRu2G5EqH zKC*#S?T>~iN5H?-#FRC2lsfV3b7Y&vt4E(Xtg=d~cQ&+e{@((q5wYA9Aq;Rk2a3AJ zwegu<^yRL5;MulUt3k#285Q8N12c3JgK)uX>5un*`ylAnlQn>olLqq}j(_rKnIiol z+_AJ8S!&H&$4JMIJSkAa4qN&&-2Hn^TVS8_onvgW?SO{}EjLt#oZytUZb=0)aWu^@ z#pb6O5xso-a?uf^0;}^bIU>oKkjy;BIpdIr=&2A+N~EXOWz()%BjN?JpzKhz5sJJ>HL= zw82IIPM-~TUc7h3W!&f$b)Jb=d>~JqiSAiRThB!f?XCxz1l_%IQ-v1?C?Bp7%)F*OJ0z@yqEz+=WM=ei*ZAH zzJ8H5?>a4seuL@4^zBx9ybKd#iB%8H59d?OUdVf!acjRSr8nu%NZwVCDI3byABa}{ zPQ!S+Y2vq;JukGy$P9|PnliBrF4q(SX8Fl=~bez+M6>%^N zr--ioAQ@LNIJQQF%7?3~!WwLH!{hnJev8ks{bjfO@)p$&X2+Pnk@xMuuKlW<2K=iI z1va(s&fBa%rMtzQY#wNlJh-a0uyz8Ld>;uGQt&9jDN#F$jS5LwT>B~WFM>~vq_KIF zgCx|{gW4$Q$ntdbJSoxZa#?O4YSg-_tF@^t$KHOv;^k>PJ0#=O)@T!R@wsZ)(WBd2(?_pSTA) z(X1)I*fLG(L0W#uHXknDKU@fP7bNim(c-|whD1$X!$PA+N9~A&vNMR-GRd)^jI8!> zVm*wCNZMHxhfpm-aqE!j@K|Nj*>G??p_XJ0wW>6qh^-6MBCQ}+LssLF_E(MaIQ#zN zCp!8`UQcjWp9;AOG_GQLG5H6*it`q!0C4yK*&@_`nIi{ftfhK)L0-Zu3rj%J9nb{Z$RX$}AlN zEZh?bdvUewkDm?%TTp*|a92c~`4P^yfx;r-AuY$rxNKkHy@Nws6tN%zFX4IJ<{I|c zybWsnD}*|3lzdgM?aD_8HQ14l8(+{L*A`8QAiHdt-!H$;8A{kzW6HkjXMMuy&_Gly zmRQwbMIOI@Ef(icmiOP7}HWh{Imt{F-}Bqld@1p(6?Czj6}oiC>>Y)V0w9l^ulm*qe5_V$JP-^y3^mg=i!lCkHR#2{U zI4yF)Fr!&|kyg-kt|emK#WC!#Y~3II+aH(#Wf~A{PR2;X;+iOoHY5igH7{d(hlLdj zvn>AJW6`Avt37$y+&*EzigvkfQ_sVvB8f4n-w)oIo1qsNsopN|-=DeHF)bb54gA`n z)J!c*PrObQm6ET?!BgbM_TU7NoICJ1T!$?B!K!=oV@-m><$3*?38lZ9PE3FH9wA$< zm5nandT2PQI`Xvjk%StlRxX4$$=gQs_2K!D3m`5;x<_|jasc-EnHsk}(lKAw*N_aV z(OzjMoI>!K#O#llK6FX-(n@At;ht>2MN|Qj&p$9$e$61`L56%jaWVY5Ef&B+J2X=~aN_{RD5*#L^^rrI2n7#nZ+4S{70oZ8q zEUyv3k{6IEITJV1hQzbvkZ!FUX+Y6~Ap$Ls&WE~E6a18Cv4e!*D+J7-Q`6Gg%~{-N zx_PuGW#TBt+tG{J4UNi+FBA?l5ZnvsvS!)CFkm8UzLCh8h2<_O`w`jYE>ZEjJyUZa z4ydrXcn2xF5Vxl=rg2L=58{AW@tNGs;UPO*lG!lR0o~l*y-$-W>JDW^EFja-+XrXz zjBxQVHPNmePDd3D$UkKQD_Qle_`H3Z#V3>kz1gLNsBL|lvI<~fsMDsVF{-9juYGAh zE?F` zg4+4{k}F=kMU8{J81vWK>#Z>XhZhA$eQHaC=cwMSqorsRfrHVWjz7%yHR3PBJI+4f zukNDRD{sAz9r%kII9E+?o*Q~@9^&SXRf}G`d$jX+vFSc$AYvo<79MzS&eUycJo_lE z^JV)IJNS(5u1%Tp&DlEDMa|XEtH+xiOQvVkP?|?$h^<_`%9IDF$ATryM%( zJxecB8VG^pO;vmglDFN1^Te++Y3}8a7 z*@8&>4}k+er?tf}`iuz`961MVcgY=vXBgFUguhs+$+eYEZn6dL!X}9zXc%NHD$(MK z+P2cS-^=TMjFaI;LZ9x>EsY!7T2){~4TeRM`@4!3Nk%nkehW-L&_$)zGdGPQxuw4s zw*P|1Qw0o0vB0uu&z1HfBZg0>m+%>5?BcEejpPVM#}ZPr>JnW>5$P_-^z5+-76>vf z!wqC%2a4}!t2VYx&g(nZ8mfG8M1OQd>5r}}e=n6GRpKlVoM=hTL99I~yhG^isO=6% z%2Shkgm`L9!-7FdWB)li*u-l=*$4H)zkEN<@{6WFf#{=nzT2BaKvVFPQi3;gj=zf+ z9olK;rwe+dLD(S_*vwr4v5pag0QOeK{^%kr^}2t+V-Z&=KXBjMOrFJ;^zFO*{f*cG z%TI`vmA==`ub6+r49w?pBnMx>cZl?js&JqdbZm6u7+!PO+=3Hk-D`jHhBkMd;@#Hl zF8+=g{D2(d7Ntr>MvIvL`Vo!!>=)6>(KIHsWo&ikq@7K~44&+u;-l&f~J6DUdak%sYTCMT;EdXb0f@nWcKF${Xn-^*6rooHlM$oQM^vy-_(`<+Tar%46?H zlV)w|W6V-uwEqhaCRC&)vY2U5fuCyQmTUdW+h|-W$^}MROzhQdq0vh12+2iS%ynYa_zEBHVHF0sPvRt`xc~wO|nV8-A)sl zE#SJCinFNVMQo#`06@eKR?d=$p#oInaiEdgH=rw?Aq1HC+Qpj$*v8slZ>>o|vPOgz zp{XW8crRlh76H_;ITY9Z_H2u)Sc@I5g@s*u#RNn|OtHw9?3!Td9MPArt!i)gQVVJ( zv_Q$O_>K2o$b$r0g&?G)b(5#9>WuwPJ4VykOp1XxYAX<*c6stc|{rYNNW6zCp=2N{^ zz1E3`3Z*^g3H7Q!H~p1Xs%A{hZ)KowO0}jFQq+^_dRgg0g1;D@i!RX4Z9_vS?9PwB z-uDtWe`H1{5nO!P_-MS^2$3&~e7!!xmhP!r~vLVpW~TjJ!I0fvLLYyo-IaST8q%YIA!0!PWii0p!L> z+t~Wm1JV)Tk52QwT8@sewl*yu1=_r0xuZa~rPgn%G*jXVEzG)2+Nx!T^w9P9&j$E& zn-#_=|BOj&bQ{RE-vs}xa$yJv&d<|3*7<}=$gU{#bn9YL5SYkmXXT7PtgA>on9@k~ zkpI6=*HtX0J!v!?8wSdebu&BuPRjt!8WhizPEV>t`1;)R3d6(nxK&rGA#2{y6!kY> zky;CoIe)N9mO0UVC1oFxr+}ZaZfibThaw%ZUY3mw;aM+oD1p$o3R$vnJ3{ zYcv@o!1(LZF#B~a_@x;L(plHvH3c{|d6G@6gWLJEqUyJQ`eo@E69nndIJz>qTP?#< z8lAD@#xh>N;oqt)G=Dnx*)G?i$zmn7_QTJauAeKDOCG{MJ)61DKjT@Jxs^R*=I5w4 z8?cbszzu?#Z?abv{|d~tyjI7m`NyUSXxx7HPvTPE)a{$IBSb-n$-*Nx6k#I0o-*|8OB!?6JOo%c6+CC>Ib6e|~(Rbjt-hDZlX z^~0`RGV7iS@*1O&(4h!paRhnZ=D~=_HrK2HcJ&&RoO~-~Fw=683l&c=T|>59o!(5t zuA>mbA8tBy@G9VT^Zo}`-i_<{^CazWq4=13gc#=StK?%o{0T04an@rq#xBd%VY5in7@Lt|UiBmT$(o0|x1{MkKapZ$%c@B* z$N?Dhb+BsTX&G1Z)|5CgGc56RB*NAdO%rBL3@S!~gqjO~FI&UWB%1~eZV4(UL;P@Q zv`F)_P=|ln#)s_@7}7?OmP<@+j+7!=L=Q8Fp3Ld$GuxYtU!(mrXZ`_)QS;#POKQ$3 zx6jNlN@U4U+Qx0@yW zFRvyNzuEEK9WkW+l+W9cpqY4e@b{IL0yDOmNms)K5{s;cHyXVgXYf%=Oy zyfhxujM7vzp9N8Yynw1eP2rYsZv-A`jP%lS(YivuqL3&TR4CdM?SoE0muc7Oc<4Og z*6Et)`sgO=R_gB2z0ITb4qy~9W|%(AB32t)gR{lSaB_Wt{#}K>zG!`i0oGu`aKdoK z{oGq%yyBOe+*B#1%NpNo)app*>AA_FWKi%>geNmFB|7{Ca>aR?9$|VzXWrCR(A3z_89Rv zU4BwITY1{7xTSupnWwgwwYS7u>b>Os(EA^K*=Lhaw2#ndm(PUH1)n!W4aS;CCUS^% z#Bt(f-#O9*=`87)p9=TW|5reNU};bhc_9QHf)5D};e^zMjD?&G`5#4*H>P+~wowWw zos|8Q>y%HSh){=6N+>t9IgA>v6}~OvpQjkPGfLCz5ygqR9(^HZb4))KOLL>$i+#V% zWn1dD_Bfk3T3l1yskrxaE-z1jDgeGWvD%I)z!@)r9ch7}Ru70V{<|^&b=G%n64MY5 z=4E1x=<_^CM7Tn@W8bJXku7mn2Ue@yyNl5E7FbffK6SrtD$9cw!?2UmV^#ta7{Tw%O8Oo8r>0AE5`u^xLUnxq3r zs3Qfle?B1r8uY5V?#y)ku28EPSCKVXV1osgb-{=X-@5}7z`SOJZz95>?YCk>4q;$+ z9FYL@VF0l^1|6N3gmhrLkZM$r!#G3{4Z)mk9Mfe<)nq|dA=;S57(yTm$+Qh;%-YhF z488+TO7zre!slOzcVf1)IjqF2RinSo4^$VqUDIkh82rFc-2Mdft)_*N)|L11&F}Hw zJps?JQYC!a4Y?>tXWV@^SQ`8mzRHz4GCYU&Dg_1)$u-p&%IEpFMYuTha6P`1B^$ZY z_!NvnawfFkwR_5Zti1;)Cz-g3QOcgm85RMWpNF{4?+LFWx%<^?)u2z(vPbu)ezP0A zOT%b%U}JnjaF!Rq!4spHJ*o*{f*B^5+#a$Bzc84^!0#-G$h$-I#5ByoWtfIZ?z{_3 z%gBP1^NcI!qNq=igq=5J?jeMm1Ex7Dj3G)+q+zF?0~1@j?kc$@e4 zN6azBJ!PN==FlLq$9Rl6bfftjJXZr}rj8xc_}VbvTO)?93Fn~GX*ey9<&Bh9RBM{d zjfLk23%!1{Wzzl3>(uTCTHy~C22B#%Am~gU&vWRAZk@At5~lsiB7|VIQn8%9(9#K+ zNZ{+H8V}iQar^b&ozEobFo@pWWj534!BiyHA5WLssv96gXx29e2l_(;1L<4|v}XrG zCDTG`4BYIxmY(Fc4 z#XE|wR2;84u2y7!)E=61vv2FNhr!9+LH|&;ZRs5p(y9YruDF1Nx@}syj)ZO4ZNx5d zzt3mw?@p|FU9|>Z!EWb!Vws(Sp&{1#z%a(PtB7%*;?cqZPb8NFRs8H~_s~6X-tX;| z4|}w1FQ1Rd!3OryegeBR3cxi>K=lLy1o$9~3fUAOjAO@%4uT-XVn~Myvcf#I< zVA3th>5wpc>D!mKWX=_;^ju5(?bS-8o-Sz~wK41z{ZWTrukRi0ZVg8=C&OI3{8&$R z`j*q-UP~**vGw)e$!!VAh(dvqBu;HP z+pdX3oKG)W|8N%mK;Dqk4}zx}Tg-SV=x4m-qx2U(8Juglzj~$iv#HlO4u!87kC>n@ zS}!JXoQUz{&T^W;1{+Y=VDmM-1H%v`BccCJ?NNX=1OFZcCC2y~*XK)a4hU-( zWK%{TfKE$(&2LK^ufSSPhJtY1;KsT9vYgHt)Vp4EkylxdMW?wk;R$HDho7A}1N!|wrqv4W6vO3Yh8OF@MMG@L z8tI6xI5ItCAYQ_vps=_7Zn7jeeiFMuV73_1_!(O z_9btIag)YTkPS#Xm@Hbp{K%w2>1IUgD4fmmycn{182Fw?fQyW~DiR!C8rgD`q%Y#r z{li`g^OAX$DPuF`(O#O%7)vwmOp&HcmE+p)a89U~#FP&p7oy8ZtmMFnA|Gjv^=OJ9 z2nx7YJ1EjFSXa82RDxEyeCA8KpiiCC2UKGnl|wWG7khA<<=_%Fz zpCP#ej2ji<Zu#Hn)Q;+#o{-vw*bjj{d9T z*95ifAiJ!x%KH4gq2B?0;op3G7zb@F2u)xcVjO*q1e=z}=N4eGNOEJ%_&PLB({;Ya zX|#;13HrQ=Bcscykv=Cw&Dt@uxusbtMH6{dq5)`aseLbvtdeD~<95W9^_(->1c*l> zby{M{tC<^v{v2o$)N-xX46N#T^Vc>%rmOPcbj^N>$AynFh;YyhPs>BlN%|;&iDfmsJjrfvO?8&*!=y&)KF(7i0(zw6POsw(CQ`1VGgS-iM*9NT|v28;H6 zfpv>pGFC&-fygAmF=D{gCWt1GQq^B<915@X|I7E-LRT&nWn?gx{d)5%q^dSs4tVe1o9UKNc| zMR}7=Q@+o+@l`mR6=3<*CO!I-FvDU7)>SNj7lKkG4g3x&=i)|!lteHBVG+hH)PH{J ztaoSEU89MiZNtoRzDdRBwQ8;#Zo9Fz zM)(`?_`8uKQqjOH%|r8h?n(K!$r>?K?i%~A8RQfAcEILVO`^osp;}_ndc)=*d4CzX zrF~1tQ^ZX^w&=nnaGaA}JyB-hXQ#s9B5ZADhuPjd217xG*2YBxX=0~bko2jU6_lIi zja!Iy|LB-L^|)mB$*Rlv0sBljOq0%&nP?ykJV+XF<@4P;Ajeb&M}Fo-!!>rWV4;8o zTW0%zB`=^&YwZPqnL|vy>M7Wf%B!hBS8E*jDd3-hrCqFRrrkaIzb88+I)?i$@a15p zMx&k2*>TBK@nO{w69)q1SrRwOG7>jmUwDZelpp{(lT^DL5<#^SCgF5+qBD&5EC{IY z%6br{(OAxg_Z(!0B#Rx`eTc|{V}e9*NEJDo*h}1!j3!A{LRMX}(TOsPcwfox80B7> z=+A2C!l2(5iwz~yaa-%_Mloh*-~6|(^ZZ(2v#ee<+W`?AKK*-K_aYDA&$;6N(Hv z=LZwUd~jIs8iHNc36M@F6=?T1;LXn*A#X~>{5B#MJ`ANSl8A+y$S^fpyEv4k;%XJ` z*GmDiiKQZ82t8ZpfR{~SS7j94BXSW>3F+oSck(DPG_prMW2^DRKIcps7lEjfPyX%O$3yTc0q70DF1s(nLdCz9k; zd0GCf76d*nRK93U?Z(6M;7 zx91UF%GyzkDYOZXH98ErZ}9dOVzH9u9lK9oOuk55o>Q3uC{?!KZDym50}kyI0P-s&`XD2x4{TQ9JBT^*MF#VcOz zv4$=_*2O|2DXS#hiop#@B+nibw7{PSLbKDa()jK`4PON|KlC%<#<`xSid$U2|1_OE zN&?$FlO{(GJbJj7-SlKU)Aof62S>x5M9pDWcKtZkDmYl><*3A!BtjF4(x76Hm+DDU zZSwx{5kwKM05w3$zjG4^n$XU2pTbct{gi#nF<8wbHS8 z9{kdE&-{JO4-)}7F5xlcSdw{SHz46mO^E+6gAl@XP181zOK4!o4OJ3(-Y|4kR%A0m zXxm71vp(&M%vPz@leAx&R6~R;Lj!AVwskoADboNOnF?FyB?ugdH?11-5|n3I2*tf~ zp?qJ2M>BQ0#_Vhrwzte7mG2uHMj>T(2Gtk}yIZOJxN;(?X}7cqTaxefYOVfcpn7I( z;UIdB@7-%gLsm?+q%$pLza9z)R{XY38JaI&tXY?vZFuXBPPfhxt(JOiGk+pK%Bv$T zR05q#Wh+S$^-QF1H|p7O0~#Gza&oa_U!I}-T>3w%I=VEQ3M6ct5QCK2)cat!l-6-qT_f5<2k<0{RvWIDHXI+zxU zS|bV9hR8*dxCg2Fl9SHdSe6PhB>SN$;tk6v@ ztu>OQOj_l}v|^HvvPK=q-TN<7xOB}_%STTn=lPZ%yE8E!9$t*6U1z0X%Kt0Ax!0xz zaV3YwhRt!#4>_lbrdH{cwGgqQigB|zy_Nypc>jdT{k#`DgMR8OEu^HeZLLo-V`!HR z=Sh@=e_{8iXe5gunsP{uxp0d-9~t8VV_Z03KpDL1uL#;i{x03y@#lQ-){vN#r^vN# zrN=|~_WN}&g1nz|p_G^wFuI}n@ow5Lmt$!^=32NCMXB;#aZ{dk64WS&K_;RQ?OKTj z!cvE0ORT7?t%pM;mgm~MY9P36Nix^kt#gL&o4|tD>gmc;`7VsxZ`nF?#WpV&qqv_( z?YI7%tE9$%IPGzaca9wFiwq+1mLo8JaxdJryp&=FmW{vEqa=FFKROHhnZftOkizxs z;ApE^;}fItF1b8GB$uYEbecRl@bX_8{G#LAznyv+;I>rsKNJO|Dr%*<;)uvL)Nf&yQz(4^x!qw0<%YR z!5WCIo>N*Xf3aVU`_iF5v@D*2cj(K_7bvN5i%)6aafxI1BE7lOo~CdFkyRgK)2ZT@ zB?c#0N#Q7jBS>C!``xVH&pA9a!=${6D9&u7^;leRy;wzB(v#THUD|OADO%TYm`{Br z2AG98I1e*1>tJ-!Bzv1K*X{Or(K}r|h+t??c2BV#H<;3HiF~^&LtqO5jkw%0qcWJ+ z>UCL`69nd)jWQD&9~MU;T1iJe?eBeaVu=<&Qx4xj4yVS>?MUVI@U<^oNI9=d`!~!1 zb7$P>iR3%>0+`M&jyCOP4$ME{Tl7S;T1+NaX`E0#-dO@I7bg08e`%C?!^P-ay~Wdh zO9idivqNqAz{nq60}mi0sN+Ex7%jXe}40~TS2rzG{e$_371~qM|#}0 z3s2_X`HI@LHH>|y;>aaE zDP?Utj%^0r?s{*mwkZm$edOuoJJG2nS4cm8+?3N4IG45~V*s1xni9ZBea>Vp}B_? zwaY6a%c#v%W=tstQi>ZJ2_d!Sl&;b!9(ZGwo;0_n8nu>eGoy5ts;dm#g9PYIac8|^ zWviVMUC2rI&fn#m#p2qPH~Y^%nxz-9zaKudZ;HU+-=Akup{@mBP2YMG9+;URd?K7q zQv23AL94oEpUBK8$^tHfaH87o5E+vMoeCTL_@)QOD<7GY3t8;(2F2^$+g_8cN-Zsi zE+HZ5^&6*nL}aYWY-HI$>P@zD3!1i6#EaDTJPjc(*((a%gfIVvkWO&&-mFgHWjaiK zQZ}VtWRC!0#iWcf7{B zLMbuM^FTjdooen^S8L$sW2=}PRISNK#3V}S$C?Qxsf_Ra{q0yQQb)sRoQ*LU?W&6! z@{Gn%X6x%oLn?nr;#&1xdaJ++nxR*AKxc?I7}>^9>cUU5{Qd#p|Dr46hmH)XO|vAJ zS6heYd-E75vgV^l%?-Mu`1z$+2YuU6vX|e~c^(1tA>KeJR3;R7ezD`df_rc8F89wy z=BSkBEteZFzDKZ9ZoOfGc2dw#GcIz&kf2Lr|Nh&B{AyKy#j-0>;%KtS@ z#tM{e#2{$fpT^>~ANvJ@eqhRc{f~Jy0kI0GlV|ePi!g6Bu6%3*T`!&Zt{EU|EL@-q zI$C-`>f?gzV5#P4oVnCm317fu-bp%13^uTcTS&{HN>NfwuXPy&t-8^at7F6NVCJ?N zH}q7ptWZ2#TU}9L<1(MXeK}k z2Qp&u9Cx#;9c|jzZP#&MsxL`0Iq8qN3L>-6o74Q|WbKshp6?S11{kPDJmUQA4xM!~ zOELt1A$pzKmN~^br>skFwM|=-xDLzA#*{cP4$wh?-9rPM7>96g(W2X;XWL4eL*d^PgA+|wiAAof3PTT|B=&gUW!i%K~V7SwDFpy zW&ykm<{)4E+@CjAd|^1ke^x8&eXXM=5cn?#)$Q(ygM*f9rJl%)aqoYBPC&o@Qu?;`$mx;=bQ@UQ!*q?8Kl#Q3GPRbi=rD36+2y)FUYAc_(lE0jRo(G3($HB-k)HU%~ z6$8iUY~L7X+$bsL!BQ(j&MEaFX|;uoH+py2<2mwAZ6#m$);+&xruY~Cx7X@n9FwSX zYo;)#&ctuWr235(-K*0xZm!>e(x4VX`Ua?j5|ZoD^o_74AAkm$u8Mgf-hUi95JUwB zH|dapZJ|QgE{cpZ>`~pe>MuN8-Cn^@hsG@?J8%Vu4PWSCewVp4;j=Xh0b^EInCIPNSbSoVx{Y=#_vfzS*&Ivy`8%O< zdh2x}C}n}o&jB-|4Q860kY9l^{sT{O#uZrcXD^0Oo6jqE+H+57v15Tg-m zt?e&T#JprMhdoB9dy2-Q8_p(=SuUDjBkv#G@%{ATnP*}(rEg3gDGK;i=VpuEUdr;g zvxVL8O2UR$s)ar!xqKVf{_?=vz`@|K=KDuXe^*yHY`UWLzzr`Ykb8Lz*N#rsC?j^8Ct=%=~y{EM_@1 zFgj$ftL^i>s%ky?|Fs@Hi0_ZTI93jU>jrQ# z56BO|-4V6s4ZyFvdLPpPq)N2saNr>0;BGv&f27+s!kzJz?V?hh04HcT;mlbsdZ>=% z#$<`sZm<3OoBPuxS3}iaStdhUf@2p z3t<2O0z3#1Gq#IPoFt>ALe8-7r9VA7x%d8%G1%RHDSnyQ4q3f z8ykF|)EbPg{&jwdbTXP*G}v`#*C(f1Mim|G|4e8wBT;MPpzEy|Fh*u&Wnd z=s=K5t6!IF(4=WHAal>LA#(8)kLe8X++iw7>Z}C>hc?DZxnv@gY)YyJX(jzYV?_Z&Sa>VGcVE}BI8zVa^6}8$5Xk%*`Fr51O z9>IZQFVK!5yKCO1)^*RjHM)OS$7qM+9Wge6H$rePkPhXwz!qb!>Hf}6_vzr14fjp` zfGwX2^k&mX`a`%R=-~@GroWy%P`fqqNL?-1@h-y|KP&S$SNgMdA=06=3>+%HpI}C0$(_+-i;f>a1!C za8T{RbOi}49RYR+sMybWWL-DZdOv?X33B2S_lJa&2CLEFG`no_i9fK* z6wq=RgfR0PE5-w%w!e4JoxP$2T-R#EZ2+G$`o` z8bQjJ;8pGhX2U-~tyE-Rb571brvcun>m!;w6zHzfd-T8At@c}_KK!24He*Z8vG7*# zzZn!2{rxox4x8&=?l?9CW~^2}kbR9u-5MtRSzj524HL) z=fY{nO((Z+JDqQM58i&0Yg^|G#y9uWx18g8I_#Db&x5vO>xR`f5ynZGkvK^+FpGe? zN;%_A0&AbKMhR<29BxWtr^EqgTnlk`5yMG(xn+vdIZeW$RN9J#JA)75ySKrP2nwh| z1V!l3v-GmG@D`O`Pd9pPwkyaAfX|}0(Qg1H6^f~2cZ1_C9-!zYAbKI2{w2iIakkn?BA$O?|$)uF5p&NhAa+ z-`bK3x_zJ(rZ>~jI|6@tsNJ)6E!N>jYEdv2Q&2?9SxYCx^DWDx5a}ozQXjXALGBmG%S^k>w4`Ohb@EF>haIk1kkm8o zv+7zq{(fBmIHaAio$UehoXCmf+4+rf5{HYNXx!tIWpA7UNgibNP18CGLkC=n5F~XL z$W81MFC4cg!5gh$u53D0hNVCthP?-JuPdWL&LAA)^fyJ2mqr?%jD(9B*#G9m=TRQpm9Mn6EL>X zOrfPjSbxH7)VM~yb6nI1zufX}2%HZsuBoDnamH(!A^sE?vj926b== zUd}}CM;wTY$UzwX|G{jKmo9yncxgVrN;@lY2s8EL5hHbd`q)iel#phImM4A_eBL~! zM*wM{_Roo(_mBqUT9LJt3aq3}J3o|DgJf?}sRW3^Hg!2AQmIkhOm2qBPIyE{-4O zeKY0}@jxj|!r;6QX>3V0l4v5s7HjSxquXyp`o{-bPi9}yJ{8g)bKar4NA2vH$}QHbLXSQsu5|hNEGFOlMNmuh@z%)p}wtN-+zYTNwPQIBENFmW1)3w^(GV z&OlA;m}Yr7RBqT~Tu|2<iR(Jwo$_(W847J>QcmktcxZTMV=q% zos$h&AJ(Z1nM?cco+Fk5vz}xBXz$Q(aU80L`RqzJ%;?~i?T=Kz;Sfy6uzLvmZvNR| z(;HOF(M9kVOxam)yJL`x{h|`zVB z84EBnOhlu6=w0JsOp>A)O6y!mSaaO=Q)!rH8|z5N#esD2C`;5nqBbA_lW`QoxZ@!4 z!rVHn61jw!F^bA%QW6^P(#Ve}rb5MAm(42YpL;)u2d)9wX@ zmP7%AL%&_w`gVs}W?p=*eZaygE+vmT<(O%7?O(dAkqH5<7#Gx_fJH-4q>=J7wcg9R zB{*6`@2!fC5gjwU*1jwvZ_wAD9(?rYd|qcv9k z2XloX+E&v4ywbHQbI)mJh=pA6f)#-_qq2Yb9qbC*Fp&EK_$BVefPPj(YF5NeifT93M2}al^*@`9?VWnN z)$VDP0H%(n@Xa?<7C#3&rqX8hfKneC#+IbRvaLp~Evi~SWxKX@Z^)Kb{_rfw*(*aL z7BU{3&+5YoZ+dN#tlmhGB-WmD*Nqmm5v{d88D*TIBu*3OYprBbP_e{JOan|yG&7B& zVl24ij4&l!#yQ}4JrO=*yl&`znlyuED6Q2D;T8_^`bjasu9z7Mt}IS8i?P>bFjO$G zQYK{-6$zX4kdu;r#;7hR))u{l7!8$*UUG4CgEYwnCaH|8@GkztRXFJ`H$gEMXsn%b znc&%{!Ezog}In^4%~mlM;xZK)_xENDSSb6xBd*Y~1HY?Ft5Lg*`s?sbkDl;j z7q^W26`8T9SY13QA~zm$GxHQwBJm_e6~8s|UeGR6xg4{H0v?5+qdHXDkJz(n zN7VN>%FwS>8@@Df4Xo*s?3y$qUWdgEI^L&} zG-AxQ$_dYFcU^xvAff6N^ohg2&Ns}3Q>p$#$%m#8$CV9E(L znq*B)KQdbl6%0=-Qnp0nKYWjEjybRSseL4hvauhbsBCus7XwOq|mBgwZ_Hw8VtkE1Z8VLqUCHHZE{GL6Ve!P*MO zl=s~}({@tFB%a7a@>L(440th*ew^q}p~v0`#GAaQX5Z1iK~|)J9)-A3>`*GAn3R@fr5<)9V^kKJ`l%jdrQ7lyEiy+u5OH5v zk0sT7I1q_xh1znSH<6@R42<|nx7%@BqzeM=dPrJPNa>YtVq1tdDEvB0W8ABup`{61LZYVtBBZjf4=vK>-IYWq%vaIh5E9 zuZN+OBqqVbRa*n!aT3My>>Mr=eqs8jonLNEoU~mFUBsRgSXC}EhEp+G{ya~~;i?6? zou+0Rv!aqBSYd@7R@jT?4O2NdZy=qEih-5O)a)pmX#mIFgx$ucz0UuERb%HA<4ARO zB8Ajj&K>(^Lxg%ysy8}att7JUp)>-);8kjdLFnQO-3ru`@HY|i=l;8@VrITgf5-%% zQT?HN>nz6jMW`vQOY)_`8>(8q^QxwSgGYf+cKKZ@wt~(}FIc$Twl6`cjok6%>&!dL zq6UWQGx2l@aNdOZc6{@NDh^K=)4{)pvnLkvyA&M|J6tygmIbfHWKKUv(d0?8o7tq~Ac5Q)CmrHZ$|BI|jt$SWK@h~h z$})rs&?F$&gMx%}a1Q3<9GoLd-e5Z7Gi*h9$1FIjX;}1&vL8B{X#|05Bjk95PF4YY z7yC2;BYB$+TT32~>41H0n$Uny9hrtgal5;#OIBBv8?kUV_QZd~u$XygAJ%1g$3HTfF0mlgYn(&M zlY;ZBnl#;wJ==pZZ!@+nvut?@_wkXfxrGHrYSFVxz;f|0T*u|H4XO127ZvKKt?R|h zsR}Vz3F2^Tfbl3EE>mAwZ?qDe?K-;^$B|Va%u7T&YPUOCea1UR(j>Z$h6L23DWCE7 ztY*u3s$|BXaRUY3C&?W}1%HcrSwL-3W(5JY0j^iXJNgx81bj((+%cUc`cF4VSK?3a*ei3GJ+7E#1 zmpf-eFrj zwbv(q9CQI}Q3nZ|x)pFMFpb^r8CxS%mEXNar8w|?E&HqBnQ702VL7HMvgFEmZAhPL z%o8sk);LTj4yRL*z!Vd^RV(ufO~|T@V{<%6L3QF2wQnTA6jhAER8-Mk;@)?%IB;we z;xfV{aFf)98Ok8OcTFc!Q(*Qwlf8`bIdL!M6oysLwy1OHP8I(qb>=_U|5 z+1NRG``dAB1G%GjP4&EoMCuQ&@AH~CE}6#Kw{1=4*nKC-`B&@hEt}SQC`2*-r)1+u zWFap~MSz+^ea{8KVS>{MY2uk~Q!tSlHy;CVwl;=ExB^Yhh~p-MmZmj}Y*>FUl#o@( z&o1W2MTr~K$Jp5*OHn?R&>3urxVljqnapaoE_SySH97AI%Q!w9Nk8=GSmm;&12H^O z%A~Q|l%@w4dTb#D9WfN3BVds%5;cqCjKI8Qb=|0{EfGG#Fu};a5>+OseYIlObX#xv z{`S!Kl60-8mceiEAz_#}mik)Jjg<9$M6N-&JcTor1?y|$KdmCQN`BLJTm@!;Ckdk% zyj}f%M9@G`vCa0>#>;QxWm(CZz!^l$xO*7NJo7&F1~D$WWJ1vtLXgL(6@xS+l#+bv zFa!|@`x=%n2qJq@9tKe7s|X<-t;-=_CgXI71vI5fX(xl7t~xq-hB~VJkUW;`dF@mq z>h!aLF0?M}m}3L{v{|+j&ZCck*FV>^?^CtO70WA_Ee-rzTmEsbO^S!SH<-1HWm{yu z4XA7*Lgy{>9S17s;9$@MTe@Si3c{+#b!FT|R7WJu6vq$*JbWzMMq?v{p|33Ivun&d z2>=MML)6WFUb-D|QUe{dS%fu>%)NkNDl}D##Ix&7mWh-e13(rRdEcA*7NtCJSO7D@ z8E<3D+ikv(fL7A^O+LHM0)vZ9?a7VyDio?-yv;+Zhpitmbm6zb`AG3BqU{^mQmqiq z%1`cxFE?r8>j^R1f=ZJcjZK1U!5Jz`=G}6gM%XhRsVPU*l0@4Dr(ZX*z`2yyQox0F zS|{qKIvf*M{tP-;M!Bq0v8}qW1wD}1v%VR>>2|zPdyBJOsxydX{Vq- zjxwrEfipb}aNq(97Z|X4$J@{{Yv5VIqO#M2rl!+m?y94#o0u=1|!|EhBi1^ZMK!L(fe;jfM2v;kR(yYEp|J4 zB$_$%Xh9zB$RY12CnS4(y66SRWEupf1w$6yfWtKe!?q%yl?iE+t>3s7`%pgP4a5^3 zUoi1Tx92JgV=>cD+-tSj;lmY1YjQrj-c{kke>@ot7aNAFvJ0J;rf9I2=5z_iNDca? zUR!79(;JMvcMsFx_i+uxD#T#@=lx{}BWD6|!VNf!$^&d6@}LCAiaft@E&f77G(?Va zvnUdxTk&&B2}c;KaQ~}>&2B38Fnkz{Y{zU~@x*G7*bOxwaJ`1Ye?4LlK_@0-Ji5^S zA>uttvPi>{4$~+kP}U9N7(GR9^;pgIf+zxk(50lEcIAjMs&K|I-Oj6Z45KrQ4{raM z?hiZl+TlUBb71i7Zl@^wlznFaGn-!md8uZS_4@be>9YnqY|m8G%laa~mi(x-v&bU` zb2|lt@w1;gGqepd$Bc-B|J_Z`)Ad@Uy4QqmlVx@{GlQ9YQxZ(A`!BCuCD8KT^S2tL zSQ+6Y#KWNpFggNG#c&nv=bm;`g#DZ*9x;-~bSzAscG7qg%25o^1qO$OG^xPQwz%i! z1=a0i9Zm}YKIk*$)bArX6P}Nzbtevcsy$j-LZM|YK<2R4NmIoT)`bBDobc?@H90*V zPvolhS%*$-@j}&PXbq*p;f@MEA3>FeBJ+>(U^E+}ppV@K$(a^C?q-bd1-rje(HQs@ zmzB7NfZo#sE+c{H%ABL2mx)!ghx~5w;f^fTu`edWd`WeP|VHy!KGl2_za}}Q7 zujwy3%-(aHMfV>_^y{S$V_+$0L=xF8ANK#>*H&c9UyjF;3u!z4wav7y;pWu0b3)Q1 zwDU}){82xbcI^}RX3!Q+v?`qbOH*(z9P{DP9`_TgMv04YmL^dg1%XdU;JQX-Nsglo z`^y-E$mLClvF=RfC_+%>c~KTx5lUH_^!kXS(x1m%3iFd$IYP<}d%j0`#!kU}^TkWj*>cU_({#oHguY|%0u8iq3r(z5*| zCH;vMb`(=G2hddvG+fmO{`U^8LesA8><+dDzN9hFJtlbe-HL)}nE%0$o|N?BChKiI zw6vt2NgWAnoy|hUuNQ?F@+T|Wez|SN*k(&T9iqUsVeVmhki1R7V;*Acj%#L!4fL!w z>*5(-rdg37u!E2X5IN>J4W`1h2(2u@V-~98{-$I{19NXC{H=ImijYTeUf3t!3J1dD zXTeIW!mM*fz)^XC9PJ4W4%Y(Vjc7!|6I+O3rTYjIg8e{|9X1k8S6Fi$l4jYVn1Pg9 zCU`0ggQ1X1Vd&`O4|0XX4-dAiWamWDOO%uZj!P`%GuL#l#GEQ9wT0j7bWy60rmBsn zp6Ph@&G~vJsUl zE{W$Ub49~$kJs;}SoS6OM3SPNV;>+JwbZ)b$o(Z^%Zbb3#m}67i75?8u5*oH9I` zES4MxFY{eK{V3QQu+*M`Y({JpsnRI6@N89% zNbI)S=r&P8G~0)fp9W!d``CiKLER^c&G+BmW#M(ysb=RlJJz_;gLA#Uy#rtI&vkn; zu@qu6p{#xO=Rn1;ErieNtk^V;+l9jDJs}qy3KP3ut<#n{E?UJZ0k*w^+_`^#w^JLs z`Aq(dJ_&O7$@q*?wGvW_#3&JR zR<`tzU@WzidlZn+jEEJp{pt`&vRZC)#+6_&$%L7JR(To8kbNI1^Q2J`Gmk*sIi<%?;hIOQ@>7dJ!>zy_oW{q~5b6`E zQ?dzCo#cdcC@#)k&R*9Pxc^FZ!!=U(%-ialCOUSmvO?4+7C73*msu8cA*8p|ZHFS) z^L-b!EIHw`0^Kf}I>h&oX>=_#T8a=wv=JjZ)^oeP#C(+FH5FYAZ`~GewWOhqGZsa0 zN>Fpdi-KFU)z0rd(%A*!+VTxPd7}~vZa7%cqb!bb7H@CR!5P`-1G|3y^J%a1!qX(rxQf~mHR#z=tej(cJaTyJsf&iC&0o}d!s)JoN z%j|gL* z(6T4km#*rO!i>Xz5Yk@QHRvQ%~fF3WW zI%`~fRzkJU36B4XTgLFZ7%D$rC&oFKBoM>P#fks=4Xw&CHF^C=C&$^QPo2ND-)c$H zvKVo;KI##=d(#7l*3*@pI%{yw+ zv9l|N)6rU1?FNH2t}TtLA+|Rf1UUCnbbvU8V^A~JazKfmwATIYBZu;e&F;~4q|GeAevmA zEKlXZThT%O`k6zTn(b~;d#V})iY4A9fft0sSd^P|K(UGHf9_2;LxS6ZiW$dbQFK}Z z!zvqqu5mIG(ic)-o4}H}vjk&^Ma!_ax_flA*%;N!NRmFfN{&OOjm9TH^oNnoD#4zW z#F`op+=Kyr%1CNxyhL`ooAg;4B}2fown~FPebf8FJ|#pHm0^h0DnHBx_6F_AwYk*T z7D{WuFxMH1`~9Qd2Hy@EzeV|^SmyJ$3I|O$hr6WfcD84vo+DTzR3~xj3RUGqLu|tC zfWTB2wUdu*z3LIZh=K~wylmUD>>Bv%p-{9b4XJ4ZgfmqSY@!P4FWSwZ-vQCepUhkN z*!Id0Q%qjFgx476?9EqTpKJa{hO3^6Cm>c&i*3`Kj6H6Dyd1?0QH) zFQQ63FUvigW$8xPD>AU8W}HOjde8p2tG$^7At)p^y&Pl4yc)S?lC@0l1x(>ts$;u85mIQ>>#MPg9F3FYMzh12ARoM1$?T~YdyJ8GgDiiu z-ar1-ME#2?A3MCSp8V%G-C(y#vgvAsv=ST9PD|c$qZeKU=+rrGkAAdLyr&9TKYgd8 zx=Lbn0^hH+(dw1!_URiu<#SH*K4E>I9zYK{B#Xi^ZL<{QL!vO-<0D$XWmc>M)rryp zOtO_e=AiZf^h0NhiQz!iF-#3yfM>7>m*Rrea)-#ai0@&KR1#B8pyEhVhd!9ILnmVg zwD%+gS~j$8OlUM{uyHUL2BsKd8%K>yVhmw;;Ebzh(u{>r#1MvnKsOj`LT7!y`cXMy zlz{(gykGkX3k%1AHU2LtZCq6QN$-qdzkwM^mAAN>Inn@yxio*9xjzyMQMLnK5WtZ= zVR*rTY#3Iq`#`j8wT`(X-&NeUT~>5%I7Wr$;1-(RJQeP4M#u$qRENx+g)|x5> z#@dK5Z=k%78HQktQc@vf499KuyeN?r!?G03ay-itjwFdwo*;M*CpelUof%1zyd;Z) zz>owsF97Xe;@Xa#ob|oc2eYZ_L1< zK}P&Ofwev>DQ@=Sm==m%Q{XjXqB>7KBHa7``aq;Oc^%x#2>S)LChea_=28$-t?IUp zu0*=}G%UK9hI3+Oz@k$(7bi(ukKcr#Ih4lnB^GK9EJ_YGFEX39NZvnBKKT6GLcUeB z8N=#Gr6!9TE5P1;++Q}zc);Vv@jFjJ%*wgEBA%Yp@?-?f+REs=sJ z0kshwZ(lh+A0HMT3#F=>YeR94mg>5fRsRo5y%_dow}{@b5$VfQ8Wk&2k#s*zj!`(x%sl2 zuA(2xC4Z8Eh?AXVD0kuKA!u$@p0Bdda)GE`A7rlgH6{14HZAWK-yT?M;dK6e;Y`en zu5Y~@4|nTb;X-Y_KRw><$c;a_o{Gww;hTdwNj%*!+qXe)R&n%=dlXd|90+ydYB(W- zR*QCSO1Aw;y!J^}9`%c@bDN`H;}BJKluZOvbB;S?F+OH?sVT8#LO$>hE zkdutm+VM;s+0EH>yCn-NgYW!xezGN}~aXqo6rB(NK zyS;iqK-FIA$t20DdI{}cVAV|U2N8AGceD<0PFoJzm&V+arNajkK}Mb9j=9bPMq)0m z$4HFyRZpmGSCxj4S#@N!GlCI z*lEs>(rWs#Bs;b3A;4;n|IgV6z^Ta3#uSftRS>LZ?YuT05ewve=zH20cBe06`_Dyb z5=G&l#jzIN6!}akLE3(i#nfi>4S@!rdAL||Q*KaVg+T4dq$o9=HOVAOD{ZRsB^z40rYS51m)Q8`1(5~;W z6-F$=&%Z~=_}l+gV>FeL4eKNxba-^|RQ5`!k&IJzNRp(Br^9^GSUt6vq#MaC7c4m- zgkq;5BqY(n!J|)D&Ws9V`S&J(SqdZQ&I`MkcWR#%cF1cg=2!8%!&3(?gE=uY-Km?g zYEq%!rovif?5UAK1Z|Y>rg2izAWYIUA8;X9TjX&_X<4MGc4cWM%ZqueRW-|L_Mcn? zv@=Hg*q8*CY&D)tt-=3raNWs z<)tCC;_KauJ{il9gfN1xbKGzO#|QK_ueT`JP7>{d9|*d`^Uw|Z)w+#iySfL1b|&A_ z9Zk=#$sC|IeWw9`ccMeO+ZXwmUmM@3m-B~QLqyUi^!hgIzZ%KbI;-*7DjwE{`zR<0 zeso5q{-E!%9a&4CwVm4h zKt0I-(hm8)#)EiY%?jEu0&&DG$=&JO;m1WZ&`Vm3+QI68Xg0xEQ9wQdlI&`-(1HCi zCoE>MREWWrXF6CK|7!7CExiE(DE-&sIH%>>9rPC&AdiwfU)N^|@(^;oW9%F)L!f@- zuem{oRht!`Q)8to+kyM-xaI%kM2e~XN1`Oto{n4VL@vOJF@&1uiZuY}M^X8mbM%l*-J@fEe`)*cd3+4dqP$7LZK;@&KEU3g{C7|eE5?qRdOxyx4i2#Ofy5@JZYMG z*wk%kQ)(s5%>5dWh7L+IC61zwjn(_ye~!hrofEY|wJUNa9CY}=auicw%26Oh$kE=I z16r|jiLMLq;nL$6Y|LNp2rmqE|L2doOdnhMRv4Rje}#M~7rU$cl;NNYdxNtX+eR2v z?8TBvec<%1m>Vq7@dW%S=z(T4wgFGKHo)I!hU#Iq*#B$?3o&2i@Xq^JeF8gsU3e-D z1ub(kbpBfg`MQ_+yQO~bm!m7PFHM@GW~{Zx4+%M{(}>a_0OP^g?scLz zs1S9@WYF>XM{SAX2FRe$%%L1k9+lwbyi<%bJ|9UzdY)$NT*StT9w|bgmmS^uxD(Fg z-t|vKNFJ4-t+D$ty6aTTv?wh;I)y_7j-6yJ&c@m3#o0K!R_c)w&g#s^VH6FB)Jw^^ z*_QyJgGjKlm+__eVnXT7D7UwhCGeQV-80|aMx}9^Y|P^5qiD$KZI1T)5^b~NEE0|; zhGG8O`6ho-*?m78-lKSh8o6~~z~lUQ{cmr4!J2=3H1qPMPYJdq0OfeM+I061l=rza zgJae%eN6uZrqg3K!tWWM@u!R_7&5sUAnRvpHU)kgs5mf1gpgVQ0`|7&#n(LpuN!!(*UOjfdNEBqLJEo}_E>5z*JZ#H$ z9R~#@u%5!ajop>t6HU$Z1NP){#w=%9pu)Uvl{%Elm`Eu3&z862h&4tHd6*dIjPp^g zOx%gac3lGn}2sQH*LR4c5fTIEaBo#xwg-_iq)>lUQpM258DTOPQ5F? zwfK0Z)OKR=;ExiMtA_ZR;?{>X@IlCC{-RG2d5-&|-P-%$%uc)gueoM^+Z7wfd)-Z+ z9lZYY`MOD>691XWNsS~AUb_gpN5?iUR%IOESL?M(*+1uwRsY@CzBfC3mp3w-fnEnK z>6u3zx~b(_GvQ6zj-2vKPpBsv3Ne)G>*oC_E zgD?u^jZH`t9LI$oF(--Qglxl%w#}$$g2iiEf>{SClBA)8@r zjU>WptfMt16*n2ff{wWFnWk|aN3oA1!C(Y&RCDN4?6o6lmSY))rYR~4Se!%|MMvOx zfeu4++>T9?Ax9E~)4(l>V}p}XB$xT+r6>aBOaR0Z4kqlH+y-o_*{1i$U50jj^e6EI z_i4~383IeF!O5WOYH6*e|L(f0g7F%p{WB>}^j~0OL%n=5nq6JBYK$*Y6m*D^b3h0MazKL0}5@Q4} z+`imDNN4fhU5LEc`4C0{5IVJ7-?5l9OUHlpV!6}@D6}pCeXeQkJ8iZSY}knwa5mtw z-i|ll-u{kA+|<^&@XAZo0*{7Gf_{?Yy*@J{*51Wryr$0L(oDu2=$BQMCifTzlr zbsH46cDz;oq%g3V>w(A0mvtLIena(I`IF8tZ%2pVxf0Vb2UlYnX16??XW5D4Fo;G- zXl+dDNO9ZY#Px{nPLoNQqK|h6SZ5r;o-nOC=4{5~XgwtRVyJGho1fGuc{=b+|2o|cx*frOQ>h~J}-bLS!2~c28D^H zVWyE4qdM0ui;VO?`>Q=>l>&6-wS7du^!9Cc50cz9Yb*I2VsXC^1- zG3XPMp&twG(@VST0?VYuP_+I(`L#y0P)B*uj$B{Xwi>&?;dTr68D+xqK~#!(`O zB>L@sLu=7%ui@3w-d%s>k0IoGj$CK9^10kVDmjpyAz|RBp-^9oN6mp~Uw0%qmDbk$W%fH6K*H|PGdXknvUhYG=`2NoEFfQ_ zI1B%Ha)Ay27qf^S;`R@^$p|bK3>2b)6n@NxEJVpHF+I;$aag z*kM9H8L_|Dmxvz{-yuE%8sLA#=@9-Y%8aOez-ny|fr#_dHsArN?{TKiWEYpn zfFg?bcTJ9LUPgR9?W|8>x}Zc5oXzt5u%Lg8Q&N_NX&WQ;47xmq&^5&vjA+Dyjw;YV zwQQVMa$u{EPLe1LTwM_PUQfG-iohv0gsHab6XcqvB!Cba_I+%2HNytIB8S%z>sy6w zR+5d0wU1caNxUsdDU>eqGj~L`<%YlnEq&aV z*fTxl3fom#QPo}7nAIW*dtHjH&^o6>$_J#zQJ)!J^$UxNU+FTB;6r(6xC;B`>umeM+ZiAKd$-_Da4c#IxVJ*VNWTgQI!`!-TWKil zMAqT-)}Am%?y@7QPJU|fIh@cWO^<~<{uGk&#ACTt?{4y|qH_YD3l7Y4ZM(6Neomka zx(4~%?1Uy&f$_SQ4#{$$36bv|Cot4oW6-b=vUJV#G3XBtUd*+^e&1S~IPRGflMaa$ z;KfIGlItf&1T4jDC$+~uqjAT)B1oK7o{|Y5fNXaiP@;~-O)+gGH9t@XJEc6vVh%1r z7wKvQw5K(35^D1%%XT_tNL`EJ=_C(>9Y=9dK3ozMg9&d4ze+_lPey_dm+)wV?Vao))<4WjL>vsT)QBjqy> z<2YMh^$ktRMdNQEceanKW!oCsqN-qQlZr)|AS;%lsJ76PZ?-70OyYW?sRMs5rEX|) zHFz>GYI~QO-p27qhi`A0EDxps__rk!&2|#&eMUL`g2IcOMVyjwhP~?1CSu1|kZ;>{ z8XI9ME?aq(s=8stLv<&FQiafy3|R<`QqFgjm31wV!z0$9bo`{SQU{NNGnp6rHb^`v z+02Yi*)x4o*10~gyvX#;miF}7=+Ub(#t42lL^%qQySAm*86;v?@0Wg)Z&OB`m>#yP zmekWqsj972gLa-ptLkj51C-nbuq8Ecra|AeL3&VO8%{?mcEmVc@Tk@UJ3zgIL8%7@ zT)P4OHq)g%Q#rlLKqD<9zBcOiV(Tn>lR?meGZqV(evUyCr8SabvELF11^03>uDzC3 zDaa8M#&B?^TyS#Ge4vLd?|au_rysEd{XhjAf+vuK;2pXA^lS-Ugl7VZh}!KaCeAAz z2gZrk27ojAf@!s3?c7dZ$}OCxHzvfOK+C96T4!6OW^i57j;NAi>n&Aww;s+%G){cp2A#!b&7feHu6;a|@mgA@`+P>dm4V~lFGRQFd zJ$lo9q{#l#3l4?gn3hR@DoBg45U7_yWVMnp|G-lKVKC7TQ{io3X<3v~0)1|k8{Gzb z)@E7|^5**J@A7Ra66JSZ`u@(%Y)ray{yD8v=C$s+*|5lYs~T*pnLbT7z?R&=s}}C= zZj{>X`fk@2kIzupaP1~5_NU!111{Op_)0$0E}1Z00(erytjn%A*JYoOznFvAKiMo6 zj23y(aQ9NEu^#@1zIk5_7d) zx(W{|w>|@@hw@(5Pqm_-0Ah4DZ363tYAnDJXh#%80>>>PbuLOY&9;Mk#mO@~>Us=% z7y;q_r(?u1_4W{u!K>yll}7D^epsydg3@%%BGD;;yMngqyzpRe0X>*zc^Jf=HP`-OpsRmCd2b zx?tttaA%$&haa@h#V>BQt=DNN&0W(YfnU7#o(G$Evda14khiHJYn&*JQgMCl_e_TV zLp{9qYRxgL;r z&K@jJhX$LuEEK(H-@pUxpU!m59s8Yb)BF?0MQKIF9!ibol}}&j50BKb`D~KDB>#)! zXVVZ7^bpv%`{;w0FvuG*NipVFXG_IG4M)t3=l}Z;?BMeunnY((&6Crn&zN5SGxEOu z@P$8jpIWM%t>T&Tp+!lS2C!vBHw$-T3!z_A!wjYfa`21 zAQ_W9mTb_Q)qu?Y~r3j$=M3OTt>P)i6r}e=i zmTou%affq`?MN{d|5=}~VBvuOODZKz1(dZGy+&_G^vP&5mJH;H2NAA<@6W4V$T%!S zLnwH@76{g;w9~5n5E<1FA~q6d}%ckpq_*vD}P!n0gxzSdSVl{CzR>GA3^yh**Q zdQUS0;KxbOpw>21?SyIU!EMzSZ~qpgiski7@np-I>MQO$g6K>}Ks2JCL^%ws7@a@& zs#bJzbgDBMVSvozV0+m45ltW{m6;^4X3C za=mGu6VvAA$yjbR?w0vwjXGwVVVY4iW7mwL8N3-qGZW1yn&nI<&|ap5%lZ1o%z&jY zhrs830{*xgh@}|}KAAViTb}{n%&s@+U8#pacSn2s58-10Q%EN8v@YE1SgRmaoG?eU zpt5{W^>J`C?dZg4OhX4ozAWA&YN*~oU#m?6QDg&;pf5W!)HP4z74)^rh*+h44tNF? z;7qxSvp;bjLK6(I#j$z`bvI2VAB%)zpS-kmc4<1^LSL3mmSS(>G4v;y(ej1#zrbrK z+R%pSXhT(SZ<9O_{X5CSt|fIk?M73O3`>LOOnW1CKGnI`D2|A8S~D1r&jG8alvBH4_e&sC7KZ>LaU7GO3vwZ zo*kTTrT{~6O7Yt&&%;+$P4^e_soD}>6&Nng=Q=>>H)x1!*uMbA%l=H+`sacbLI@^B zYNmV2i7VMpp1k2a>YY7r9ClRL4_u5r*H4BP@se)RI8O6Cn|K4}w1}>fD^^XRNi$Va z7p1-PLZYPDC}U9D=NR0=aUzXGbFxiyW?V|MygwEJ5!klNilat8hFI0M8mYD;{^fYY zp;{~KYC=_6VJG$hVx!TP;>1vJebI5Td)YXfQm}IJ7b5pM{&=-J{CDVC_)q6geo^YV z34Ecg{k|iMt{Ar}`4$msN?KV7w&m=>KOx(38d%LPHSc$TCl|D5s0?KP4mdMbrpT-PlG}R?zvb z2CO7XL~Zok|w|b1CgdBE}^|?OD=VGv0|KM z5dMG6JrT`!D*Q{(JuUk@@)zWP3K|NEsw5r59y+W=`aU$CtB^`fhsoTb)v6S7y+&g+ z+g&cZ!`!9UDMVs<{%&0zx(kwuFno{aLW1gPS{XnY};g8r(Kh1-=d2y~&41{W93UILB;8UktmviPqr2^4oPB zyguG6-+=SyeAy*}|CG83#z%|0_T9$Gr_05_F6k?*^^)*J9qgE51x=vH8)%sQUH@e6 zQ9AfvPEoiw1F7OxKSd?_Q{hA=CGfBK^W|g9CuGL^*%f~!d~A`KA1Cg~4vY|h!bpsK zS|7fLD**Y0J&GCz1e&M&IRVqhu<7@v3Yh=$X2{c5-Wsnepbl4{6z?%IM*%4W5wsZH z2ZwH^k?Zs}LL(E?TP>)PU|9fY(W598&bO9?6CYI+LuLbZDJg%jo^v|P-YN~bP6PAG zPV*Oej_VCh!{KO9Q`KN7jK=Fgez^r@{RowKfvAM4gaRQ* znm9@dxs;FX?}Py2;LFRtI~x_yU{?K4-j{5c@sY`- zG;BQJ$l*9iN;&0-y9C2BG~&CNP0=%lV<@s?d%OfS+1K%{X^9sBRaP~v5c4@TMDE>5 zj{M5s{kJS}JxFRvh~lh{m^xDSLl6+mH^+)jHD2O&AJ)VRq(tYErT1DzM^{9-tHb z)s@1jY)zJERFqKuI@kS=(q$Z%JhWXL%iz1HsyZ7N#xtSBrFJl{^SmnJwV8@+-O)mn zwg+vg7Gro*%=K`h43|OgfX<>X|Ovb z&%$n_&N|v-diuOme*D!P!g|2Pcxmo2)hY%ZJ zjUWgkCg9AA!W5zqKr6*@pYewXg643VT;rgD8_>i?$zxR!X5wz#gPE9lFn)kgF_cHP zY1g5x9%)MizNn(8yqmp@ z5SEp0KDeOS4fs}CVc9EJ2+7j)GjIRX+H&;C7bVwO+-cBUw$gvhZxVS=%XETIIHZPLc1 z6H5ZaL`c4oLU{b}kt-b%8x)YbGQ-DBfs0oN=k1^p2%b0Nj1o>l0$s-73OXV(2{K)q z3?cSr(+YE7;=~r6g~esJJaqHK)A!f$;Pt7kGeY4=G@dVK@y#$&J|?q9uNgx_fE(fk zn#72~9V&rB8@+{U7mdHEYP~g4!nOM+E}bXi)n+l^OSMtdt-(iNf57aJM5jgf{h_xk zkw^Fgrv@ViNq(Qt9I3jNa858gXj}r{rtwHg@Xi7&=P+I9q4p}_%_k=rpncP-nvzLE zYlR4i$X7s|aYVb*Z+vBlhM0@%a2IA`ddp*{cFWQf!yynsjosE7f-R{M*KR2i+h`lu zK{~s`@uH&25cq@FDw*|}$$l`IRMEW`))(>$r^Qw8+bou7u_aubm+jiE%Rk$$%&f)T zgn@chOTAd$ZFM9q3O$W^=fAJPJ==pk`!E+sS3}Z!H{GqYcDLV%CWl5ke*)%1^3zdT zu|~hxLm>;_Hs0mUS3Dk5>+8oC-0pES6b^YB9#1t;_thir$`v%+mOQ==s#@1$6L>)< z!RAcD&l$tbUX|7cv0z~rc@G8?#2LTTqgU~E@(1?obVvxss)1B4{*IgW#&Cq>$ES!d z5Hxsj@HNZTb|}jR`Y7U4Tl};iR|_P3Xi+$wVxA-0y%SyX(teySqUC#?&UU_bB-q=| zPV~5V2@jX$uuZ~{M*ZXd&8b+il}SD%tF$bVB%whxP;HsTVVnRJ8Ba@K2M<)$+dD|! z+_L6rapBB3BI^V$V{dyEgib(h>w)XPvn4ZQ>aJ6$cmQhp!3o{$pb zYWhe=klC9_mCGrx3W%@~M2d`wfII}zP)dLS1EFF7tf{7B!zgHjQU%o&T?}4%3dDnk zEt5V|htmh2g>2{XhoF5Q4X)jzn!Az=966-+#iRRuzz+^AUwbE}I@V}dNX)@Yoz8hf z@utu80=u*9PxdRMti7)g@tewRpG_>S;xs@4jCsvu$cv-pxxu%=uoxT~%E+sESy^&h z?jy|fx}8p!6GTarmEKm>+pUN^*J*>EG;7+BVv43AH4@)T+X_@&^F?JVn;A@G4wKQb zYyU(l>*YjPGlO$!_J-TVkZfj@=^kZsVKowMmamRfmWCvRr<@Zlx6C_Qt7~(09?j0$ zL)kX4G*2BKAV*M#s}$C?Ox;jDx+sdOYxve3q9(1RXb9EjoP;vg$FMm#0wETt9CKOC zOofKYKM3!a$%fr7S&~GC849jH;CNA%13D#>1kf>m{{u^0yv zj0poNe>It4O~xCrF{$IR4k&|$E)_pr2lVEsr&f!E7lXMOA^BojJ+H-py=vPjn3&Yw9uou!|o5`#z zHnz**uefJhI40--A_LJ!M>wL7-Pi?0f{ra16I#rSDGTPGii6m{a{F$wWu-=}274zg zK0EnZly|-_0h`N&8Hx-A)LrHx!Upmr>==tEDQgdlHDKKXuCrn~mJUkXyIV!bftt%s zPZ*cm3}K7o(P1YD#*BEYKx$>ms9T`^axEt2rKRuYZH*2k^jM#3d}!4JKD=%_t&$JuE77zK!=*38XL-mVG)t9d! zZc^V~LcO$qniz#`jy#7anX!;0pN&oe#p%{o4f?$$e91A1Za^_0K{goem@S7plniwO>Za zYVt8i#wvnsTA{ijNs*ABj)B(mnEgky%k>qujXW8HS) zy-)7!3yU@6j@mgRHPhDXrzDa70qpG&-{Pe@`HomIiup*}fX|jtb!;}W_tM?pquTz) z>DqE#7rUT+K(IQe{uDz%7Loi0Ay<)8VMM{rcIKvyC)~u#< z(Sp7cn!lN*-I6oq_BlhoCb@cqud|Lut9CrjnDgLk!|!;!ocFNfd^j_;567gEn9p_? zG~n+nH4MOHAfBeqB5{ zrz`PA;`i_#v@6oWm8FJAVLbXn0gZ0q4N($gL# zmLv9Ga1v>98`RZ|+L@(=^f7a4 z;2sk*+M(H#6;OvVlI6Nc&Cq%bu^qexXfNmpx6 z3)L2_u98`RX45rTK#2G!v!0Z*&3d?>+fJ0G3s5L|0Nk>JVgLXD literal 0 HcmV?d00001 diff --git a/assets/inter-italic-cyrillic.By2_1cv3.woff2 b/assets/inter-italic-cyrillic.By2_1cv3.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..def40a4f658cf8a9f7029c98931f5c9ff5a00910 GIT binary patch literal 31300 zcmV(?K-a%_Pew8T0RR910D43K6951J0MIl50C~{>1ONa400000000000000000000 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�!Z1%E;0yxE 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 DQqDCk%U}E%4TNCAYy)Ortm-QE& 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 literal 0 HcmV?d00001 diff --git a/assets/inter-italic-greek-ext.4fbe9427.woff2 b/assets/inter-italic-greek-ext.4fbe9427.woff2 deleted file mode 100644 index 00218960325a4636092b66a46e701c2bf4bb0466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12188 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 diff --git a/assets/inter-italic-greek.DJ8dCoTZ.woff2 b/assets/inter-italic-greek.DJ8dCoTZ.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a3c16ca40b2a8f454c34cfa91996ec99ae2e4aa0 GIT binary patch literal 32564 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

l(X_I+GK&R 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 diff --git a/assets/inter-roman-cyrillic.5f2c6c8c.woff2 b/assets/inter-roman-cyrillic.5f2c6c8c.woff2 deleted file mode 100644 index a20adc161f433a7c4e3d92306301b9228bcf9fb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16780 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

KZ;k8ywA} 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 H00000K--!s literal 0 HcmV?d00001 diff --git a/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 b/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..36d67487dcf5fbe3dc6d0a6b01cf4d29dc997765 GIT binary patch literal 16272 zcmV;BKX1TyPew8T0RR9106&lb6951J0Hgo_06!c61ONa400000000000000000000 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 G0RR9|PM1{x literal 0 HcmV?d00001 diff --git a/assets/inter-roman-greek-ext.ab0619bc.woff2 b/assets/inter-roman-greek-ext.ab0619bc.woff2 deleted file mode 100644 index e3b0be76db2641253744aa613469eedb118667da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11808 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 O1{o}0SRMEP0000Yp_Hru diff --git a/assets/inter-roman-greek.BBVDIX6e.woff2 b/assets/inter-roman-greek.BBVDIX6e.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2bed1e85e8b20cb3903206a6cace251c52bdd8c3 GIT binary patch literal 29920 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 literal 0 HcmV?d00001 diff --git a/assets/inter-roman-greek.d5a6d92a.woff2 b/assets/inter-roman-greek.d5a6d92a.woff2 deleted file mode 100644 index f790e047daa346583880da2be470431e35aa6054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21776 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 De!(H( diff --git a/assets/inter-roman-latin-ext.0030eebd.woff2 b/assets/inter-roman-latin-ext.0030eebd.woff2 deleted file mode 100644 index 715bd903b9b14d22a056f10e6d13b8d7e0acce57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59608 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 literal 0 HcmV?d00001 diff --git a/assets/kvm.d81063e5.png b/assets/kvm.CI48mv3H.png similarity index 100% rename from assets/kvm.d81063e5.png rename to assets/kvm.CI48mv3H.png diff --git a/assets/lower1.28498396.png b/assets/lower1.DFw6c1iw.png similarity index 100% rename from assets/lower1.28498396.png rename to assets/lower1.DFw6c1iw.png diff --git a/assets/lower2.e782a20a.png b/assets/lower2.SPGPKJ4N.png similarity index 100% rename from assets/lower2.e782a20a.png rename to assets/lower2.SPGPKJ4N.png diff --git a/assets/lxd1.78537e30.png b/assets/lxd1.CbGLa5s4.png similarity index 100% rename from assets/lxd1.78537e30.png rename to assets/lxd1.CbGLa5s4.png diff --git a/assets/lxd10.a25a745c.png b/assets/lxd10.BjQ0l1K7.png similarity index 100% rename from assets/lxd10.a25a745c.png rename to assets/lxd10.BjQ0l1K7.png diff --git a/assets/lxd11.b83f953c.png b/assets/lxd11.D6E5sVW2.png similarity index 100% rename from assets/lxd11.b83f953c.png rename to assets/lxd11.D6E5sVW2.png diff --git a/assets/lxd12.0da335dd.png b/assets/lxd12.B9udKIzn.png similarity index 100% rename from assets/lxd12.0da335dd.png rename to assets/lxd12.B9udKIzn.png diff --git a/assets/lxd13.308fe0de.png b/assets/lxd13.Dwv7xBpz.png similarity index 100% rename from assets/lxd13.308fe0de.png rename to assets/lxd13.Dwv7xBpz.png diff --git a/assets/lxd14.8dbfdcd6.png b/assets/lxd14.Whdz6cP-.png similarity index 100% rename from assets/lxd14.8dbfdcd6.png rename to assets/lxd14.Whdz6cP-.png diff --git a/assets/lxd15.70114933.png b/assets/lxd15.BjW7LbDr.png similarity index 100% rename from assets/lxd15.70114933.png rename to assets/lxd15.BjW7LbDr.png diff --git a/assets/lxd16.a595fa36.png b/assets/lxd16.CgeIdYJ2.png similarity index 100% rename from assets/lxd16.a595fa36.png rename to assets/lxd16.CgeIdYJ2.png diff --git a/assets/lxd17.d7ea65d8.png b/assets/lxd17.CWPY1pea.png similarity index 100% rename from assets/lxd17.d7ea65d8.png rename to assets/lxd17.CWPY1pea.png diff --git a/assets/lxd18.d6225daa.png b/assets/lxd18.DqnpcYcL.png similarity index 100% rename from assets/lxd18.d6225daa.png rename to assets/lxd18.DqnpcYcL.png diff --git a/assets/lxd19.69674669.png b/assets/lxd19.B9_MB265.png similarity index 100% rename from assets/lxd19.69674669.png rename to assets/lxd19.B9_MB265.png diff --git a/assets/lxd2.da10b5ec.png b/assets/lxd2.C4eWfnaM.png similarity index 100% rename from assets/lxd2.da10b5ec.png rename to assets/lxd2.C4eWfnaM.png diff --git a/assets/lxd20.179fc6e1.png b/assets/lxd20.rK3P3TT8.png similarity index 100% rename from assets/lxd20.179fc6e1.png rename to assets/lxd20.rK3P3TT8.png diff --git a/assets/lxd21.48123d6a.png b/assets/lxd21.w-R0l00Y.png similarity index 100% rename from assets/lxd21.48123d6a.png rename to assets/lxd21.w-R0l00Y.png diff --git a/assets/lxd22.4386597e.png b/assets/lxd22.45M-VX6J.png similarity index 100% rename from assets/lxd22.4386597e.png rename to assets/lxd22.45M-VX6J.png diff --git a/assets/lxd23.c26427e3.png b/assets/lxd23.CLaVW0qk.png similarity index 100% rename from assets/lxd23.c26427e3.png rename to assets/lxd23.CLaVW0qk.png diff --git a/assets/lxd3.917f56de.png b/assets/lxd3.tQBNiKQo.png similarity index 100% rename from assets/lxd3.917f56de.png rename to assets/lxd3.tQBNiKQo.png diff --git a/assets/lxd4.83a1a121.png b/assets/lxd4.CSfRHLxz.png similarity index 100% rename from assets/lxd4.83a1a121.png rename to assets/lxd4.CSfRHLxz.png diff --git a/assets/lxd5.4ebc1444.png b/assets/lxd5.WUJi0qzd.png similarity index 100% rename from assets/lxd5.4ebc1444.png rename to assets/lxd5.WUJi0qzd.png diff --git a/assets/lxd6.572825bf.png b/assets/lxd6.Cnds779U.png similarity index 100% rename from assets/lxd6.572825bf.png rename to assets/lxd6.Cnds779U.png diff --git a/assets/lxd7.b73982c7.png b/assets/lxd7.EJ0s1ls2.png similarity index 100% rename from assets/lxd7.b73982c7.png rename to assets/lxd7.EJ0s1ls2.png diff --git a/assets/lxd8.9fcc21e5.png b/assets/lxd8.DAOueoww.png similarity index 100% rename from assets/lxd8.9fcc21e5.png rename to assets/lxd8.DAOueoww.png diff --git a/assets/lxd9.00250a32.png b/assets/lxd9.Dgmw4lpJ.png similarity index 100% rename from assets/lxd9.00250a32.png rename to assets/lxd9.Dgmw4lpJ.png diff --git a/assets/lxdd0.b1d6b8bc.png b/assets/lxdd0.QoEngFSd.png similarity index 100% rename from assets/lxdd0.b1d6b8bc.png rename to assets/lxdd0.QoEngFSd.png diff --git a/assets/lxdd1.433ff357.png b/assets/lxdd1.CVTAIewh.png similarity index 100% rename from assets/lxdd1.433ff357.png rename to assets/lxdd1.CVTAIewh.png diff --git a/assets/lxdd2.6a93138a.png b/assets/lxdd2.C_mYE7sL.png similarity index 100% rename from assets/lxdd2.6a93138a.png rename to assets/lxdd2.C_mYE7sL.png diff --git a/assets/lxdd3.f56cf598.png b/assets/lxdd3.DZ2Na5-t.png similarity index 100% rename from assets/lxdd3.f56cf598.png rename to assets/lxdd3.DZ2Na5-t.png diff --git a/assets/lxdd4.28d80b71.png b/assets/lxdd4.CO1I1FPh.png similarity index 100% rename from assets/lxdd4.28d80b71.png rename to assets/lxdd4.CO1I1FPh.png diff --git a/assets/mac0.935d53f3.png b/assets/mac0.CofQ9vw_.png similarity index 100% rename from assets/mac0.935d53f3.png rename to assets/mac0.CofQ9vw_.png diff --git a/assets/mac00.4296be7b.png b/assets/mac00.DelKhhmr.png similarity index 100% rename from assets/mac00.4296be7b.png rename to assets/mac00.DelKhhmr.png diff --git a/assets/mac1.3307e401.png b/assets/mac1.D7yJtJrl.png similarity index 100% rename from assets/mac1.3307e401.png rename to assets/mac1.D7yJtJrl.png diff --git a/assets/mac10.e9c284db.png b/assets/mac10.CZg7Yifb.png similarity index 100% rename from assets/mac10.e9c284db.png rename to assets/mac10.CZg7Yifb.png diff --git a/assets/mac11.a7587e0e.png b/assets/mac11.P11nsmhn.png similarity index 100% rename from assets/mac11.a7587e0e.png rename to assets/mac11.P11nsmhn.png diff --git a/assets/mac12.06b051d3.png b/assets/mac12.DHTBO7ih.png similarity index 100% rename from assets/mac12.06b051d3.png rename to assets/mac12.DHTBO7ih.png diff --git a/assets/mac13.7d4e3199.png b/assets/mac13.DDrsH3zK.png similarity index 100% rename from assets/mac13.7d4e3199.png rename to assets/mac13.DDrsH3zK.png diff --git a/assets/mac14.39a58b6a.png b/assets/mac14.dLHoMtJy.png similarity index 100% rename from assets/mac14.39a58b6a.png rename to assets/mac14.dLHoMtJy.png diff --git a/assets/mac15.f151793c.png b/assets/mac15.vkr7IxY1.png similarity index 100% rename from assets/mac15.f151793c.png rename to assets/mac15.vkr7IxY1.png diff --git a/assets/mac16.eae177db.png b/assets/mac16.CeB_3pKz.png similarity index 100% rename from assets/mac16.eae177db.png rename to assets/mac16.CeB_3pKz.png diff --git a/assets/mac17.be61913a.png b/assets/mac17.qkqeaTbW.png similarity index 100% rename from assets/mac17.be61913a.png rename to assets/mac17.qkqeaTbW.png diff --git a/assets/mac18.f9454618.png b/assets/mac18.ChbyoMxq.png similarity index 100% rename from assets/mac18.f9454618.png rename to assets/mac18.ChbyoMxq.png diff --git a/assets/mac19.845f5510.png b/assets/mac19.C_d085-7.png similarity index 100% rename from assets/mac19.845f5510.png rename to assets/mac19.C_d085-7.png diff --git a/assets/mac2.da6ce0bc.png b/assets/mac2.du7V_m90.png similarity index 100% rename from assets/mac2.da6ce0bc.png rename to assets/mac2.du7V_m90.png diff --git a/assets/mac20.49a5800c.png b/assets/mac20.DsWyqQaw.png similarity index 100% rename from assets/mac20.49a5800c.png rename to assets/mac20.DsWyqQaw.png diff --git a/assets/mac21.2c30b60f.png b/assets/mac21.XZ5wILhH.png similarity index 100% rename from assets/mac21.2c30b60f.png rename to assets/mac21.XZ5wILhH.png diff --git a/assets/mac3.76a50b9f.png b/assets/mac3.BCWQuf_Q.png similarity index 100% rename from assets/mac3.76a50b9f.png rename to assets/mac3.BCWQuf_Q.png diff --git a/assets/mac4.c341ba50.png b/assets/mac4.B0L5oLF9.png similarity index 100% rename from assets/mac4.c341ba50.png rename to assets/mac4.B0L5oLF9.png diff --git a/assets/mac5.39e1c9a4.png b/assets/mac5.QrcmrZyS.png similarity index 100% rename from assets/mac5.39e1c9a4.png rename to assets/mac5.QrcmrZyS.png diff --git a/assets/mac6.1cc0462b.png b/assets/mac6.CEnQahaC.png similarity index 100% rename from assets/mac6.1cc0462b.png rename to assets/mac6.CEnQahaC.png diff --git a/assets/mac7.181275ae.png b/assets/mac7.Cq44sm3y.png similarity index 100% rename from assets/mac7.181275ae.png rename to assets/mac7.Cq44sm3y.png diff --git a/assets/mac8.dd556f02.png b/assets/mac8.CfhgXZ8s.png similarity index 100% rename from assets/mac8.dd556f02.png rename to assets/mac8.CfhgXZ8s.png diff --git a/assets/mac9.c5d88eba.png b/assets/mac9.DIA9P3VH.png similarity index 100% rename from assets/mac9.c5d88eba.png rename to assets/mac9.DIA9P3VH.png diff --git a/assets/memory.c4992870.png b/assets/memory.CH7Gxf76.png similarity index 100% rename from assets/memory.c4992870.png rename to assets/memory.CH7Gxf76.png diff --git a/assets/net1.4f166207.png b/assets/net1.CUyp8ayS.png similarity index 100% rename from assets/net1.4f166207.png rename to assets/net1.CUyp8ayS.png diff --git a/assets/net2.e2773ada.png b/assets/net2.BP2m5XnQ.png similarity index 100% rename from assets/net2.e2773ada.png rename to assets/net2.BP2m5XnQ.png diff --git a/assets/net3.40e8a226.png b/assets/net3.BJFg7Me5.png similarity index 100% rename from assets/net3.40e8a226.png rename to assets/net3.BJFg7Me5.png diff --git a/assets/net4.a81e777c.png b/assets/net4.CANZtcPE.png similarity index 100% rename from assets/net4.a81e777c.png rename to assets/net4.CANZtcPE.png diff --git a/assets/network.48037353.png b/assets/network.DPXM5W42.png similarity index 100% rename from assets/network.48037353.png rename to assets/network.DPXM5W42.png diff --git a/assets/nodisk.5ec86f3b.png b/assets/nodisk.CH47I8Tu.png similarity index 100% rename from assets/nodisk.5ec86f3b.png rename to assets/nodisk.CH47I8Tu.png diff --git a/assets/nodisk1.671c1309.png b/assets/nodisk1.gZ09o2py.png similarity index 100% rename from assets/nodisk1.671c1309.png rename to assets/nodisk1.gZ09o2py.png diff --git a/assets/nodisk2.ff20bb76.png b/assets/nodisk2.Do6XEKMW.png similarity index 100% rename from assets/nodisk2.ff20bb76.png rename to assets/nodisk2.Do6XEKMW.png diff --git a/assets/nodisk3.71534a11.png b/assets/nodisk3.1vBQc75S.png similarity index 100% rename from assets/nodisk3.71534a11.png rename to assets/nodisk3.1vBQc75S.png diff --git a/assets/nodisk4.b08d75e3.png b/assets/nodisk4.CJjHGgtp.png similarity index 100% rename from assets/nodisk4.b08d75e3.png rename to assets/nodisk4.CJjHGgtp.png diff --git a/assets/onlinepkg.30da8d76.png b/assets/onlinepkg.-C5qKOrj.png similarity index 100% rename from assets/onlinepkg.30da8d76.png rename to assets/onlinepkg.-C5qKOrj.png diff --git a/assets/os.b2be1a5c.png b/assets/os.CX7bMEp5.png similarity index 100% rename from assets/os.b2be1a5c.png rename to assets/os.CX7bMEp5.png diff --git a/assets/pve_kvm_1.0f7e84f0.png b/assets/pve_kvm_1.BEDy-Dxt.png similarity index 100% rename from assets/pve_kvm_1.0f7e84f0.png rename to assets/pve_kvm_1.BEDy-Dxt.png diff --git a/assets/pve_kvm_2.cefb9578.png b/assets/pve_kvm_2.C98l0GO8.png similarity index 100% rename from assets/pve_kvm_2.cefb9578.png rename to assets/pve_kvm_2.C98l0GO8.png diff --git a/assets/pve_kvm_3.1d307586.png b/assets/pve_kvm_3.DzuyyWMo.png similarity index 100% rename from assets/pve_kvm_3.1d307586.png rename to assets/pve_kvm_3.DzuyyWMo.png diff --git a/assets/start.3aebbfd4.png b/assets/start.vjgB4hml.png similarity index 100% rename from assets/start.3aebbfd4.png rename to assets/start.vjgB4hml.png diff --git a/assets/style.DFTx90Kk.css b/assets/style.DFTx90Kk.css new file mode 100644 index 0000000000..d8b392b13b --- /dev/null +++ b/assets/style.DFTx90Kk.css @@ -0,0 +1 @@ +@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: #3c3c43;--vp-c-text-2: #67676c;--vp-c-text-3: #929295}.dark{--vp-c-text-1: #dfdfd6;--vp-c-text-2: #98989f;--vp-c-text-3: #6a6a71}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:lang(es),:lang(pt){--vp-code-copy-copied-text-content: "Copiado"}:lang(fa){--vp-code-copy-copied-text-content: "کپی شد"}:lang(ko){--vp-code-copy-copied-text-content: "복사됨"}:lang(ru){--vp-code-copy-copied-text-content: "Скопировано"}:lang(zh){--vp-code-copy-copied-text-content: "已复制"}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;-webkit-user-select:none;user-select:none;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-c79a1216]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-c79a1216],.VPBackdrop.fade-leave-to[data-v-c79a1216]{opacity:0}.VPBackdrop.fade-leave-active[data-v-c79a1216]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-c79a1216]{display:none}}.NotFound[data-v-d6be1790]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-d6be1790]{padding:96px 32px 168px}}.code[data-v-d6be1790]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-d6be1790]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-d6be1790]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-d6be1790]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-d6be1790]{padding-top:20px}.link[data-v-d6be1790]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-d6be1790]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-b933a997]{position:relative;z-index:1}.nested[data-v-b933a997]{padding-right:16px;padding-left:16px}.outline-link[data-v-b933a997]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-b933a997]:hover,.outline-link.active[data-v-b933a997]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-b933a997]{padding-left:13px}.VPDocAsideOutline[data-v-a5bbad30]{display:none}.VPDocAsideOutline.has-outline[data-v-a5bbad30]{display:block}.content[data-v-a5bbad30]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-a5bbad30]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-a5bbad30]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-3f215769]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-3f215769]{flex-grow:1}.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-3f215769] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-e98dd255]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-e98dd255]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-e257564d]{margin-top:64px}.edit-info[data-v-e257564d]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-e257564d]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-e257564d]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-e257564d]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-e257564d]{margin-right:8px}.prev-next[data-v-e257564d]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-e257564d]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-e257564d]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-e257564d]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-e257564d]{margin-left:auto;text-align:right}.desc[data-v-e257564d]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-e257564d]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-39a288b8]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-39a288b8]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-39a288b8]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-39a288b8]{display:flex;justify-content:center}.VPDoc .aside[data-v-39a288b8]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{max-width:1104px}}.container[data-v-39a288b8]{margin:0 auto;width:100%}.aside[data-v-39a288b8]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-39a288b8]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-39a288b8]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-39a288b8]::-webkit-scrollbar{display:none}.aside-curtain[data-v-39a288b8]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-39a288b8]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-39a288b8]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-39a288b8]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-39a288b8]{order:1;margin:0;min-width:640px}}.content-container[data-v-39a288b8]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-39a288b8]{max-width:688px}.VPButton[data-v-fa7799d5]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-fa7799d5]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-fa7799d5]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-fa7799d5]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-fa7799d5]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-fa7799d5]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-fa7799d5]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-fa7799d5]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-fa7799d5]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-fa7799d5]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-fa7799d5]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-fa7799d5]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-fa7799d5]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-8426fc1a]{display:none}.dark .VPImage.light[data-v-8426fc1a]{display:none}.VPHero[data-v-4f9c455b]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-4f9c455b]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-4f9c455b]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-4f9c455b]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-4f9c455b]{flex-direction:row}}.main[data-v-4f9c455b]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-4f9c455b]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-4f9c455b]{text-align:left}}@media (min-width: 960px){.main[data-v-4f9c455b]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-4f9c455b]{max-width:592px}}.heading[data-v-4f9c455b]{display:flex;flex-direction:column}.name[data-v-4f9c455b],.text[data-v-4f9c455b]{width:fit-content;max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-4f9c455b],.VPHero.has-image .text[data-v-4f9c455b]{margin:0 auto}.name[data-v-4f9c455b]{color:var(--vp-home-hero-name-color)}.clip[data-v-4f9c455b]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-4f9c455b],.text[data-v-4f9c455b]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-4f9c455b],.text[data-v-4f9c455b]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-4f9c455b],.VPHero.has-image .text[data-v-4f9c455b]{margin:0}}.tagline[data-v-4f9c455b]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-4f9c455b]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-4f9c455b]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-4f9c455b]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-4f9c455b]{margin:0}}.actions[data-v-4f9c455b]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-4f9c455b]{justify-content:center}@media (min-width: 640px){.actions[data-v-4f9c455b]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-4f9c455b]{justify-content:flex-start}}.action[data-v-4f9c455b]{flex-shrink:0;padding:6px}.image[data-v-4f9c455b]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-4f9c455b]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-4f9c455b]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-4f9c455b]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-4f9c455b]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-4f9c455b]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-4f9c455b]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-4f9c455b]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-4f9c455b]{width:320px;height:320px}}[data-v-4f9c455b] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-4f9c455b] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-4f9c455b] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-a3976bdc]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-a3976bdc]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-a3976bdc]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-a3976bdc]>.VPImage{margin-bottom:20px}.icon[data-v-a3976bdc]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-a3976bdc]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-a3976bdc]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-a3976bdc]{padding-top:8px}.link-text-value[data-v-a3976bdc]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-a3976bdc]{margin-left:6px}.VPFeatures[data-v-a6181336]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-a6181336]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-a6181336]{padding:0 64px}}.container[data-v-a6181336]{margin:0 auto;max-width:1152px}.items[data-v-a6181336]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-a6181336]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336]{width:50%}.item.grid-3[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-a6181336]{width:25%}}.container[data-v-8e2d4988]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-8e2d4988]{padding:0 48px}}@media (min-width: 960px){.container[data-v-8e2d4988]{width:100%;padding:0 64px}}.vp-doc[data-v-8e2d4988] .VPHomeSponsors,.vp-doc[data-v-8e2d4988] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-8e2d4988] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-8e2d4988] .VPHomeSponsors a,.vp-doc[data-v-8e2d4988] .VPTeamPage a{text-decoration:none}.VPHome[data-v-8b561e3d]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-8b561e3d]{margin-bottom:128px}}.VPContent[data-v-1428d186]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-1428d186]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-1428d186]{margin:0}@media (min-width: 960px){.VPContent[data-v-1428d186]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-1428d186]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-1428d186]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e315a0ad]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e315a0ad]{display:none}.VPFooter[data-v-e315a0ad] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-e315a0ad] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-e315a0ad]{padding:32px}}.container[data-v-e315a0ad]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e315a0ad],.copyright[data-v-e315a0ad]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-8a42e2b4]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-8a42e2b4]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-8a42e2b4]{color:var(--vp-c-text-1)}.icon[data-v-8a42e2b4]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]{font-size:14px}.icon[data-v-8a42e2b4]{font-size:16px}}.open>.icon[data-v-8a42e2b4]{transform:rotate(90deg)}.items[data-v-8a42e2b4]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-8a42e2b4]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-8a42e2b4]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-8a42e2b4]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-8a42e2b4]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-8a42e2b4]{transition:all .2s ease-out}.flyout-leave-active[data-v-8a42e2b4]{transition:all .15s ease-in}.flyout-enter-from[data-v-8a42e2b4],.flyout-leave-to[data-v-8a42e2b4]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-a6f0e41e]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-a6f0e41e]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-a6f0e41e]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-a6f0e41e]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-a6f0e41e]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-a6f0e41e]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-a6f0e41e]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-a6f0e41e]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-a6f0e41e]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-a6f0e41e]{display:none}}.menu-icon[data-v-a6f0e41e]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 32px 11px}}.VPSwitch[data-v-1d5665e3]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-1d5665e3]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-1d5665e3]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-1d5665e3]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-1d5665e3] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-1d5665e3] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-5337faa4]{opacity:1}.moon[data-v-5337faa4],.dark .sun[data-v-5337faa4]{opacity:0}.dark .moon[data-v-5337faa4]{opacity:1}.dark .VPSwitchAppearance[data-v-5337faa4] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-6c893767]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-6c893767]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-35975db6]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-35975db6]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-35975db6]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-35975db6]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-69e747b5]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-69e747b5]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-69e747b5]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-69e747b5]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-b98bc113]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-b98bc113] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-b98bc113] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-b98bc113] .group:last-child{padding-bottom:0}.VPMenu[data-v-b98bc113] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-b98bc113] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-b98bc113] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-b98bc113] .action{padding-left:24px}.VPFlyout[data-v-cf11d7a2]{position:relative}.VPFlyout[data-v-cf11d7a2]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-cf11d7a2]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-cf11d7a2]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-cf11d7a2]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-cf11d7a2]{color:var(--vp-c-brand-2)}.button[aria-expanded=false]+.menu[data-v-cf11d7a2]{opacity:0;visibility:hidden;transform:translateY(0)}.VPFlyout:hover .menu[data-v-cf11d7a2],.button[aria-expanded=true]+.menu[data-v-cf11d7a2]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-cf11d7a2]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-cf11d7a2]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-cf11d7a2]{margin-right:0;font-size:16px}.text-icon[data-v-cf11d7a2]{margin-left:4px;font-size:14px}.icon[data-v-cf11d7a2]{font-size:20px;transition:fill .25s}.menu[data-v-cf11d7a2]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-bd121fe5]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-bd121fe5]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-bd121fe5]>svg,.VPSocialLink[data-v-bd121fe5]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-7bc22406]{display:flex;justify-content:center}.VPNavBarExtra[data-v-bb2aa2f0]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-bb2aa2f0]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-bb2aa2f0]{display:none}}.trans-title[data-v-bb2aa2f0]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-bb2aa2f0],.item.social-links[data-v-bb2aa2f0]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-bb2aa2f0]{min-width:176px}.appearance-action[data-v-bb2aa2f0]{margin-right:-2px}.social-links-list[data-v-bb2aa2f0]{margin:-4px -8px}.VPNavBarHamburger[data-v-e5dd9c1c]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-e5dd9c1c]{display:none}}.container[data-v-e5dd9c1c]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-e5dd9c1c]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .middle[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .bottom[data-v-e5dd9c1c]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-e5dd9c1c],.middle[data-v-e5dd9c1c],.bottom[data-v-e5dd9c1c]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(0)}.middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-e56f3d57]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-e56f3d57],.VPNavBarMenuLink[data-v-e56f3d57]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-dc692963]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-dc692963]{display:flex}}/*! @docsearch/css 3.8.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 1px 0 rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 1px 1px 0 #0304094d;--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch-Button-Key--pressed{box-shadow:var(--docsearch-key-pressed-shadow);transform:translate3d(0,1px,0)}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button-Key--pressed{transform:none;box-shadow:none}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.DocSearch-Search-Icon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke-width='1.6' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' d='m14.386 14.386 4.088 4.088-4.088-4.088A7.533 7.533 0 1 1 3.733 3.733a7.533 7.533 0 0 1 10.653 10.653z'/%3E%3C/svg%3E")}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-0394ad82]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-0394ad82]{display:flex;align-items:center}}.title[data-v-1168a8e4]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-1168a8e4]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-1168a8e4]{border-bottom-color:var(--vp-c-divider)}}[data-v-1168a8e4] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-88af2de4]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-88af2de4]{display:flex;align-items:center}}.title[data-v-88af2de4]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-6aa21345]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-6aa21345]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-6aa21345]:not(.home){background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar[data-v-6aa21345]:not(.home){background-color:transparent}.VPNavBar[data-v-6aa21345]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-6aa21345]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-6aa21345]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-6aa21345]{padding:0}}.container[data-v-6aa21345]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-6aa21345],.container>.content[data-v-6aa21345]{pointer-events:none}.container[data-v-6aa21345] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-6aa21345]{max-width:100%}}.title[data-v-6aa21345]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-6aa21345]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-6aa21345]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-6aa21345]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-6aa21345]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-6aa21345]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-6aa21345]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.home.top) .content-body[data-v-6aa21345]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-6aa21345]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-6aa21345]{column-gap:.5rem}}.menu+.translations[data-v-6aa21345]:before,.menu+.appearance[data-v-6aa21345]:before,.menu+.social-links[data-v-6aa21345]:before,.translations+.appearance[data-v-6aa21345]:before,.appearance+.social-links[data-v-6aa21345]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-6aa21345]:before,.translations+.appearance[data-v-6aa21345]:before{margin-right:16px}.appearance+.social-links[data-v-6aa21345]:before{margin-left:16px}.social-links[data-v-6aa21345]{margin-right:-8px}.divider[data-v-6aa21345]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-6aa21345]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-6aa21345]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-6aa21345]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-6aa21345]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.home.top) .divider-line[data-v-6aa21345]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-6aa21345]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-b44890b2]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-b44890b2]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-df37e6dd]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-df37e6dd]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-3e9c20e4]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-3e9c20e4]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-8133b170]{display:block}.title[data-v-8133b170]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-b9ab8c58]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-b9ab8c58]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-b9ab8c58]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-b9ab8c58]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-b9ab8c58]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-b9ab8c58]{transform:rotate(45deg)}.button[data-v-b9ab8c58]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-b9ab8c58]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-b9ab8c58]{transition:transform .25s}.group[data-v-b9ab8c58]:first-child{padding-top:0}.group+.group[data-v-b9ab8c58],.group+.item[data-v-b9ab8c58]{padding-top:4px}.VPNavScreenTranslations[data-v-858fe1a4]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-858fe1a4]{height:auto}.title[data-v-858fe1a4]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-858fe1a4]{font-size:16px}.icon.lang[data-v-858fe1a4]{margin-right:8px}.icon.chevron[data-v-858fe1a4]{margin-left:4px}.list[data-v-858fe1a4]{padding:4px 0 0 24px}.link[data-v-858fe1a4]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-f2779853]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-f2779853],.VPNavScreen.fade-leave-active[data-v-f2779853]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-f2779853],.VPNavScreen.fade-leave-active .container[data-v-f2779853]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-f2779853],.VPNavScreen.fade-leave-to[data-v-f2779853]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-f2779853],.VPNavScreen.fade-leave-to .container[data-v-f2779853]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-f2779853]{display:none}}.container[data-v-f2779853]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-f2779853],.menu+.appearance[data-v-f2779853],.translations+.appearance[data-v-f2779853]{margin-top:24px}.menu+.social-links[data-v-f2779853]{margin-top:16px}.appearance+.social-links[data-v-f2779853]{margin-top:16px}.VPNav[data-v-ae24b3ad]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-ae24b3ad]{position:fixed}}.VPSidebarItem.level-0[data-v-b3fd67f8]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-b3fd67f8]{padding-bottom:10px}.item[data-v-b3fd67f8]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-b3fd67f8]{cursor:pointer}.indicator[data-v-b3fd67f8]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-b3fd67f8]{background-color:var(--vp-c-brand-1)}.link[data-v-b3fd67f8]{display:flex;align-items:center;flex-grow:1}.text[data-v-b3fd67f8]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-b3fd67f8]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-b3fd67f8],.VPSidebarItem.level-2 .text[data-v-b3fd67f8],.VPSidebarItem.level-3 .text[data-v-b3fd67f8],.VPSidebarItem.level-4 .text[data-v-b3fd67f8],.VPSidebarItem.level-5 .text[data-v-b3fd67f8]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-b3fd67f8]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-b3fd67f8]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-b3fd67f8]{color:var(--vp-c-brand-1)}.caret[data-v-b3fd67f8]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-b3fd67f8]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-b3fd67f8]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-b3fd67f8]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-b3fd67f8]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-b3fd67f8],.VPSidebarItem.level-2 .items[data-v-b3fd67f8],.VPSidebarItem.level-3 .items[data-v-b3fd67f8],.VPSidebarItem.level-4 .items[data-v-b3fd67f8],.VPSidebarItem.level-5 .items[data-v-b3fd67f8]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-b3fd67f8]{display:none}.no-transition[data-v-c40bc020] .caret-icon{transition:none}.group+.group[data-v-c40bc020]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-c40bc020]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-319d5ca6]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-319d5ca6]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-319d5ca6]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-319d5ca6]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-319d5ca6]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-319d5ca6]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-319d5ca6]{outline:0}.VPSkipLink[data-v-0b0ada53]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-0b0ada53]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-0b0ada53]{top:14px;left:16px}}.Layout[data-v-5d98c3a5]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-3d121b4a]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPHomeSponsors[data-v-3d121b4a]{margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{margin:128px 0}}.VPHomeSponsors[data-v-3d121b4a]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 64px}}.container[data-v-3d121b4a]{margin:0 auto;max-width:1152px}.love[data-v-3d121b4a]{margin:0 auto;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-3d121b4a]{display:inline-block}.message[data-v-3d121b4a]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-3d121b4a]{padding-top:32px}.action[data-v-3d121b4a]{padding-top:40px;text-align:center}.VPTeamMembersItem[data-v-f3fa364a]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-f3fa364a]{padding:32px}.VPTeamMembersItem.small .data[data-v-f3fa364a]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-f3fa364a]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-f3fa364a]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-f3fa364a]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-f3fa364a]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-f3fa364a]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-f3fa364a]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-f3fa364a]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-f3fa364a]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-f3fa364a]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-f3fa364a]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-f3fa364a]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-f3fa364a]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-f3fa364a]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-f3fa364a]{text-align:center}.avatar[data-v-f3fa364a]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-f3fa364a]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-f3fa364a]{margin:0;font-weight:600}.affiliation[data-v-f3fa364a]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-f3fa364a]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-f3fa364a]:hover{color:var(--vp-c-brand-1)}.desc[data-v-f3fa364a]{margin:0 auto}.desc[data-v-f3fa364a] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-f3fa364a]{display:flex;justify-content:center;height:56px}.sp-link[data-v-f3fa364a]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-f3fa364a]:hover,.sp .sp-link.link[data-v-f3fa364a]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-f3fa364a]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-6cb0dbc4]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-6cb0dbc4]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-6cb0dbc4]{max-width:876px}.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-6cb0dbc4]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-6cb0dbc4]{max-width:760px}.container[data-v-6cb0dbc4]{display:grid;gap:24px;margin:0 auto;max-width:1152px}.VPTeamPage[data-v-7c57f839]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-7c57f839]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-7c57f839-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-7c57f839-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:96px}}.VPTeamMembers[data-v-7c57f839-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 64px}}.VPTeamPageSection[data-v-b1a88750]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-b1a88750]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-b1a88750]{padding:0 64px}}.title[data-v-b1a88750]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-b1a88750]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-b1a88750]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-b1a88750]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-b1a88750]{padding-top:40px}.VPTeamPageTitle[data-v-bf2cbdac]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:80px 64px 48px}}.title[data-v-bf2cbdac]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-bf2cbdac]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-bf2cbdac]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-bf2cbdac]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}} diff --git a/assets/style.e150f059.css b/assets/style.e150f059.css deleted file mode 100644 index 91739c5232..0000000000 --- a/assets/style.e150f059.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic.5f2c6c8c.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-cyrillic-ext.e75737ce.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek.d5a6d92a.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-greek-ext.ab0619bc.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin.2ed14f66.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-latin-ext.0030eebd.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:normal;font-named-instance:"Regular";src:url(/assets/inter-roman-vietnamese.14ce25a6.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic.ea42a392.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-cyrillic-ext.33bd5a8e.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek.8f4463c4.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-greek-ext.4fbe9427.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin.bd3b6f56.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-latin-ext.bd8920cc.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter var;font-weight:100 900;font-display:swap;font-style:italic;font-named-instance:"Italic";src:url(/assets/inter-italic-vietnamese.6ce511fb.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Chinese Quotes;src:local("PingFang SC Regular"),local("PingFang SC"),local("SimHei"),local("Source Han Sans SC");unicode-range:U+2018,U+2019,U+201C,U+201D}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-gray: #8e8e93;--vp-c-text-light-1: rgba(60, 60, 67);--vp-c-text-light-2: rgba(60, 60, 67, .75);--vp-c-text-light-3: rgba(60, 60, 67, .33);--vp-c-text-dark-1: rgba(255, 255, 245, .86);--vp-c-text-dark-2: rgba(235, 235, 245, .6);--vp-c-text-dark-3: rgba(235, 235, 245, .38);--vp-c-green: #10b981;--vp-c-green-light: #34d399;--vp-c-green-lighter: #6ee7b7;--vp-c-green-dark: #059669;--vp-c-green-darker: #047857;--vp-c-green-dimm-1: rgba(16, 185, 129, .05);--vp-c-green-dimm-2: rgba(16, 185, 129, .2);--vp-c-green-dimm-3: rgba(16, 185, 129, .5);--vp-c-yellow: #d97706;--vp-c-yellow-light: #f59e0b;--vp-c-yellow-lighter: #fbbf24;--vp-c-yellow-dark: #b45309;--vp-c-yellow-darker: #92400e;--vp-c-yellow-dimm-1: rgba(234, 179, 8, .05);--vp-c-yellow-dimm-2: rgba(234, 179, 8, .2);--vp-c-yellow-dimm-3: rgba(234, 179, 8, .5);--vp-c-red: #f43f5e;--vp-c-red-light: #fb7185;--vp-c-red-lighter: #fda4af;--vp-c-red-dark: #e11d48;--vp-c-red-darker: #be123c;--vp-c-red-dimm-1: rgba(244, 63, 94, .05);--vp-c-red-dimm-2: rgba(244, 63, 94, .2);--vp-c-red-dimm-3: rgba(244, 63, 94, .5);--vp-c-sponsor: #db2777}:root{--vp-c-bg: #ffffff;--vp-c-bg-elv: #ffffff;--vp-c-bg-elv-up: #ffffff;--vp-c-bg-elv-down: #f6f6f7;--vp-c-bg-elv-mute: #f6f6f7;--vp-c-bg-soft: #f6f6f7;--vp-c-bg-soft-up: #f9f9fa;--vp-c-bg-soft-down: #e3e3e5;--vp-c-bg-soft-mute: #e3e3e5;--vp-c-bg-alt: #f6f6f7;--vp-c-border: rgba(60, 60, 67, .29);--vp-c-divider: rgba(60, 60, 67, .12);--vp-c-gutter: rgba(60, 60, 67, .12);--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white);--vp-c-text-1: var(--vp-c-text-light-1);--vp-c-text-2: var(--vp-c-text-light-2);--vp-c-text-3: var(--vp-c-text-light-3);--vp-c-text-inverse-1: var(--vp-c-text-dark-1);--vp-c-text-inverse-2: var(--vp-c-text-dark-2);--vp-c-text-inverse-3: var(--vp-c-text-dark-3);--vp-c-text-code: #476582;--vp-c-brand: var(--vp-c-green);--vp-c-brand-light: var(--vp-c-green-light);--vp-c-brand-lighter: var(--vp-c-green-lighter);--vp-c-brand-dark: var(--vp-c-green-dark);--vp-c-brand-darker: var(--vp-c-green-darker);--vp-c-mute: #f6f6f7;--vp-c-mute-light: #f9f9fc;--vp-c-mute-lighter: #ffffff;--vp-c-mute-dark: #e3e3e5;--vp-c-mute-darker: #d7d7d9}.dark{--vp-c-bg: #1e1e20;--vp-c-bg-elv: #252529;--vp-c-bg-elv-up: #313136;--vp-c-bg-elv-down: #1e1e20;--vp-c-bg-elv-mute: #313136;--vp-c-bg-soft: #252529;--vp-c-bg-soft-up: #313136;--vp-c-bg-soft-down: #1e1e20;--vp-c-bg-soft-mute: #313136;--vp-c-bg-alt: #161618;--vp-c-border: rgba(82, 82, 89, .68);--vp-c-divider: rgba(82, 82, 89, .32);--vp-c-gutter: #000000;--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black);--vp-c-text-1: var(--vp-c-text-dark-1);--vp-c-text-2: var(--vp-c-text-dark-2);--vp-c-text-3: var(--vp-c-text-dark-3);--vp-c-text-inverse-1: var(--vp-c-text-light-1);--vp-c-text-inverse-2: var(--vp-c-text-light-2);--vp-c-text-inverse-3: var(--vp-c-text-light-3);--vp-c-text-code: #c9def1;--vp-c-mute: #313136;--vp-c-mute-light: #3a3a3c;--vp-c-mute-lighter: #505053;--vp-c-mute-dark: #2c2c30;--vp-c-mute-darker: #252529}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-local-nav: 10;--vp-z-index-nav: 20;--vp-z-index-layout-top: 30;--vp-z-index-backdrop: 40;--vp-z-index-sidebar: 50;--vp-z-index-footer: 60}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E")}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-c-code-dimm: var(--vp-c-text-dark-3);--vp-code-block-color: var(--vp-c-text-dark-1);--vp-code-block-bg: #292b30;--vp-code-block-bg-light: #1e1e20;--vp-code-block-divider-color: #000000;--vp-code-line-highlight-color: rgba(0, 0, 0, .5);--vp-code-line-number-color: var(--vp-c-code-dimm);--vp-code-line-diff-add-color: var(--vp-c-green-dimm-2);--vp-code-line-diff-add-symbol-color: var(--vp-c-green);--vp-code-line-diff-remove-color: var(--vp-c-red-dimm-2);--vp-code-line-diff-remove-symbol-color: var(--vp-c-red);--vp-code-line-warning-color: var(--vp-c-yellow-dimm-2);--vp-code-line-error-color: var(--vp-c-red-dimm-2);--vp-code-copy-code-border-color: transparent;--vp-code-copy-code-bg: var(--vp-code-block-bg-light);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-code-block-bg-light);--vp-code-copy-code-active-text: var(--vp-c-text-dark-2);--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-dark-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-dark-1);--vp-code-tab-active-text-color: var(--vp-c-text-dark-1);--vp-code-tab-active-bar-color: var(--vp-c-brand)}.dark{--vp-code-block-bg: #161618}:root:not(.dark) .vp-adaptive-theme{--vp-c-code-dimm: var(--vp-c-text-2);--vp-code-block-color: var(--vp-c-text-1);--vp-code-block-bg: #f8f8f8;--vp-code-block-divider-color: var(--vp-c-divider);--vp-code-line-highlight-color: #ececec;--vp-code-line-number-color: var(--vp-c-code-dimm);--vp-code-copy-code-bg: #e2e2e2;--vp-code-copy-code-hover-bg: #dcdcdc;--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-tab-divider: var(--vp-c-divider);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1)}:root{--vp-button-brand-border: var(--vp-c-brand-lighter);--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand);--vp-button-brand-hover-border: var(--vp-c-brand-lighter);--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-dark);--vp-button-brand-active-border: var(--vp-c-brand-lighter);--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-darker);--vp-button-alt-border: var(--vp-c-border);--vp-button-alt-text: var(--vp-c-neutral);--vp-button-alt-bg: var(--vp-c-mute);--vp-button-alt-hover-border: var(--vp-c-border);--vp-button-alt-hover-text: var(--vp-c-neutral);--vp-button-alt-hover-bg: var(--vp-c-mute-dark);--vp-button-alt-active-border: var(--vp-c-border);--vp-button-alt-active-text: var(--vp-c-neutral);--vp-button-alt-active-bg: var(--vp-c-mute-darker);--vp-button-sponsor-border: var(--vp-c-gray-light-3);--vp-button-sponsor-text: var(--vp-c-text-light-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}.dark{--vp-button-sponsor-border: var(--vp-c-gray-dark-1);--vp-button-sponsor-text: var(--vp-c-text-dark-2)}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: var(--vp-c-border);--vp-custom-block-info-text: var(--vp-c-text-2);--vp-custom-block-info-bg: var(--vp-c-bg-soft-up);--vp-custom-block-info-code-bg: var(--vp-c-bg-soft);--vp-custom-block-tip-border: var(--vp-c-green);--vp-custom-block-tip-text: var(--vp-c-green-dark);--vp-custom-block-tip-bg: var(--vp-c-bg-soft-up);--vp-custom-block-tip-code-bg: var(--vp-c-bg-soft);--vp-custom-block-warning-border: var(--vp-c-yellow);--vp-custom-block-warning-text: var(--vp-c-yellow);--vp-custom-block-warning-bg: var(--vp-c-bg-soft-up);--vp-custom-block-warning-code-bg: var(--vp-c-bg-soft);--vp-custom-block-danger-border: var(--vp-c-red);--vp-custom-block-danger-text: var(--vp-c-red);--vp-custom-block-danger-bg: var(--vp-c-bg-soft-up);--vp-custom-block-danger-code-bg: var(--vp-c-bg-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-details-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-hover-border-color: var(--vp-c-gray);--vp-input-switch-bg-color: var(--vp-c-mute)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: var(--vp-c-border);--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-bg-soft-up);--vp-badge-tip-border: var(--vp-c-green-dark);--vp-badge-tip-text: var(--vp-c-green);--vp-badge-tip-bg: var(--vp-c-green-dimm-1);--vp-badge-warning-border: var(--vp-c-yellow-dark);--vp-badge-warning-text: var(--vp-c-yellow);--vp-badge-warning-bg: var(--vp-c-yellow-dimm-1);--vp-badge-danger-border: var(--vp-c-red-dark);--vp-badge-danger-text: var(--vp-c-red);--vp-badge-danger-bg: var(--vp-c-red-dimm-1)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand);--vp-local-search-highlight-bg: var(--vp-c-green-lighter);--vp-local-search-highlight-text: var(--vp-c-black)}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);direction:ltr;font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600}.custom-block a:hover{text-decoration:underline}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.dark .vp-code-light{display:none}html:not(.dark) .vp-code-dark{display:none}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:absolute;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:1px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-]{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active{display:block}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand);text-decoration-style:dotted;transition:color .25s}.vp-doc a:hover{text-decoration:underline}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block a{color:inherit;font-weight:600}.vp-doc .custom-block a:hover{text-decoration:underline}.vp-doc .custom-block code{font-size:var(--vp-custom-block-code-font-size);font-weight:700;color:inherit}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;color:var(--vp-c-text-code);background-color:var(--vp-c-mute);transition:color .5s,background-color .5s}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc a>code{color:var(--vp-c-brand);transition:color .25s}.vp-doc a:hover>code{color:var(--vp-c-brand-dark)}.vp-doc div[class*=language-]{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-]{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;left:-65px;display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;width:64px;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:"Copied"}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-c-code-dimm);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin-bottom:4px;text-align:center;letter-spacing:1px;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-bg-soft-down)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge[data-v-f026a7e7]{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:10px;padding:0 8px;line-height:18px;font-size:12px;font-weight:600;transform:translateY(-2px)}h1 .VPBadge[data-v-f026a7e7],h2 .VPBadge[data-v-f026a7e7],h3 .VPBadge[data-v-f026a7e7],h4 .VPBadge[data-v-f026a7e7],h5 .VPBadge[data-v-f026a7e7],h6 .VPBadge[data-v-f026a7e7]{vertical-align:text-top}h2 .VPBadge[data-v-f026a7e7]{border-radius:11px;line-height:20px}.VPBadge.info[data-v-f026a7e7]{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip[data-v-f026a7e7]{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning[data-v-f026a7e7]{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger[data-v-f026a7e7]{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-c79a1216]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-c79a1216],.VPBackdrop.fade-leave-to[data-v-c79a1216]{opacity:0}.VPBackdrop.fade-leave-active[data-v-c79a1216]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-c79a1216]{display:none}}.NotFound[data-v-c70503b8]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-c70503b8]{padding:96px 32px 168px}}.code[data-v-c70503b8]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-c70503b8]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-c70503b8]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-c70503b8]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-c70503b8]{padding-top:20px}.link[data-v-c70503b8]{display:inline-block;border:1px solid var(--vp-c-brand);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:border-color .25s,color .25s}.link[data-v-c70503b8]:hover{border-color:var(--vp-c-brand-dark);color:var(--vp-c-brand-dark)}.root[data-v-b0ff2abe]{position:relative;z-index:1}.nested[data-v-b0ff2abe]{padding-left:13px}.outline-link[data-v-b0ff2abe]{display:block;line-height:28px;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s;font-weight:500}.outline-link[data-v-b0ff2abe]:hover,.outline-link.active[data-v-b0ff2abe]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-b0ff2abe]{padding-left:13px}.VPDocAsideOutline[data-v-ff0f39c8]{display:none}.VPDocAsideOutline.has-outline[data-v-ff0f39c8]{display:block}.content[data-v-ff0f39c8]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-ff0f39c8]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:1px;height:18px;background-color:var(--vp-c-brand);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-ff0f39c8]{letter-spacing:.4px;line-height:28px;font-size:13px;font-weight:600}.VPDocAside[data-v-3f215769]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-3f215769]{flex-grow:1}.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-3f215769] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-149a99df]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-149a99df]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-37656e44]{margin-top:64px}.edit-info[data-v-37656e44]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-37656e44]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-37656e44]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:color .25s}.edit-link-button[data-v-37656e44]:hover{color:var(--vp-c-brand-dark)}.edit-link-icon[data-v-37656e44]{margin-right:8px;width:14px;height:14px;fill:currentColor}.prev-next[data-v-37656e44]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-37656e44]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-37656e44]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-37656e44]:hover{border-color:var(--vp-c-brand)}.pager-link.next[data-v-37656e44]{margin-left:auto;text-align:right}.desc[data-v-37656e44]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-37656e44]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand);transition:color .25s}.VPDocOutlineDropdown[data-v-2edece88]{margin-bottom:42px}.VPDocOutlineDropdown button[data-v-2edece88]{display:block;font-size:14px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;border:1px solid var(--vp-c-border);padding:4px 12px;border-radius:8px}.VPDocOutlineDropdown button[data-v-2edece88]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPDocOutlineDropdown button.open[data-v-2edece88]{color:var(--vp-c-text-1)}.icon[data-v-2edece88]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-2edece88] .outline-link{font-size:13px}.open>.icon[data-v-2edece88]{transform:rotate(90deg)}.items[data-v-2edece88]{margin-top:10px;border-left:1px solid var(--vp-c-divider)}.VPDoc[data-v-6b87e69f]{padding:32px 24px 96px;width:100%}.VPDoc .VPDocOutlineDropdown[data-v-6b87e69f]{display:none}@media (min-width: 960px) and (max-width: 1279px){.VPDoc .VPDocOutlineDropdown[data-v-6b87e69f]{display:block}}@media (min-width: 768px){.VPDoc[data-v-6b87e69f]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-6b87e69f]{padding:32px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-6b87e69f]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-6b87e69f]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-6b87e69f]{display:flex;justify-content:center}.VPDoc .aside[data-v-6b87e69f]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-6b87e69f]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-6b87e69f]{max-width:1104px}}.container[data-v-6b87e69f]{margin:0 auto;width:100%}.aside[data-v-6b87e69f]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-6b87e69f]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-6b87e69f]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 32px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-6b87e69f]::-webkit-scrollbar{display:none}.aside-curtain[data-v-6b87e69f]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-6b87e69f]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 32px));padding-bottom:32px}.content[data-v-6b87e69f]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-6b87e69f]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-6b87e69f]{order:1;margin:0;min-width:640px}}.content-container[data-v-6b87e69f]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-6b87e69f]{max-width:688px}.external-link-icon-enabled[data-v-6b87e69f] :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.VPButton[data-v-567ba664]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-567ba664]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-567ba664]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-567ba664]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-567ba664]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-567ba664]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-567ba664]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-567ba664]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-567ba664]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-567ba664]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-567ba664]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-567ba664]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-567ba664]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-6db2186b]{display:none}.dark .VPImage.light[data-v-6db2186b]{display:none}.VPHero[data-v-da5d1713]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-da5d1713]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-da5d1713]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-da5d1713]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-da5d1713]{flex-direction:row}}.main[data-v-da5d1713]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-da5d1713]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-da5d1713]{text-align:left}}@media (min-width: 960px){.main[data-v-da5d1713]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-da5d1713]{max-width:592px}}.name[data-v-da5d1713],.text[data-v-da5d1713]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-da5d1713],.VPHero.has-image .text[data-v-da5d1713]{margin:0 auto}.name[data-v-da5d1713]{color:var(--vp-home-hero-name-color)}.clip[data-v-da5d1713]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-da5d1713],.text[data-v-da5d1713]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-da5d1713],.text[data-v-da5d1713]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-da5d1713],.VPHero.has-image .text[data-v-da5d1713]{margin:0}}.tagline[data-v-da5d1713]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-da5d1713]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-da5d1713]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-da5d1713]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-da5d1713]{margin:0}}.actions[data-v-da5d1713]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-da5d1713]{justify-content:center}@media (min-width: 640px){.actions[data-v-da5d1713]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-da5d1713]{justify-content:flex-start}}.action[data-v-da5d1713]{flex-shrink:0;padding:6px}.image[data-v-da5d1713]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-da5d1713]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-da5d1713]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-da5d1713]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-da5d1713]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-da5d1713]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-da5d1713]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-da5d1713]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-da5d1713]{width:320px;height:320px}}[data-v-da5d1713] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-da5d1713] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-da5d1713] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-f7bdba60]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-f7bdba60]:hover{border-color:var(--vp-c-brand);background-color:var(--vp-c-bg-soft-up)}.box[data-v-f7bdba60]{display:flex;flex-direction:column;padding:24px;height:100%}.VPFeature[data-v-f7bdba60] .VPImage{width:48px;height:48px;margin-bottom:20px}.icon[data-v-f7bdba60]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-bg-soft-down);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-f7bdba60]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-f7bdba60]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-f7bdba60]{padding-top:8px}.link-text-value[data-v-f7bdba60]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand)}.link-text-icon[data-v-f7bdba60]{display:inline-block;margin-left:6px;width:14px;height:14px;fill:currentColor}.VPFeatures[data-v-39646fad]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-39646fad]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-39646fad]{padding:0 64px}}.container[data-v-39646fad]{margin:0 auto;max-width:1152px}.items[data-v-39646fad]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-39646fad]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-39646fad],.item.grid-4[data-v-39646fad],.item.grid-6[data-v-39646fad]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-39646fad],.item.grid-4[data-v-39646fad]{width:50%}.item.grid-3[data-v-39646fad],.item.grid-6[data-v-39646fad]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-39646fad]{width:25%}}.VPHome[data-v-d82743a8]{padding-bottom:96px}.VPHome[data-v-d82743a8] .VPHomeSponsors{margin-top:112px;margin-bottom:-128px}@media (min-width: 768px){.VPHome[data-v-d82743a8]{padding-bottom:128px}}.VPContent[data-v-3107c4ee]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-3107c4ee]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-3107c4ee]{margin:0}@media (min-width: 960px){.VPContent[data-v-3107c4ee]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-3107c4ee]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-3107c4ee]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e03eb2e1]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e03eb2e1]{display:none}@media (min-width: 768px){.VPFooter[data-v-e03eb2e1]{padding:32px}}.container[data-v-e03eb2e1]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e03eb2e1],.copyright[data-v-e03eb2e1]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-d5bb9d56]{padding:12px 20px 11px}.VPLocalNavOutlineDropdown button[data-v-d5bb9d56]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-d5bb9d56]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-d5bb9d56]{color:var(--vp-c-text-1)}.icon[data-v-d5bb9d56]{display:inline-block;vertical-align:middle;margin-left:2px;width:14px;height:14px;fill:currentColor}[data-v-d5bb9d56] .outline-link{font-size:14px;padding:2px 0}.open>.icon[data-v-d5bb9d56]{transform:rotate(90deg)}.items[data-v-d5bb9d56]{position:absolute;left:20px;right:20px;top:64px;background-color:var(--vp-local-nav-bg-color);padding:4px 10px 16px;border:1px solid var(--vp-c-divider);border-radius:8px;max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}.top-link[data-v-d5bb9d56]{display:block;color:var(--vp-c-brand);font-size:13px;font-weight:500;padding:6px 0;margin:0 13px 10px;border-bottom:1px solid var(--vp-c-divider)}.flyout-enter-active[data-v-d5bb9d56]{transition:all .2s ease-out}.flyout-leave-active[data-v-d5bb9d56]{transition:all .15s ease-in}.flyout-enter-from[data-v-d5bb9d56],.flyout-leave-to[data-v-d5bb9d56]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-5cfd5582]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--vp-c-gutter);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-5cfd5582]{position:fixed}.VPLocalNav.reached-top[data-v-5cfd5582]{border-top-color:transparent}@media (min-width: 960px){.VPLocalNav[data-v-5cfd5582]{display:none}}.menu[data-v-5cfd5582]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-5cfd5582]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-5cfd5582]{padding:0 32px}}.menu-icon[data-v-5cfd5582]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPOutlineDropdown[data-v-5cfd5582]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-5cfd5582]{padding:12px 32px 11px}}.VPSwitch[data-v-f3c41672]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s}.VPSwitch[data-v-f3c41672]:hover{border-color:var(--vp-input-hover-border-color)}.check[data-v-f3c41672]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s}.icon[data-v-f3c41672]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-f3c41672] svg{position:absolute;top:3px;left:3px;width:12px;height:12px;fill:var(--vp-c-text-2)}.dark .icon[data-v-f3c41672] svg{fill:var(--vp-c-text-1);transition:opacity .25s}.sun[data-v-82b282f1]{opacity:1}.moon[data-v-82b282f1],.dark .sun[data-v-82b282f1]{opacity:0}.dark .moon[data-v-82b282f1]{opacity:1}.dark .VPSwitchAppearance[data-v-82b282f1] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-f6a63727]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-f6a63727]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-2f2cfafc]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-2f2cfafc]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-2f2cfafc]:hover{color:var(--vp-c-brand);background-color:var(--vp-c-bg-elv-mute)}.link.active[data-v-2f2cfafc]{color:var(--vp-c-brand)}.VPMenuGroup[data-v-69e747b5]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-69e747b5]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-69e747b5]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-69e747b5]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-e7ea1737]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-e7ea1737] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-e7ea1737] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-e7ea1737] .group:last-child{padding-bottom:0}.VPMenu[data-v-e7ea1737] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-e7ea1737] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-e7ea1737] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-e7ea1737] .action{padding-left:24px}.VPFlyout[data-v-764effdf]{position:relative}.VPFlyout[data-v-764effdf]:hover{color:var(--vp-c-brand);transition:color .25s}.VPFlyout:hover .text[data-v-764effdf]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-764effdf]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-764effdf]{color:var(--vp-c-brand)}.VPFlyout.active:hover .text[data-v-764effdf]{color:var(--vp-c-brand-dark)}.VPFlyout:hover .menu[data-v-764effdf],.button[aria-expanded=true]+.menu[data-v-764effdf]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-764effdf]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-764effdf]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-764effdf]{margin-right:0;width:16px;height:16px;fill:currentColor}.text-icon[data-v-764effdf]{margin-left:4px;width:14px;height:14px;fill:currentColor}.icon[data-v-764effdf]{width:20px;height:20px;fill:currentColor;transition:fill .25s}.menu[data-v-764effdf]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-f80f8133]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-f80f8133]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-f80f8133]>svg{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-7bc22406]{display:flex;justify-content:center}.VPNavBarExtra[data-v-40855f84]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-40855f84]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-40855f84]{display:none}}.trans-title[data-v-40855f84]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-40855f84],.item.social-links[data-v-40855f84]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-40855f84]{min-width:176px}.appearance-action[data-v-40855f84]{margin-right:-2px}.social-links-list[data-v-40855f84]{margin:-4px -8px}.VPNavBarHamburger[data-v-e5dd9c1c]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-e5dd9c1c]{display:none}}.container[data-v-e5dd9c1c]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-e5dd9c1c]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .middle[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .bottom[data-v-e5dd9c1c]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-e5dd9c1c],.middle[data-v-e5dd9c1c],.bottom[data-v-e5dd9c1c]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(0)}.middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-5e623618]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-5e623618],.VPNavBarMenuLink[data-v-5e623618]:hover{color:var(--vp-c-brand)}.VPNavBarMenu[data-v-7f418b0f]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-7f418b0f]{display:flex}}/*! @docsearch/css 3.5.1 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.DocSearch{--docsearch-primary-color: var(--vp-c-brand);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark .DocSearch{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-bg-soft-mute);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:1px;letter-spacing:-12px;color:transparent}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:var(--vp-meta-key);font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-bg-soft-mute)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-0394ad82]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-0394ad82]{display:flex;align-items:center}}.title[data-v-8bbac535]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-8bbac535]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-8bbac535]{border-bottom-color:var(--vp-c-divider)}}[data-v-8bbac535] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-74abcbb9]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-74abcbb9]{display:flex;align-items:center}}.title[data-v-74abcbb9]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-faa4ef78]{position:relative;border-bottom:1px solid transparent;padding:0 8px 0 24px;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap}@media (min-width: 768px){.VPNavBar[data-v-faa4ef78]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar[data-v-faa4ef78]{padding:0}.VPNavBar.fill[data-v-faa4ef78]:not(.has-sidebar){border-bottom-color:var(--vp-c-gutter);background-color:var(--vp-nav-bg-color)}}.container[data-v-faa4ef78]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-faa4ef78],.container>.content[data-v-faa4ef78]{pointer-events:none}.container[data-v-faa4ef78] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-faa4ef78]{max-width:100%}}.title[data-v-faa4ef78]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-faa4ef78]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-faa4ef78]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-faa4ef78]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-faa4ef78]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-faa4ef78]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-faa4ef78]{display:flex;justify-content:flex-end;align-items:center;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .content-body[data-v-faa4ef78],.VPNavBar.fill .content-body[data-v-faa4ef78]{position:relative;background-color:var(--vp-nav-bg-color)}}@media (max-width: 768px){.content-body[data-v-faa4ef78]{column-gap:.5rem}}.menu+.translations[data-v-faa4ef78]:before,.menu+.appearance[data-v-faa4ef78]:before,.menu+.social-links[data-v-faa4ef78]:before,.translations+.appearance[data-v-faa4ef78]:before,.appearance+.social-links[data-v-faa4ef78]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-faa4ef78]:before,.translations+.appearance[data-v-faa4ef78]:before{margin-right:16px}.appearance+.social-links[data-v-faa4ef78]:before{margin-left:16px}.social-links[data-v-faa4ef78]{margin-right:-8px}@media (min-width: 960px){.VPNavBar.has-sidebar .curtain[data-v-faa4ef78]{position:absolute;right:0;bottom:-31px;width:calc(100% - var(--vp-sidebar-width));height:32px}.VPNavBar.has-sidebar .curtain[data-v-faa4ef78]:before{display:block;width:100%;height:32px;background:linear-gradient(var(--vp-c-bg),transparent 70%);content:""}}@media (min-width: 1440px){.VPNavBar.has-sidebar .curtain[data-v-faa4ef78]{width:calc(100% - ((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width)))}}.VPNavScreenMenuLink[data-v-30be0acb]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-30be0acb]:hover{color:var(--vp-c-brand)}.VPNavScreenMenuGroupLink[data-v-6656c42a]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-6656c42a]:hover{color:var(--vp-c-brand)}.VPNavScreenMenuGroupSection[data-v-8133b170]{display:block}.title[data-v-8133b170]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-338a1689]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-338a1689]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-338a1689]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-338a1689]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-338a1689]{padding-bottom:6px;color:var(--vp-c-brand)}.VPNavScreenMenuGroup.open .button-icon[data-v-338a1689]{transform:rotate(45deg)}.button[data-v-338a1689]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-338a1689]:hover{color:var(--vp-c-brand)}.button-icon[data-v-338a1689]{width:14px;height:14px;fill:var(--vp-c-text-2);transition:fill .5s,transform .25s}.group[data-v-338a1689]:first-child{padding-top:0}.group+.group[data-v-338a1689],.group+.item[data-v-338a1689]{padding-top:4px}.VPNavScreenAppearance[data-v-add8f686]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-add8f686]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenTranslations[data-v-d72aa483]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-d72aa483]{height:auto}.title[data-v-d72aa483]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-d72aa483]{width:16px;height:16px;fill:currentColor}.icon.lang[data-v-d72aa483]{margin-right:8px}.icon.chevron[data-v-d72aa483]{margin-left:4px}.list[data-v-d72aa483]{padding:4px 0 0 24px}.link[data-v-d72aa483]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-69fcc70f]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-69fcc70f],.VPNavScreen.fade-leave-active[data-v-69fcc70f]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-69fcc70f],.VPNavScreen.fade-leave-active .container[data-v-69fcc70f]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-69fcc70f],.VPNavScreen.fade-leave-to[data-v-69fcc70f]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-69fcc70f],.VPNavScreen.fade-leave-to .container[data-v-69fcc70f]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-69fcc70f]{display:none}}.container[data-v-69fcc70f]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-69fcc70f],.menu+.appearance[data-v-69fcc70f],.translations+.appearance[data-v-69fcc70f]{margin-top:24px}.menu+.social-links[data-v-69fcc70f]{margin-top:16px}.appearance+.social-links[data-v-69fcc70f]{margin-top:16px}.VPNav[data-v-7e5bc4a5]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-7e5bc4a5]{position:fixed}}.VPSidebarItem.level-0[data-v-4fbabd82]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-4fbabd82]{padding-bottom:10px}.item[data-v-4fbabd82]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-4fbabd82]{cursor:pointer}.indicator[data-v-4fbabd82]{position:absolute;top:6px;bottom:6px;left:-17px;width:1px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-4fbabd82],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-4fbabd82],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-4fbabd82],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-4fbabd82]{background-color:var(--vp-c-brand)}.link[data-v-4fbabd82]{display:flex;align-items:center;flex-grow:1}.text[data-v-4fbabd82]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-4fbabd82]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-4fbabd82],.VPSidebarItem.level-2 .text[data-v-4fbabd82],.VPSidebarItem.level-3 .text[data-v-4fbabd82],.VPSidebarItem.level-4 .text[data-v-4fbabd82],.VPSidebarItem.level-5 .text[data-v-4fbabd82]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-4fbabd82],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-4fbabd82],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-4fbabd82],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-4fbabd82],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-4fbabd82],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-4fbabd82]{color:var(--vp-c-brand)}.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-4fbabd82],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-4fbabd82],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-4fbabd82],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-4fbabd82],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-4fbabd82],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-4fbabd82]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-4fbabd82],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-4fbabd82],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-4fbabd82],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-4fbabd82],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-4fbabd82],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-4fbabd82]{color:var(--vp-c-brand)}.caret[data-v-4fbabd82]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-4fbabd82]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-4fbabd82]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-4fbabd82]{width:18px;height:18px;fill:currentColor;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-4fbabd82]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-4fbabd82],.VPSidebarItem.level-2 .items[data-v-4fbabd82],.VPSidebarItem.level-3 .items[data-v-4fbabd82],.VPSidebarItem.level-4 .items[data-v-4fbabd82],.VPSidebarItem.level-5 .items[data-v-4fbabd82]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-4fbabd82]{display:none}.VPSidebar[data-v-845b8fc6]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-845b8fc6]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-845b8fc6]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-845b8fc6]{z-index:1;padding-top:var(--vp-nav-height);padding-bottom:128px;width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-845b8fc6]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-845b8fc6]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-845b8fc6]{outline:0}.group+.group[data-v-845b8fc6]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-845b8fc6]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-ae3e3f51]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-ae3e3f51]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-ae3e3f51]{top:14px;left:16px}}.Layout[data-v-255ec12d]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-3c6e61c2]{border-top:1px solid var(--vp-c-gutter);padding:88px 24px 96px;background-color:var(--vp-c-bg)}.container[data-v-3c6e61c2]{margin:0 auto;max-width:1152px}.love[data-v-3c6e61c2]{margin:0 auto;width:28px;height:28px;color:var(--vp-c-text-3)}.icon[data-v-3c6e61c2]{width:28px;height:28px;fill:currentColor}.message[data-v-3c6e61c2]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-3c6e61c2]{padding-top:32px}.action[data-v-3c6e61c2]{padding-top:40px;text-align:center}.VPTeamPage[data-v-10b00018]{padding-bottom:96px}@media (min-width: 768px){.VPTeamPage[data-v-10b00018]{padding-bottom:128px}}.VPTeamPageSection+.VPTeamPageSection[data-v-10b00018-s],.VPTeamMembers+.VPTeamPageSection[data-v-10b00018-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-10b00018-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-10b00018-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-10b00018-s],.VPTeamMembers+.VPTeamPageSection[data-v-10b00018-s]{margin-top:96px}}.VPTeamMembers[data-v-10b00018-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-10b00018-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-10b00018-s]{padding:0 64px}}.VPTeamPageTitle[data-v-bf2cbdac]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:80px 64px 48px}}.title[data-v-bf2cbdac]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-bf2cbdac]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-bf2cbdac]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-bf2cbdac]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-b1a88750]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-b1a88750]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-b1a88750]{padding:0 64px}}.title[data-v-b1a88750]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-b1a88750]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-b1a88750]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-b1a88750]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-b1a88750]{padding-top:40px}.VPTeamMembersItem[data-v-a3462077]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-a3462077]{padding:32px}.VPTeamMembersItem.small .data[data-v-a3462077]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-a3462077]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-a3462077]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-a3462077]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-a3462077]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-a3462077]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-a3462077]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-a3462077]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-a3462077]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-a3462077]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-a3462077]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-a3462077]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-a3462077]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-a3462077]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-a3462077]{text-align:center}.avatar[data-v-a3462077]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-a3462077]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-a3462077]{margin:0;font-weight:600}.affiliation[data-v-a3462077]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-a3462077]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-a3462077]:hover{color:var(--vp-c-brand)}.desc[data-v-a3462077]{margin:0 auto}.desc[data-v-a3462077] a{font-weight:500;color:var(--vp-c-brand);text-decoration-style:dotted;transition:color .25s}.links[data-v-a3462077]{display:flex;justify-content:center;height:56px}.sp-link[data-v-a3462077]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-a3462077]:hover,.sp .sp-link.link[data-v-a3462077]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-a3462077]{margin-right:8px;width:16px;height:16px;fill:currentColor}.VPTeamMembers.small .container[data-v-04685dce]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-04685dce]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-04685dce]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-04685dce]{max-width:876px}.VPTeamMembers.medium .container[data-v-04685dce]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-04685dce]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-04685dce]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-04685dce]{max-width:760px}.container[data-v-04685dce]{display:grid;gap:24px;margin:0 auto;max-width:1152px} diff --git a/assets/system.8e69987e.png b/assets/system.C_AmkiPg.png similarity index 100% rename from assets/system.8e69987e.png rename to assets/system.C_AmkiPg.png diff --git a/assets/vcr1.30d933ab.jpg b/assets/vcr1.NRLOOynQ.jpg similarity index 100% rename from assets/vcr1.30d933ab.jpg rename to assets/vcr1.NRLOOynQ.jpg diff --git a/assets/vcr10.548c566e.jpg b/assets/vcr10.D8t6cQ5v.jpg similarity index 100% rename from assets/vcr10.548c566e.jpg rename to assets/vcr10.D8t6cQ5v.jpg diff --git a/assets/vcr11.58ce8ace.jpg b/assets/vcr11.Cz1VMbIx.jpg similarity index 100% rename from assets/vcr11.58ce8ace.jpg rename to assets/vcr11.Cz1VMbIx.jpg diff --git a/assets/vcr12.3aa69b2a.jpg b/assets/vcr12.BNQe5j_u.jpg similarity index 100% rename from assets/vcr12.3aa69b2a.jpg rename to assets/vcr12.BNQe5j_u.jpg diff --git a/assets/vcr13.fcbcc557.jpg b/assets/vcr13.JV3PfcCZ.jpg similarity index 100% rename from assets/vcr13.fcbcc557.jpg rename to assets/vcr13.JV3PfcCZ.jpg diff --git a/assets/vcr14.7009c833.jpg b/assets/vcr14.Cjyr65Qp.jpg similarity index 100% rename from assets/vcr14.7009c833.jpg rename to assets/vcr14.Cjyr65Qp.jpg diff --git a/assets/vcr2.9b30a319.jpg b/assets/vcr2.DC9j-Ib5.jpg similarity index 100% rename from assets/vcr2.9b30a319.jpg rename to assets/vcr2.DC9j-Ib5.jpg diff --git a/assets/vcr3.0aa5a564.jpg b/assets/vcr3.Ea5Km6nQ.jpg similarity index 100% rename from assets/vcr3.0aa5a564.jpg rename to assets/vcr3.Ea5Km6nQ.jpg diff --git a/assets/vcr4.18a1487e.jpg b/assets/vcr4.B9DOiqQ8.jpg similarity index 100% rename from assets/vcr4.18a1487e.jpg rename to assets/vcr4.B9DOiqQ8.jpg diff --git a/assets/vcr5.97deb479.jpg b/assets/vcr5.BajXu8XE.jpg similarity index 100% rename from assets/vcr5.97deb479.jpg rename to assets/vcr5.BajXu8XE.jpg diff --git a/assets/vcr6.e706123b.jpg b/assets/vcr6.CxN-b1o3.jpg similarity index 100% rename from assets/vcr6.e706123b.jpg rename to assets/vcr6.CxN-b1o3.jpg diff --git a/assets/vcr7.43c60335.jpg b/assets/vcr7.D4aYKhIW.jpg similarity index 100% rename from assets/vcr7.43c60335.jpg rename to assets/vcr7.D4aYKhIW.jpg diff --git a/assets/vcr8.1bf1f353.jpg b/assets/vcr8.ByRFpMlF.jpg similarity index 100% rename from assets/vcr8.1bf1f353.jpg rename to assets/vcr8.ByRFpMlF.jpg diff --git a/assets/vcr9.b5afa4b4.jpg b/assets/vcr9.B4apCqgi.jpg similarity index 100% rename from assets/vcr9.b5afa4b4.jpg rename to assets/vcr9.B4apCqgi.jpg diff --git a/assets/virtio.b42d8275.png b/assets/virtio.CUVhk14O.png similarity index 100% rename from assets/virtio.b42d8275.png rename to assets/virtio.CUVhk14O.png diff --git a/assets/wechat.e3b2e06e.jpg b/assets/wechat.BhfskdFa.jpg similarity index 100% rename from assets/wechat.e3b2e06e.jpg rename to assets/wechat.BhfskdFa.jpg diff --git a/assets/win1.7d3fc058.png b/assets/win1.BYIcp55m.png similarity index 100% rename from assets/win1.7d3fc058.png rename to assets/win1.BYIcp55m.png diff --git a/assets/win1.c8d28bad.png b/assets/win1.CJKAoRm5.png similarity index 100% rename from assets/win1.c8d28bad.png rename to assets/win1.CJKAoRm5.png diff --git a/assets/win2.72bb0e48.jpg b/assets/win2.BNn7RQzT.jpg similarity index 100% rename from assets/win2.72bb0e48.jpg rename to assets/win2.BNn7RQzT.jpg diff --git a/assets/win3.442eb15f.jpg b/assets/win3.BgsODJcQ.jpg similarity index 100% rename from assets/win3.442eb15f.jpg rename to assets/win3.BgsODJcQ.jpg diff --git a/assets/win4.75bd03c1.jpg b/assets/win4.DwKt_Ood.jpg similarity index 100% rename from assets/win4.75bd03c1.jpg rename to assets/win4.DwKt_Ood.jpg diff --git a/assets/win5.58c1b996.jpg b/assets/win5.BSQ3T_9y.jpg similarity index 100% rename from assets/win5.58c1b996.jpg rename to assets/win5.BSQ3T_9y.jpg diff --git a/assets/win5.cacd68cb.jpg b/assets/win5.C8qmMo1u.jpg similarity index 100% rename from assets/win5.cacd68cb.jpg rename to assets/win5.C8qmMo1u.jpg diff --git a/assets/win6.f4215c61.jpg b/assets/win6.B-575Zc1.jpg similarity index 100% rename from assets/win6.f4215c61.jpg rename to assets/win6.B-575Zc1.jpg diff --git a/assets/win6.19e58640.jpg b/assets/win6.Cx0KdzQb.jpg similarity index 100% rename from assets/win6.19e58640.jpg rename to assets/win6.Cx0KdzQb.jpg diff --git a/assets/win7.8f856089.jpg b/assets/win7.CI43Ul0V.jpg similarity index 100% rename from assets/win7.8f856089.jpg rename to assets/win7.CI43Ul0V.jpg diff --git a/assets/win7.854d0e0a.jpg b/assets/win7.xhBfJRvu.jpg similarity index 100% rename from assets/win7.854d0e0a.jpg rename to assets/win7.xhBfJRvu.jpg diff --git a/assets/wincf.76927350.jpg b/assets/wincf.B_Jc2M1G.jpg similarity index 100% rename from assets/wincf.76927350.jpg rename to assets/wincf.B_Jc2M1G.jpg diff --git a/assets/wintj.56bef513.jpg b/assets/wintj.tP8uDOfH.jpg similarity index 100% rename from assets/wintj.56bef513.jpg rename to assets/wintj.tP8uDOfH.jpg diff --git a/assets/wk1.7d9f24d7.png b/assets/wk1.BGnwsbrE.png similarity index 100% rename from assets/wk1.7d9f24d7.png rename to assets/wk1.BGnwsbrE.png diff --git a/assets/wk2.2e88d91a.png b/assets/wk2.BasdNK2d.png similarity index 100% rename from assets/wk2.2e88d91a.png rename to assets/wk2.BasdNK2d.png diff --git a/assets/wk3.975bc38e.png b/assets/wk3.CWstwLHH.png similarity index 100% rename from assets/wk3.975bc38e.png rename to assets/wk3.CWstwLHH.png diff --git a/assets/wk4.004be17f.png b/assets/wk4.K5XvE6uQ.png similarity index 100% rename from assets/wk4.004be17f.png rename to assets/wk4.K5XvE6uQ.png diff --git a/assets/wk5.6cdba880.png b/assets/wk5.BEJ5BAWW.png similarity index 100% rename from assets/wk5.6cdba880.png rename to assets/wk5.BEJ5BAWW.png diff --git a/assets/wk6.667c5c95.png b/assets/wk6.D9MKwk3w.png similarity index 100% rename from assets/wk6.667c5c95.png rename to assets/wk6.D9MKwk3w.png diff --git a/assets/wk7.38e3cd7d.png b/assets/wk7.B0gH-0gL.png similarity index 100% rename from assets/wk7.38e3cd7d.png rename to assets/wk7.B0gH-0gL.png diff --git a/assets/wv1.5ac4a026.png b/assets/wv1.8ARiSJ9x.png similarity index 100% rename from assets/wv1.5ac4a026.png rename to assets/wv1.8ARiSJ9x.png diff --git a/case/case1.html b/case/case1.html index a0385205c6..0318ad491c 100644 --- a/case/case1.html +++ b/case/case1.html @@ -5,79 +5,82 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + - - +
Skip to content

仓库

Hits

Hits

融合怪测评项目

(GO版本除非必须的环境安装使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖也可全测项目)

如有问题请 issues 反馈。

Go 版本:https://github.com/oneclickvirt/ecs

Shell 版本:https://github.com/spiritLHLS/ecs


适配系统和架构

编译与测试支持情况

编译支持的架构测试支持的架构编译支持的系统测试支持的系统
amd64amd64LinuxLinux
armarmWindowsWindows
arm64arm64FreeBSDFreeBSD
386386OpenBSD
mipsMacOS
mipsle
s390xs390x
riscv64

功能

本项目初次使用建议查看说明:跳转


使用说明

Linux/FreeBSD/OpenBSD/MacOS

一键命令

一键命令默认安装依赖默认更新包管理器默认非互动模式

  • 国际用户无加速:

    bash
    export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
  • 国际/国内使用 CDN 加速:

    bash
    export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
  • 国内用户使用 CNB 加速:

    bash
    export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs

详细说明

详细说明中的命令可控制是否安装依赖是否更新包管理器默认互动模式可进行选择

  1. 下载脚本

    国际用户无加速:

    bash
    curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国际/国内使用 CDN 加速:

    bash
    curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国内用户使用 CNB 加速:

    bash
    curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
  2. 更新包管理器(可选择)并安装环境

    bash
    ./goecs.sh env

    非互动模式:

    bash
    export noninteractive=true && ./goecs.sh env
  3. 安装 goecs

    bash
    ./goecs.sh install
  4. 升级 goecs

    bash
    ./goecs.sh upgrade
  5. 卸载 goecs

    bash
    ./goecs.sh uninstall
  6. 帮助命令

    bash
    ./goecs.sh -h
  7. 唤起菜单

    bash
    goecs

命令参数化

bash
Usage: goecs [options]
+  -backtrace
+        Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
+  -basic
+        Enable/Disable basic test (default true)
+  -comm
+        Enable/Disable common media test (default true)
+  -cpu
+        Enable/Disable CPU test (default true)
+  -cpum string
+        Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
+  -cput string
+        Set CPU test thread mode (supported: single, multi) (default "multi")
+  -disk
+        Enable/Disable disk test (default true)
+  -diskm string
+        Set disk test method (supported: fio, dd, winsat) (default "fio")
+  -diskmc
+        Enable/Disable multiple disk checks, e.g., -diskmc=false
+  -diskp string
+        Set disk test path, e.g., -diskp /root
+  -email
+        Enable/Disable email port test (default true)
+  -h    Show help information
+  -l string
+        Set language (supported: en, zh) (default "zh")
+  -log
+        Enable/Disable logging in the current path
+  -memory
+        Enable/Disable memory test (default true)
+  -memorym string
+        Set memory test method (supported: sysbench, dd, winsat) (default "sysbench")
+  -menu
+        Enable/Disable menu mode, disable example: -menu=false (default true)
+  -nt3
+        Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
+  -nt3loc string
+        Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
+  -nt3t string
+        Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
+  -security
+        Enable/Disable security test (default true)
+  -speed
+        Enable/Disable speed test (default true)
+  -spnum int
+        Set the number of servers per operator for speed test (default 2)
+  -upload
+        Enable/Disable upload the result (default true)
+  -ut
+        Enable/Disable unlock media test (default true)
+  -v    Display version information

Windows

  1. 下载带 exe 文件的压缩包:Releases
  2. 解压后,右键以管理员模式运行。

Docker

国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm spiritlhl/goecs:latest -menu=false -l zh

使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。

国内镜像地址:https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

从源码进行编译

  1. 克隆仓库的 public 分支(不含私有依赖)
bash
git clone -b public https://github.com/oneclickvirt/ecs.git
+cd ecs
  1. 安装 Go 环境(如已安装可跳过)
bash
# 下载并安装 Go
+wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
+rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
+export PATH=$PATH:/usr/local/go/bin
  1. 编译
bash
go build -o goecs
  1. 运行测试
bash
./goecs -menu=false -l zh

支持的编译参数:

  • GOOS:支持 linux、windows、darwin、freebsd、openbsd
  • GOARCH:支持 amd64、arm、arm64、386、mips、mipsle、s390x、riscv64

跨平台编译示例:

bash
# 编译 Windows 版本
+GOOS=windows GOARCH=amd64 go build -o goecs.exe
+# 编译 MacOS 版本
+GOOS=darwin GOARCH=amd64 go build -o goecs_darwin

QA

Q: 为什么默认使用sysbench而不是geekbench

A: 比较二者特点

比较项sysbenchgeekbench
适用范围轻量级,几乎可在任何服务器上运行重量级,小型机器无法运行
测试要求无需网络,无特殊硬件需求需联网,IPV4环境,至少1G内存
开源情况基于LUA,开源,可自行编译各架构版本官方二进制闭源代码,不支持自行编译
测试稳定性核心测试组件10年以上未变每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU)
测试内容仅测试计算性能覆盖多种性能测试,分数加权计算,但部分测试实际不常用
适用场景适合快速测试,仅测试计算性能适合综合全面的测试

goecs测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求

Q: 为什么使用Golang而不是Rust重构

A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,我懒得搞我没那个技术力

Q: 为什么不继续开发Shell版本而是选择重构

A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)

Q: 每个测试项目的说明有吗?

A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明

Q: 测试进行到一半如何手动终止?

A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。

Q: 非Root环境如何进行测试?

A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。

致谢

感谢 he.net bgp.tools ipinfo.io ip.sb cheervision.co scamalytics.com abuseipdb.com virustotal.com ip2location.com ip-api.com ipregistry.co ipdata.co ipgeolocation.io ipwhois.io ipapi.com ipapi.is ipqualityscore.com bigdatacloud.com 等网站提供的API进行检测,感谢互联网各网站提供的查询资源

感谢

h501

提供的免费托管支持本开源项目的共享测试结果存储

同时感谢以下平台提供编辑和测试支持

golandibm
+ \ No newline at end of file diff --git a/case/case2.html b/case/case2.html index 268270158c..e14beac3b1 100644 --- a/case/case2.html +++ b/case/case2.html @@ -5,57 +5,60 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/spiritLHLS/one-click-installation-script

Hits

所有脚本如需在国内服务器使用,请在链接前加上https://ghproxy.com/确保命令可以下载本仓库的shell脚本执行

一键修复脚本

运行所有一键修复脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键尝试修复apt源

  • 支持系统:Ubuntu 12+,Debian 6+
  • 修复apt下载包进程意外退出导致的源锁死
  • 修复apt源broken损坏
  • 修复apt源多进程占用锁死
  • 修复apt源公钥缺失
  • 修复替换系统可用的apt源列表,国内用阿里源,国外用官方源
  • 修复本机的Ubuntu系统是EOL非长期维护的版本(奇数或陈旧的偶数版本),将替换为Ubuntu官方的old-releases仓库以支持apt的使用
  • 修复只保证apt update不会报错,其他命令报错未修复
  • 如若修复后install还有问题,重启服务器解决问题
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/package.sh -o package.sh && chmod +x package.sh && bash package.sh

一键尝试修复系统时间

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 由于系统时间不准确都是未进行时区时间同步造成的,使用chronyd进行时区时间同步后应当解决了问题
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/modify_time.sh -o modify_time.sh && chmod +x modify_time.sh && bash modify_time.sh

一键尝试修复sudo警告

  • 一键尝试修复sudo: unable to resolve host xxx: Name or service not known警告(爆错)

不要在生产环境上使用该脚本,否则容易造成网络hosts配置错误,配置的host名字不在外网IP上反而在内网IP(127.0.0.1)上

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/check_sudo.sh -o check_sudo.sh && chmod +x check_sudo.sh && bash check_sudo.sh

一键修改系统自带的journal日志记录大小释放系统盘空间

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 1.自定义修改大小,单位为MB,一般500或者1000即可,有的系统日志默认给了5000甚至更多,不是做站啥的没必要
    • 请注意,修改journal目录大小会影响系统日志的记录,因此,在修改journal目录大小之前如果需要之前的日志,建议先备份系统日志到本地
  • 2.自定义修改设置系统日志保留日期时长,超过日期时长的日志将被清除
  • 3.默认修改日志只记录warning等级(无法自定义)
  • 4.以后日志的产生将受到日志文件大小,日志保留时间,日志保留等级的限制
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/resize_journal.sh -o resize_journal.sh && chmod +x resize_journal.sh && bash resize_journal.sh

一键尝试修复网络

该脚本轻易勿要使用,请确保运行时服务器无重要文件或程序,出现运行bug后续可能需要重装系统

一定要在screen中执行该脚本,否则可能导致修改过程中ssh断链接而修改失败卡住最终SSH无法连接!不在screen中执行后果自负!

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 尝试修复nameserver为google源或cloudflare源
  • 尝试修复为IP类型对应的网络优先级(默认IPV4类型,纯V6类型再替换为IPV6类型)
bash
curl -L https://cdn.spiritlhl.workers.dev/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/network.sh -o network.sh && chmod +x network.sh && bash network.sh

如果是纯V6的也可以不使用上面脚本的nat64,使用warp添加V4网络

比如:https://github.com/fscarmen/warp

bash
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh [option] [lisence]

非纯V6的,带V4切换优先级到IPV4可用以下命令

bash
sudo sed -i 's/.*precedence ::ffff:0:0\/96.*/precedence ::ffff:0:0\/96  100/g' /etc/gai.conf && sudo systemctl restart networking

一键环境安装脚本

只推荐在新服务器上安装,环境不纯净不保证不出bug

运行所有一键环境安装脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键安装jupyter环境

  • 本脚本尝试使用Miniconda3安装虚拟环境jupyter-env再进行jupyter和jupyterlab的安装,如若安装机器不纯净勿要轻易使用本脚本!
  • 本脚本为实验性脚本可能会有各种bug,勿要轻易尝试!
  • 验证已支持的系统:
    • Ubuntu 系 - 推荐,脚本自动挂起到后台
    • Debian 系 - 部分可能需要手动挂起到后台,详看脚本运行安装完毕的后续提示
  • 可能支持的系统(未验证):centos 7+,Fedora,Almalinux 8.5+
  • 执行脚本,之前有用本脚本安装过则直接打印设置的登陆信息,没安装过则进行安装再打印信息,如果已安装但未启动则自动启动后再打印信息
  • 如果是初次安装无脑输入y回车即可,按照提示进行操作即可,安装完毕将在后台常驻运行,自动添加常用的安装包通道源
  • 安装完毕后,如果需要在lab中安装第三方库需要在lab中使用terminal并使用conda进行下载而不是pip3下载,这是需要注意的一点
  • 安装过程中有判断是否为中国IP,可选择是否使用中国镜像

原始用途是方便快捷的在按小时计费的超大型服务器上部署python环境进行科学计算,充分利用时间别浪费在构建环境上。

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/jupyter.sh -o jupyter.sh && chmod +x jupyter.sh && bash jupyter.sh

一键安装R语言环境

  • 安装前需使用Miniconda3安装虚拟环境jupyter-env,然后进行jupyter和jupyterlab的安装,再然后才能安装本内核
  • 简单的说,需要执行本仓库对应的jupyter安装脚本再运行本脚本安装R语言环境,会自动安装R环境内核和图形设备支持库
  • x11可能需要手动启动一下,执行sudo /usr/bin/Xorg
  • 可能支持的系统(未验证):centos 7+,Fedora,Almalinux 8.5+
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/R.sh -o R.sh && chmod +x R.sh && bash R.sh

一键安装rust环境

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 加载官方脚本安装,前置条件适配系统以及后置条件判断安装的版本
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/rust.sh -o rust.sh && chmod +x rust.sh && bash rust.sh

一键安装C环境

  • 一键安装C++环境
  • 支持系统:使用apt或者yum作为包管理器的系统
  • 如果未安装则安装,如果有安装则提示升级
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/cplusplus.sh -o cplusplus.sh && chmod +x cplusplus.sh && bash cplusplus.sh

一键安装vnstat环境

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 加载官方文件编译安装,前置条件适配系统以及后置条件判断安装的版本
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/vnstat.sh -o vnstat.sh && chmod +x vnstat.sh && bash vnstat.sh

一键升级低版本debian为debian11

  • 支持系统:debian 6+
  • 升级后需要重启系统加载内核,升级过程中需要选择的都无脑按回车即可
  • 升级是一个版本迭代一个版本,所以如果版本低,每执行一次升级一个版本,直至升级到debian11
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/todebian11.sh -o todebian11.sh && chmod +x todebian11.sh && bash todebian11.sh

一键升级低版本ubuntu为ubuntu22

  • 支持系统:Ubuntu 16+
  • 升级后需要重启系统加载内核,升级过程中需要选择的都无脑按回车即可
  • 升级是一个版本迭代一个版本,所以如果版本低,每执行一次升级一个版本,直至升级到ubuntu22
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/toubuntu22.sh -o toubuntu22.sh && chmod +x toubuntu22.sh && bash toubuntu22.sh

一键安装zipline平台

  • 应该支持的系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 暂时只在Ubuntu上验证无问题
  • 如若要设置反向代理绑定域名,安装前请保证原服务器未安装过nginx,如若已安装过nginx,请自行配置反向代理本机的3000端口
  • 默认一路回车是不启用反代不安装nginx的,自行选择,如需通过本脚本配置反代系统一定要未安装过nginx并在填写y或Y开启安装
  • zipline 平台功能: ShareX,自定义短链接,文件上传分享,多用户校验,高亮显示,阅后即焚,设置简单 (含pastebin)
  • 自动安装docker,docker-compose,如若已安装zipline在/root目录下,则自动更新
  • 反向代理如若已设置成功,还需要在面板设置中填写域名,绑定启用
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/zipline.sh -o zipline.sh && chmod +x zipline.sh && bash zipline.sh

如果需要删除0字节文件,打开/root/zipline文件夹,执行

docker-compose exec zipline yarn scripts:clear-zero-byte

按照提示操作

一键安装filebrowser平台

  • 端口设置为3030了,其他登陆信息详见提示
  • filebrowser平台支持下载上传文件到服务器,批量下载多个文件(自定义压缩格式),构建文件分享链接,设置分享时长
  • 如果本地有启用IPV6优先级可能绑定到V6去了,使用lsof -i:3030查看绑定情况,切换优先级后再安装就正常了
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/filebrowser.sh -o filebrowser.sh && chmod +x filebrowser.sh && bash filebrowser.sh

一键删除平台监控

  • 一键移除大多数云服务器监控
  • 涵盖阿里云、腾讯云、华为云、UCLOUD、甲骨文云、京东云
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/dlm.sh -o dlm.sh && chmod +x dlm.shh && bash dlm.sh

部分手动命令

一键开启root登陆并替换密码

bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

一键屏蔽邮件端口避免被恶意程序使用

bash
iptables -A INPUT -p tcp --dport 25 -j DROP
-iptables -A OUTPUT -p tcp --dport 25 -j DROP
-/sbin/iptables-save

设置语言包

bash
sudo apt-get update
-sudo apt-get install language-pack-en-base
-sudo locale-gen en_US.UTF-8

下载UTF-8的环境,生成UTF-8的包,然后重启服务器

bash
locale -a
-export LC_ALL=en_US.UTF-8

查看并设置语言包

language-pack-en-base 在debian中好像没有,只有Ubuntu有好像,不知道是不是个例,有问题再说

ubuntu更新源被锁

bash
sudo rm -rf /var/cache/apt/archives/lock
-sudo pkill apt
-sudo rm /var/lib/dpkg/lock-frontend
-sudo rm /var/lib/apt/lists/lock
-sudo rm /var/cache/apt/archives/lock
-sudo rm /var/lib/dpkg/lock
-sudo dpkg --configure -a

然后重启系统

debian缺失公钥

bash
apt-get install debian-keyring debian-archive-keyring -y

ubuntu或debian缺失公钥

后续这块有计划整理为一个一键脚本

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 公钥

centos换源

bash
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
-sudo sed -i 's/^mirrorlist=http/mirrorlist=https/' /etc/yum.repos.d/CentOS-Base.repo

安装gitea

Ubuntu 20无问题,Ubuntu 22好像不行

https://gitlab.com/packaging/gitea

卸载aapanel

bash
apt install sysv-rc-conf -y && service bt stop && sysv-rc-conf bt off && rm -f /etc/init.d/bt && rm -rf /www/server/panel

安装docker和docker-compose

bash
curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

卸载所有docker镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

通过docker安装code-server

安装

shell
mkdir -p ~/.config
-docker run --restart=always --name code-server -p 0.0.0.0:8886:8080 \
-  -v "$HOME/.config:/home/coder/.config" \
-  -v "$PWD:/home/coder/project" \
-  -u "$(id -u):$(id -g)" \
-  -e "DOCKER_USER=$USER" \
-  codercom/code-server:latest

新窗口

shell
docker exec code-server cat /root/.config/code-server/config.yaml

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
-sudo systemctl enable --now code-server@root
-sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
-sudo systemctl restart code-server@root
-cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
-sudo systemctl disable code-server@root
-rm -rf ~/.cache/coder
-sudo apt remove coder -y
- +
Skip to content

仓库

https://github.com/spiritLHLS/one-click-installation-script

Hits

所有脚本如需在国内服务器使用,请在链接前加上https://ghproxy.com/确保命令可以下载本仓库的shell脚本执行

一键修复脚本

运行所有一键修复脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键尝试修复apt源

  • 支持系统:Ubuntu 12+,Debian 6+
  • 修复apt下载包进程意外退出导致的源锁死
  • 修复apt源broken损坏
  • 修复apt源多进程占用锁死
  • 修复apt源公钥缺失
  • 修复替换系统可用的apt源列表,国内用阿里源,国外用官方源
  • 修复本机的Ubuntu系统是EOL非长期维护的版本(奇数或陈旧的偶数版本),将替换为Ubuntu官方的old-releases仓库以支持apt的使用
  • 修复只保证apt update不会报错,其他命令报错未修复
  • 如若修复后install还有问题,重启服务器解决问题
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/package.sh -o package.sh && chmod +x package.sh && bash package.sh

一键尝试修复系统时间

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 由于系统时间不准确都是未进行时区时间同步造成的,使用chronyd进行时区时间同步后应当解决了问题
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/modify_time.sh -o modify_time.sh && chmod +x modify_time.sh && bash modify_time.sh

一键尝试修复sudo警告

  • 一键尝试修复sudo: unable to resolve host xxx: Name or service not known警告(爆错)

不要在生产环境上使用该脚本,否则容易造成网络hosts配置错误,配置的host名字不在外网IP上反而在内网IP(127.0.0.1)上

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/check_sudo.sh -o check_sudo.sh && chmod +x check_sudo.sh && bash check_sudo.sh

一键修改系统自带的journal日志记录大小释放系统盘空间

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 1.自定义修改大小,单位为MB,一般500或者1000即可,有的系统日志默认给了5000甚至更多,不是做站啥的没必要
    • 请注意,修改journal目录大小会影响系统日志的记录,因此,在修改journal目录大小之前如果需要之前的日志,建议先备份系统日志到本地
  • 2.自定义修改设置系统日志保留日期时长,超过日期时长的日志将被清除
  • 3.默认修改日志只记录warning等级(无法自定义)
  • 4.以后日志的产生将受到日志文件大小,日志保留时间,日志保留等级的限制
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/resize_journal.sh -o resize_journal.sh && chmod +x resize_journal.sh && bash resize_journal.sh

一键尝试修复网络

该脚本轻易勿要使用,请确保运行时服务器无重要文件或程序,出现运行bug后续可能需要重装系统

一定要在screen中执行该脚本,否则可能导致修改过程中ssh断链接而修改失败卡住最终SSH无法连接!不在screen中执行后果自负!

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 尝试修复nameserver为google源或cloudflare源
  • 尝试修复为IP类型对应的网络优先级(默认IPV4类型,纯V6类型再替换为IPV6类型)
bash
curl -L https://cdn.spiritlhl.workers.dev/https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/repair_scripts/network.sh -o network.sh && chmod +x network.sh && bash network.sh

如果是纯V6的也可以不使用上面脚本的nat64,使用warp添加V4网络

比如:https://github.com/fscarmen/warp

bash
wget -N https://raw.githubusercontent.com/fscarmen/warp/main/menu.sh && bash menu.sh [option] [lisence]

非纯V6的,带V4切换优先级到IPV4可用以下命令

bash
sudo sed -i 's/.*precedence ::ffff:0:0\/96.*/precedence ::ffff:0:0\/96  100/g' /etc/gai.conf && sudo systemctl restart networking

一键环境安装脚本

只推荐在新服务器上安装,环境不纯净不保证不出bug

运行所有一键环境安装脚本前注意看说明,以及保证服务器无重要数据,运行后造成的一切后果作者不负任何责任,自行评判风险!

一键安装jupyter环境

  • 本脚本尝试使用Miniconda3安装虚拟环境jupyter-env再进行jupyter和jupyterlab的安装,如若安装机器不纯净勿要轻易使用本脚本!
  • 本脚本为实验性脚本可能会有各种bug,勿要轻易尝试!
  • 验证已支持的系统:
    • Ubuntu 系 - 推荐,脚本自动挂起到后台
    • Debian 系 - 部分可能需要手动挂起到后台,详看脚本运行安装完毕的后续提示
  • 可能支持的系统(未验证):centos 7+,Fedora,Almalinux 8.5+
  • 执行脚本,之前有用本脚本安装过则直接打印设置的登陆信息,没安装过则进行安装再打印信息,如果已安装但未启动则自动启动后再打印信息
  • 如果是初次安装无脑输入y回车即可,按照提示进行操作即可,安装完毕将在后台常驻运行,自动添加常用的安装包通道源
  • 安装完毕后,如果需要在lab中安装第三方库需要在lab中使用terminal并使用conda进行下载而不是pip3下载,这是需要注意的一点
  • 安装过程中有判断是否为中国IP,可选择是否使用中国镜像

原始用途是方便快捷的在按小时计费的超大型服务器上部署python环境进行科学计算,充分利用时间别浪费在构建环境上。

bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/jupyter.sh -o jupyter.sh && chmod +x jupyter.sh && bash jupyter.sh

一键安装R语言环境

  • 安装前需使用Miniconda3安装虚拟环境jupyter-env,然后进行jupyter和jupyterlab的安装,再然后才能安装本内核
  • 简单的说,需要执行本仓库对应的jupyter安装脚本再运行本脚本安装R语言环境,会自动安装R环境内核和图形设备支持库
  • x11可能需要手动启动一下,执行sudo /usr/bin/Xorg
  • 可能支持的系统(未验证):centos 7+,Fedora,Almalinux 8.5+
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/R.sh -o R.sh && chmod +x R.sh && bash R.sh

一键安装rust环境

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 加载官方脚本安装,前置条件适配系统以及后置条件判断安装的版本
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/rust.sh -o rust.sh && chmod +x rust.sh && bash rust.sh

一键安装C环境

  • 一键安装C++环境
  • 支持系统:使用apt或者yum作为包管理器的系统
  • 如果未安装则安装,如果有安装则提示升级
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/cplusplus.sh -o cplusplus.sh && chmod +x cplusplus.sh && bash cplusplus.sh

一键安装vnstat环境

  • 支持系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 加载官方文件编译安装,前置条件适配系统以及后置条件判断安装的版本
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/vnstat.sh -o vnstat.sh && chmod +x vnstat.sh && bash vnstat.sh

一键升级低版本debian为debian11

  • 支持系统:debian 6+
  • 升级后需要重启系统加载内核,升级过程中需要选择的都无脑按回车即可
  • 升级是一个版本迭代一个版本,所以如果版本低,每执行一次升级一个版本,直至升级到debian11
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/todebian11.sh -o todebian11.sh && chmod +x todebian11.sh && bash todebian11.sh

一键升级低版本ubuntu为ubuntu22

  • 支持系统:Ubuntu 16+
  • 升级后需要重启系统加载内核,升级过程中需要选择的都无脑按回车即可
  • 升级是一个版本迭代一个版本,所以如果版本低,每执行一次升级一个版本,直至升级到ubuntu22
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/toubuntu22.sh -o toubuntu22.sh && chmod +x toubuntu22.sh && bash toubuntu22.sh

一键安装zipline平台

  • 应该支持的系统:Ubuntu 18+,Debian 8+,centos 7+,Fedora,Almalinux 8.5+
  • 暂时只在Ubuntu上验证无问题
  • 如若要设置反向代理绑定域名,安装前请保证原服务器未安装过nginx,如若已安装过nginx,请自行配置反向代理本机的3000端口
  • 默认一路回车是不启用反代不安装nginx的,自行选择,如需通过本脚本配置反代系统一定要未安装过nginx并在填写y或Y开启安装
  • zipline 平台功能: ShareX,自定义短链接,文件上传分享,多用户校验,高亮显示,阅后即焚,设置简单 (含pastebin)
  • 自动安装docker,docker-compose,如若已安装zipline在/root目录下,则自动更新
  • 反向代理如若已设置成功,还需要在面板设置中填写域名,绑定启用
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/zipline.sh -o zipline.sh && chmod +x zipline.sh && bash zipline.sh

如果需要删除0字节文件,打开/root/zipline文件夹,执行

docker-compose exec zipline yarn scripts:clear-zero-byte

按照提示操作

一键安装filebrowser平台

  • 端口设置为3030了,其他登陆信息详见提示
  • filebrowser平台支持下载上传文件到服务器,批量下载多个文件(自定义压缩格式),构建文件分享链接,设置分享时长
  • 如果本地有启用IPV6优先级可能绑定到V6去了,使用lsof -i:3030查看绑定情况,切换优先级后再安装就正常了
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/filebrowser.sh -o filebrowser.sh && chmod +x filebrowser.sh && bash filebrowser.sh

一键删除平台监控

  • 一键移除大多数云服务器监控
  • 涵盖阿里云、腾讯云、华为云、UCLOUD、甲骨文云、京东云
bash
curl -L https://raw.githubusercontent.com/spiritLHLS/one-click-installation-script/main/install_scripts/dlm.sh -o dlm.sh && chmod +x dlm.shh && bash dlm.sh

部分手动命令

一键开启root登陆并替换密码

bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

一键屏蔽邮件端口避免被恶意程序使用

bash
iptables -A INPUT -p tcp --dport 25 -j DROP
+iptables -A OUTPUT -p tcp --dport 25 -j DROP
+/sbin/iptables-save

设置语言包

bash
sudo apt-get update
+sudo apt-get install language-pack-en-base
+sudo locale-gen en_US.UTF-8

下载UTF-8的环境,生成UTF-8的包,然后重启服务器

bash
locale -a
+export LC_ALL=en_US.UTF-8

查看并设置语言包

language-pack-en-base 在debian中好像没有,只有Ubuntu有好像,不知道是不是个例,有问题再说

ubuntu更新源被锁

bash
sudo rm -rf /var/cache/apt/archives/lock
+sudo pkill apt
+sudo rm /var/lib/dpkg/lock-frontend
+sudo rm /var/lib/apt/lists/lock
+sudo rm /var/cache/apt/archives/lock
+sudo rm /var/lib/dpkg/lock
+sudo dpkg --configure -a

然后重启系统

debian缺失公钥

bash
apt-get install debian-keyring debian-archive-keyring -y

ubuntu或debian缺失公钥

后续这块有计划整理为一个一键脚本

bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 公钥

centos换源

bash
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
+sudo sed -i 's/^mirrorlist=http/mirrorlist=https/' /etc/yum.repos.d/CentOS-Base.repo

安装gitea

Ubuntu 20无问题,Ubuntu 22好像不行

https://gitlab.com/packaging/gitea

卸载aapanel

bash
apt install sysv-rc-conf -y && service bt stop && sysv-rc-conf bt off && rm -f /etc/init.d/bt && rm -rf /www/server/panel

安装docker和docker-compose

bash
curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

卸载所有docker镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

通过docker安装code-server

安装

shell
mkdir -p ~/.config
+docker run --restart=always --name code-server -p 0.0.0.0:8886:8080 \
+  -v "$HOME/.config:/home/coder/.config" \
+  -v "$PWD:/home/coder/project" \
+  -u "$(id -u):$(id -g)" \
+  -e "DOCKER_USER=$USER" \
+  codercom/code-server:latest

新窗口

shell
docker exec code-server cat /root/.config/code-server/config.yaml

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
+sudo systemctl enable --now code-server@root
+sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
+sudo systemctl restart code-server@root
+cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
+sudo systemctl disable code-server@root
+rm -rf ~/.cache/coder
+sudo apt remove coder -y

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
+sudo systemctl enable --now code-server@root
+sed -i '1s/127.0.0.1:8080/0.0.0.0:8536/' ~/.config/code-server/config.yaml
+sudo systemctl restart code-server@root
+cat .config/code-server/config.yaml

卸载需要

sudo systemctl stop code-server@root
+sudo systemctl disable code-server@root
+rm -rf ~/.cache/coder
+sudo apt remove coder -y
+ \ No newline at end of file diff --git a/case/case3.html b/case/case3.html index c1c442e576..7e22e6ca68 100644 --- a/case/case3.html +++ b/case/case3.html @@ -5,22 +5,25 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/spiritLHLS/ecsspeed

Hits

ecsspeed

自动更新测速服务器节点列表的网络基准测试脚本

Network benchmarking script that automatically updates the list of speed measurement server nodes

说明

所有组件以及数据均来源于平台或已有的开源项目,无非开源部分,放心食用

对应 speedtest.net 的自动更新测速服务器ID的测速脚本

日常推荐使用

bash <(wget -qO- bash.spiritlhl.net/ecs-net)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-net.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-net.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表大概每7天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

当官方CLI安装失败(如罕见的架构或者官方网站访问失败时)自动使用 speedtest-go 作为替代品测速

对应 speedtest.cn 的自动更新测速服务器ID的测速脚本

单线程测速

bash <(wget -qO- bash.spiritlhl.net/ecs-cn)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-cn.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-cn.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表每天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

自动更新测试服务器列表的三网延迟测试脚本

平均耗时10~15秒

bash <(wget -qO- bash.spiritlhl.net/ecs-ping)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-ping.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-ping.sh)

效果图

图片

功能

  • [x] 自动抓取 speedtest.cn 节点信息结合已有信息去重并更新列表数据
  • [x] 自动抓取 speedtest.net 节点信息结合已有信息去重并更新列表数据
  • [x] 对应 speedtest.net 的自动更新测速服务器列表的测速脚本
  • [x] 对应 speedtest.cn 的自动更新测速服务器列表的测速脚本
  • [x] 自动更新测试服务器列表的三网Ping值测试脚本

.cn数据

仓库:https://github.com/spiritLHLS/speedtest.cn-CN-ID

.net数据

仓库:https://github.com/spiritLHLS/speedtest.net-CN-ID

- +
Skip to content

仓库

https://github.com/spiritLHLS/ecsspeed

Hits

ecsspeed

自动更新测速服务器节点列表的网络基准测试脚本

Network benchmarking script that automatically updates the list of speed measurement server nodes

说明

所有组件以及数据均来源于平台或已有的开源项目,无非开源部分,放心食用

对应 speedtest.net 的自动更新测速服务器ID的测速脚本

日常推荐使用

bash <(wget -qO- bash.spiritlhl.net/ecs-net)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-net.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-net.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表大概每7天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

当官方CLI安装失败(如罕见的架构或者官方网站访问失败时)自动使用 speedtest-go 作为替代品测速

对应 speedtest.cn 的自动更新测速服务器ID的测速脚本

单线程测速

bash <(wget -qO- bash.spiritlhl.net/ecs-cn)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-cn.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-cn.sh)

支持测速的架构:i386, x86_64, amd64, arm64, s390x, riscv64, ppc64le, ppc64

涵盖中国三大运营商、香港、台湾的测速节点,默认的三网测速每个运营商选择本机ping值最低的两个节点测速,详情三网测速才是全测,节点列表每天自动更新一次。

支持国内服务器测试(有判断是否为国内机器),但由于国内服务器带宽过小,会很慢,详见初次运行的显示

自动更新测试服务器列表的三网延迟测试脚本

平均耗时10~15秒

bash <(wget -qO- bash.spiritlhl.net/ecs-ping)

bash <(wget -qO- --no-check-certificate https://github.com/spiritLHLS/ecsspeed/raw/main/script/ecsspeed-ping.sh)

或国内用

bash <(wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubusercontent.com/spiritLHLS/ecsspeed/main/script/ecsspeed-ping.sh)

效果图

图片

功能

  • [x] 自动抓取 speedtest.cn 节点信息结合已有信息去重并更新列表数据
  • [x] 自动抓取 speedtest.net 节点信息结合已有信息去重并更新列表数据
  • [x] 对应 speedtest.net 的自动更新测速服务器列表的测速脚本
  • [x] 对应 speedtest.cn 的自动更新测速服务器列表的测速脚本
  • [x] 自动更新测试服务器列表的三网Ping值测试脚本

.cn数据

仓库:https://github.com/spiritLHLS/speedtest.cn-CN-ID

.net数据

仓库:https://github.com/spiritLHLS/speedtest.net-CN-ID

+ \ No newline at end of file diff --git a/case/case4.html b/case/case4.html index 47489899ee..34ea2be65f 100644 --- a/case/case4.html +++ b/case/case4.html @@ -5,22 +5,25 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/oneclickvirt/backtrace

Hits

backtrace

三网回程路由线路测试

基于 https://github.com/zhanghanyun/backtrace 的重构和优化,与原版存在很大不同

路由的线路判断最终还是得人工判断的才准确,本项目测试结果仅供参考

功能

  • [x] 检测回程显示IPV4地址时的线路,不显示IP地址时显示ASN检测不到,原版backtrace也支持
  • [x] 支持对48379929163线路的判断,原版backtrace也支持
  • [x] 支持对CN2GTCN2GIA线路的判断,原版backtrace不支持
  • [x] 支持对CMIN2CMI线路的判断,原版backtrace不支持
  • [x] 支持对整个回程路由进行线路分析,与原版backtrace仅进行一次判断不同
  • [x] 修复原版backtrace对IPV4地址信息获取时json解析失败依然打印信息的问题
  • [x] 增加对全平台的编译支持,原版backtrace仅支持linux平台的amd64和arm64架构

使用

shell
curl https://raw.githubusercontent.com/oneclickvirt/backtrace/main/backtrace_install.sh -sSf | sh

更多架构请查看 https://github.com/oneclickvirt/backtrace/releases/tag/output

概览图

图片

图片

图片

- +
Skip to content

仓库

https://github.com/oneclickvirt/backtrace

Hits

backtrace

三网回程路由线路测试

基于 https://github.com/zhanghanyun/backtrace 的重构和优化,与原版存在很大不同

路由的线路判断最终还是得人工判断的才准确,本项目测试结果仅供参考

功能

  • [x] 检测回程显示IPV4地址时的线路,不显示IP地址时显示ASN检测不到,原版backtrace也支持
  • [x] 支持对48379929163线路的判断,原版backtrace也支持
  • [x] 支持对CN2GTCN2GIA线路的判断,原版backtrace不支持
  • [x] 支持对CMIN2CMI线路的判断,原版backtrace不支持
  • [x] 支持对整个回程路由进行线路分析,与原版backtrace仅进行一次判断不同
  • [x] 修复原版backtrace对IPV4地址信息获取时json解析失败依然打印信息的问题
  • [x] 增加对全平台的编译支持,原版backtrace仅支持linux平台的amd64和arm64架构

使用

shell
curl https://raw.githubusercontent.com/oneclickvirt/backtrace/main/backtrace_install.sh -sSf | sh

更多架构请查看 https://github.com/oneclickvirt/backtrace/releases/tag/output

概览图

图片

图片

图片

+ \ No newline at end of file diff --git a/case/case5.html b/case/case5.html index 8883a9a091..cb3a0c2226 100644 --- a/case/case5.html +++ b/case/case5.html @@ -5,22 +5,25 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/spiritLHLS/Oracle-server-keep-alive-script

Hits

Oracle-server-keep-alive-script

实际不止可以在甲骨文服务器上使用,也可以使用在任意ARM或X86_64架构的系统,用作资源占用

甲骨文服务器保活脚本

适配系统:已在Ubuntu 20+,Debian 10+, Centos 7+, Oracle linux 8+,AlmaLinux 8.5+

上述系统验证无问题,别的主流系统应该也没有问题

可选占用:CPU,内存,带宽

安装完毕后如果有问题请卸载脚本反馈问题(重复卸载也没问题)

所有资源(除了CPU)可选默认配置则动态占用,实时调整,避免服务器有别的任何资源已经超过限额了仍然再占用资源

为避免GitHub的CDN抽风加载不了新内容,所有新更新已使用Gitlab仓库

由于speedtest-go的release依赖于GitHub,所以请检查 www.githubstatus.com ,有问题时无法安装带宽占用

基础开发完毕,测试中,有问题请在issues中反馈

选项1安装,选项2卸载,选项3更新安装引导脚本,选项4退出脚本

安装过程中无脑回车则全部可选的占用都占用,不需要什么占用输入n再回车

如果选择带宽占用,会询问使用speedtest-go占用还是使用wget占用,按照提示进行选择即可

有询问是否需要带宽占用的参数自定义,这时候默认选项就是n,回车就使用默认配置,输入y再回车则需要按照提示自定义参数

curl -L https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh -o oalive.sh && chmod +x oalive.sh && bash oalive.sh

bash oalive.sh

bash <(wget -qO- --no-check-certificate https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh)

说明

  • 提供两种CPU占用模式:DD模拟占用和科学计算模式,用户可以自由选择,占用范围设置在15%至25%之间,更推荐DD模拟占用
  • DD模拟占用在守护进程中设置了CPU占用的最高限制
  • 默认情况下,CPU占用设置为25%最高值,计算方法是核数乘以12%,如果计算结果低于25%,则设置为该值;如果计算结果高于25%,则按照计算结果的比例进行设置。
  • 内存占用设置为占用总内存的20%,占用时间为300秒,休息时间为300秒。
  • 每300秒检测一次内存占用情况,并根据需要动态调整占用大小。如果内存占用已经大于20%,则不增加占用。
  • 在占用过程中,使用守护进程和开机自启服务,以确保占用任务持续且有效。
  • 默认选项的带宽占用每45分钟下载一次大小在1G至10G之间的文件,只进行下载而不保存。在下载过程中会占用硬盘空间,但在下载完成后会自动释放。
  • 默认选项的带宽占用动态调整实际下载的带宽/速率,限制每次下载的最长时长为6分钟。在每次下载之前,会测试最大可用带宽,并根据实时结果将下载速率设置为30%的带宽。
  • 带宽占用测试使用了speedtest-cli和speedtest-go两种工具,以防其中之一不可用时使用第二种工具,用户可以自定义设置带宽占用,此时详见设置提示。
  • 提供一键卸载所有占用服务的选项,卸载将删除所有脚本、服务、任务、守护进程和开机自启设置。
  • 提供一键检查更新的功能,更新范围仅限于脚本更新。请在更新后重新设置占用服务
  • 对所有进程执行增加唯一性检测,避免重复运行,使用PID文件进行判断。

如若不希望一键的,希望自定义设置时间的,请查看README_CRON.md自行设置定时任务

- +
Skip to content

仓库

https://github.com/spiritLHLS/Oracle-server-keep-alive-script

Hits

Oracle-server-keep-alive-script

实际不止可以在甲骨文服务器上使用,也可以使用在任意ARM或X86_64架构的系统,用作资源占用

甲骨文服务器保活脚本

适配系统:已在Ubuntu 20+,Debian 10+, Centos 7+, Oracle linux 8+,AlmaLinux 8.5+

上述系统验证无问题,别的主流系统应该也没有问题

可选占用:CPU,内存,带宽

安装完毕后如果有问题请卸载脚本反馈问题(重复卸载也没问题)

所有资源(除了CPU)可选默认配置则动态占用,实时调整,避免服务器有别的任何资源已经超过限额了仍然再占用资源

为避免GitHub的CDN抽风加载不了新内容,所有新更新已使用Gitlab仓库

由于speedtest-go的release依赖于GitHub,所以请检查 www.githubstatus.com ,有问题时无法安装带宽占用

基础开发完毕,测试中,有问题请在issues中反馈

选项1安装,选项2卸载,选项3更新安装引导脚本,选项4退出脚本

安装过程中无脑回车则全部可选的占用都占用,不需要什么占用输入n再回车

如果选择带宽占用,会询问使用speedtest-go占用还是使用wget占用,按照提示进行选择即可

有询问是否需要带宽占用的参数自定义,这时候默认选项就是n,回车就使用默认配置,输入y再回车则需要按照提示自定义参数

curl -L https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh -o oalive.sh && chmod +x oalive.sh && bash oalive.sh

bash oalive.sh

bash <(wget -qO- --no-check-certificate https://gitlab.com/spiritysdx/Oracle-server-keep-alive-script/-/raw/main/oalive.sh)

说明

  • 提供两种CPU占用模式:DD模拟占用和科学计算模式,用户可以自由选择,占用范围设置在15%至25%之间,更推荐DD模拟占用
  • DD模拟占用在守护进程中设置了CPU占用的最高限制
  • 默认情况下,CPU占用设置为25%最高值,计算方法是核数乘以12%,如果计算结果低于25%,则设置为该值;如果计算结果高于25%,则按照计算结果的比例进行设置。
  • 内存占用设置为占用总内存的20%,占用时间为300秒,休息时间为300秒。
  • 每300秒检测一次内存占用情况,并根据需要动态调整占用大小。如果内存占用已经大于20%,则不增加占用。
  • 在占用过程中,使用守护进程和开机自启服务,以确保占用任务持续且有效。
  • 默认选项的带宽占用每45分钟下载一次大小在1G至10G之间的文件,只进行下载而不保存。在下载过程中会占用硬盘空间,但在下载完成后会自动释放。
  • 默认选项的带宽占用动态调整实际下载的带宽/速率,限制每次下载的最长时长为6分钟。在每次下载之前,会测试最大可用带宽,并根据实时结果将下载速率设置为30%的带宽。
  • 带宽占用测试使用了speedtest-cli和speedtest-go两种工具,以防其中之一不可用时使用第二种工具,用户可以自定义设置带宽占用,此时详见设置提示。
  • 提供一键卸载所有占用服务的选项,卸载将删除所有脚本、服务、任务、守护进程和开机自启设置。
  • 提供一键检查更新的功能,更新范围仅限于脚本更新。请在更新后重新设置占用服务
  • 对所有进程执行增加唯一性检测,避免重复运行,使用PID文件进行判断。

如若不希望一键的,希望自定义设置时间的,请查看README_CRON.md自行设置定时任务

+ \ No newline at end of file diff --git a/case/case6.html b/case/case6.html index f9a9372a78..367b6e198a 100644 --- a/case/case6.html +++ b/case/case6.html @@ -5,22 +5,25 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/spiritLHLS/addswap

addswap

为openvz、kvm虚拟化的linux服务器增加swap分区(虚拟内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

已增加openvz架构重启swap自动添加的

openvz这个添加=掩耳盗铃,实际受到虚拟化限制应该是无法添加的,只能由虚拟化的宿主机控制,同理LXC虚拟化的也只能由宿主机控制,都无法自主添加虚拟内存SWAP

因此,该项目不再更新,除非另有需求

单位换算:输入 1024 产生 1G SWAP内存

致谢

kvm分区原版脚本源自 https://www.moerats.com/

bash
curl -L https://www.moerats.com/usr/shell/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

openVZ分区原版脚本源自

http://linux-problem-solver.blogspot.com/2013/08/create-fake-swap-in-openvz-vps-if-you-get-swapon-failed-operation-not-permitted-error.html

感谢 @fscarmen 提供优化建议

- +
Skip to content

仓库

https://github.com/spiritLHLS/addswap

addswap

为openvz、kvm虚拟化的linux服务器增加swap分区(虚拟内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

已增加openvz架构重启swap自动添加的

openvz这个添加=掩耳盗铃,实际受到虚拟化限制应该是无法添加的,只能由虚拟化的宿主机控制,同理LXC虚拟化的也只能由宿主机控制,都无法自主添加虚拟内存SWAP

因此,该项目不再更新,除非另有需求

单位换算:输入 1024 产生 1G SWAP内存

致谢

kvm分区原版脚本源自 https://www.moerats.com/

bash
curl -L https://www.moerats.com/usr/shell/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

openVZ分区原版脚本源自

http://linux-problem-solver.blogspot.com/2013/08/create-fake-swap-in-openvz-vps-if-you-get-swapon-failed-operation-not-permitted-error.html

感谢 @fscarmen 提供优化建议

+ \ No newline at end of file diff --git a/case/case7.html b/case/case7.html index bd8e3fa132..34cae9d063 100644 --- a/case/case7.html +++ b/case/case7.html @@ -5,22 +5,25 @@ 仓库 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/spiritLHLS/addzram

addzram

为linux服务器启用zram(压缩内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

类同前面的addswap项目

同样是给机器优化内存占用的东西,只不过zram是压缩内存占用,swap是附加虚拟内存增加内存空间,二者都会占用CPU资源,zram在CPU性能冗余的机器上使用更优

(理论上zram会比swap的性能占用低,但未实际测试过)

单位换算:输入 1024 产生 1G 的 zram 设备压缩内存,zram 设备大小不能大于实际内存大小

致谢

感谢 @Ella-Alinda 提供优化建议

- +
Skip to content

仓库

https://github.com/spiritLHLS/addzram

addzram

为linux服务器启用zram(压缩内存)

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

类同前面的addswap项目

同样是给机器优化内存占用的东西,只不过zram是压缩内存占用,swap是附加虚拟内存增加内存空间,二者都会占用CPU资源,zram在CPU性能冗余的机器上使用更优

(理论上zram会比swap的性能占用低,但未实际测试过)

单位换算:输入 1024 产生 1G 的 zram 设备压缩内存,zram 设备大小不能大于实际内存大小

致谢

感谢 @Ella-Alinda 提供优化建议

+ \ No newline at end of file diff --git a/case/index.html b/case/index.html index 345660592e..9d2f0d0136 100644 --- a/case/index.html +++ b/case/index.html @@ -5,22 +5,25 @@ 其他实用项目 | 与Linux相关的其他实用项目 - + + + - - - - - + + + + + - + + -
Skip to content

其他实用项目

与Linux相关的其他实用项目

- +
Skip to content

其他实用项目与Linux相关的其他实用项目

+ \ No newline at end of file diff --git a/developer/index.html b/developer/index.html index b41926e8fb..232a7b80cc 100644 --- a/developer/index.html +++ b/developer/index.html @@ -5,22 +5,25 @@ 开发手册 | 欢迎使用一键虚拟化项目开发手册,欢迎你提出高质量的Pull Request,帮助一键虚拟化项目变得更好! - + + + - - - - - + + + + + - + + -
Skip to content

开发手册

开发手册

- +
Skip to content

开发手册开发手册

+ \ No newline at end of file diff --git a/developer/l10n.html b/developer/l10n.html index 04870907cf..9a6e749522 100644 --- a/developer/l10n.html +++ b/developer/l10n.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

你可以在开发新功能时遵循以下步骤来支持本地化

介绍

  1. 你可以直接使用 /resource/l10n/zh-CN.toml 中已有的文本配置来替换新功能中的文本
  2. 如果新功能中有新增文本,请参考 zh-CN.toml 的配置文本,将新文本拉取到 zh-CN.toml 等其他语言的配置文件中,并添加翻译

新本地化文本的添加

  1. /resource/l10n/ 中添加新的语言文本配置
  2. 在新的语言文本配置中拉取其他语言已有的文本配置
  3. 为新的语言文本配置添加翻译
- +
Skip to content

你可以在开发新功能时遵循以下步骤来支持本地化

介绍

  1. 你可以直接使用 /resource/l10n/zh-CN.toml 中已有的文本配置来替换新功能中的文本
  2. 如果新功能中有新增文本,请参考 zh-CN.toml 的配置文本,将新文本拉取到 zh-CN.toml 等其他语言的配置文件中,并添加翻译

新本地化文本的添加

  1. /resource/l10n/ 中添加新的语言文本配置
  2. 在新的语言文本配置中拉取其他语言已有的文本配置
  3. 为新的语言文本配置添加翻译
+ \ No newline at end of file diff --git a/en/developer/index.html b/en/developer/index.html index 7e3e8ad7c1..a56c30af88 100644 --- a/en/developer/index.html +++ b/en/developer/index.html @@ -5,22 +5,25 @@ Development Manual | Welcome to the oneclickvirt Development Manual. - + + + - - - - - + + + + + - + + -
Skip to content

Development Manual

Welcome to the oneclickvirt Development Manual.

- +
Skip to content

Development ManualWelcome to the oneclickvirt Development Manual.

+ \ No newline at end of file diff --git a/en/developer/l10n.html b/en/developer/l10n.html index befc103c1f..857fb4e200 100644 --- a/en/developer/l10n.html +++ b/en/developer/l10n.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

You can follow these steps to support localization when developing new features

Introduction

  1. You can directly use the text configuration already available in /resource/l10n/en-US.toml to replace the text in the new feature.
  2. If there is new text in the new feature, please refer to the configuration text in en-US.toml, pull the new text into the configuration files of other languages such as en-US.toml, and add translations.

Adding a new localized text file

  1. Add a new language text configuration in /resource/l10n/.
  2. Pull existing text configurations from other languages in the new language text configuration.
  3. Add translations for the new language text configuration.
- +
Skip to content

You can follow these steps to support localization when developing new features

Introduction

  1. You can directly use the text configuration already available in /resource/l10n/en-US.toml to replace the text in the new feature.
  2. If there is new text in the new feature, please refer to the configuration text in en-US.toml, pull the new text into the configuration files of other languages such as en-US.toml, and add translations.

Adding a new localized text file

  1. Add a new language text configuration in /resource/l10n/.
  2. Pull existing text configurations from other languages in the new language text configuration.
  3. Add translations for the new language text configuration.
+ \ No newline at end of file diff --git a/en/guide/block/block_docker.html b/en/guide/block/block_docker.html index 505324e4be..8c24a07cf8 100644 --- a/en/guide/block/block_docker.html +++ b/en/guide/block/block_docker.html @@ -5,22 +5,25 @@ To be developed, stay tuned | One Click Virtualization - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/en/guide/block/block_incus.html b/en/guide/block/block_incus.html index 9e88992e91..3d7940ba8f 100644 --- a/en/guide/block/block_incus.html +++ b/en/guide/block/block_incus.html @@ -5,22 +5,25 @@ Blocking Abusive Behavior via Shell Scripts | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
- +
Skip to content

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
+ \ No newline at end of file diff --git a/en/guide/block/block_iptables.html b/en/guide/block/block_iptables.html index 38e84538ce..e92ed4de36 100644 --- a/en/guide/block/block_iptables.html +++ b/en/guide/block/block_iptables.html @@ -5,75 +5,78 @@ Blocking abuse through iptables | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Blocking abuse through iptables

Basic Usage of iptables

1. Start iptables

In most Linux distributions, the iptables service can be started using the following command:

bash
sudo systemctl start iptables

2. Set Rules

After starting iptables, you can set rules to block abusive traffic. For example, the following command will block traffic from a specific IPv4 address:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. Query Rules

After setting the rules, you can use the following command to view the current iptables rules:

bash
sudo iptables -L

This will list all input, output, and forwarding rules.

4. Stop iptables

If you need to stop the iptables service, you can use the following command:

bash
sudo systemctl stop iptables

5. Save Rules

To ensure that the rules persist after a reboot, you can save the current rules:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. Restore Rules

When you need to restore the rules, you can use the following command:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. Other Common Commands

  • List Rules (Detailed Information):

    bash
    sudo iptables -L -v
  • Delete Specific Rule:

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • Flush All Rules:

    bash
    sudo iptables -F

Block abusive traffic on the host

  • prevention in advance

Blocking Mining Behavior

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking BT behavior

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

Blocking Speed Test Behavior

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
- +
Skip to content

Blocking abuse through iptables

Basic Usage of iptables

1. Start iptables

In most Linux distributions, the iptables service can be started using the following command:

bash
sudo systemctl start iptables

2. Set Rules

After starting iptables, you can set rules to block abusive traffic. For example, the following command will block traffic from a specific IPv4 address:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. Query Rules

After setting the rules, you can use the following command to view the current iptables rules:

bash
sudo iptables -L

This will list all input, output, and forwarding rules.

4. Stop iptables

If you need to stop the iptables service, you can use the following command:

bash
sudo systemctl stop iptables

5. Save Rules

To ensure that the rules persist after a reboot, you can save the current rules:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. Restore Rules

When you need to restore the rules, you can use the following command:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. Other Common Commands

  • List Rules (Detailed Information):

    bash
    sudo iptables -L -v
  • Delete Specific Rule:

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • Flush All Rules:

    bash
    sudo iptables -F

Block abusive traffic on the host

  • prevention in advance

Blocking Mining Behavior

strings=(
+    "ethermine.com"
+    "antpool.one"
+    "antpool.com"
+    "pool.bar"
+    "get_peers"
+    "announce_peer"
+    "find_node"
+    "seed_hash"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

Blocking BT behavior

strings=(
+    "torrent"
+    ".torrent"
+    "peer_id="
+    "announce"
+    "info_hash"
+    "get_peers"
+    "find_node"
+    "BitTorrent"
+    "announce_peer"
+    "BitTorrent protocol"
+    "announce.php?passkey="
+    "magnet:"
+    "xunlei"
+    "sandai"
+    "Thunder"
+    "XLLiveUD"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

Blocking Speed Test Behavior

strings=(
+    ".speed"
+    "speed."
+    ".speed."
+    "fast.com"
+    "speedtest.net"
+    "speedtest.com"
+    "speedtest.cn"
+    "test.ustc.edu.cn"
+    "10000.gd.cn"
+    "db.laomoe.com"
+    "jiyou.cloud"
+    "ovo.speedtestcustom.com"
+    "speed.cloudflare.com"
+    "speedtest"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done
+ \ No newline at end of file diff --git a/en/guide/block/block_lxd.html b/en/guide/block/block_lxd.html index 436a969c5f..19bee4b020 100644 --- a/en/guide/block/block_lxd.html +++ b/en/guide/block/block_lxd.html @@ -5,22 +5,25 @@ Blocking Abusive Behavior via Shell Scripts | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
- +
Skip to content

Blocking Abusive Behavior via Shell Scripts

Blocking Ingress/Egress Traffic on Easily Abused Ports and Filtering Out Port Scanning and Exploitation Toolkits

  • (Optional, this script is solely for preventing container abuse and is not mandatory to install.)
  • Precautionary Measures

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

Use the 'screen' command to configure monitoring and blocking of certain processes' commands: terminate containers immediately upon the appearance of specific processes.

  • To stop monitoring, you can use the 'screen' command to stop the window named 'lxc_monitor' and delete it.
  • (Optional, this script is only for preventing misuse of containers; it's fine not to install it.)
  • Shutdown afterwards.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
+ \ No newline at end of file diff --git a/en/guide/block/block_pve.html b/en/guide/block/block_pve.html index 340bfc0e52..e363f264cf 100644 --- a/en/guide/block/block_pve.html +++ b/en/guide/block/block_pve.html @@ -5,24 +5,27 @@ Avoid theft by setting up a firewall to limit the IPs used by the VMs | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Avoid theft by setting up a firewall to limit the IPs used by the VMs

Create the following file under the PVE's host machine

shell
/etc/pve/firewall/<VMID>.fw
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID> is replaced with the VMID number of the virtual machine, <net0> is replaced with the corresponding alias in the network device (which generally doesn't need to be changed unless you're restricted to IPV6), and xxx.xxx.xxx.xxx is replaced with the public IP address, noting that this IP corresponds to the network device in front of it.

The idea here is that net0 can only use the IP xxx.xxx.xxx.xxx, if you use any other IP the data will be dropped, thus restricting the VM to only use this IP.

There can be more than one IP, once this rule is enabled the VM can't use any other IP, if you don't write an IPv6 address it means the VM can't use an IPv6 address.

TIP

This setting is only recommended when opening VMs with separate IPs that are not NAT full port mapped, otherwise it may cause strange issues resulting in the server being without a network.

This method is not suitable for use on PVEs that open any NAT VMs/containers.

- +
Skip to content

Avoid theft by setting up a firewall to limit the IPs used by the VMs

Create the following file under the PVE's host machine

shell
/etc/pve/firewall/<VMID>.fw
+[IPSET ipfilter-<net0>]
+xxx.xxx.xxx.xxx

<VMID> is replaced with the VMID number of the virtual machine, <net0> is replaced with the corresponding alias in the network device (which generally doesn't need to be changed unless you're restricted to IPV6), and xxx.xxx.xxx.xxx is replaced with the public IP address, noting that this IP corresponds to the network device in front of it.

The idea here is that net0 can only use the IP xxx.xxx.xxx.xxx, if you use any other IP the data will be dropped, thus restricting the VM to only use this IP.

There can be more than one IP, once this rule is enabled the VM can't use any other IP, if you don't write an IPv6 address it means the VM can't use an IPv6 address.

TIP

This setting is only recommended when opening VMs with separate IPs that are not NAT full port mapped, otherwise it may cause strange issues resulting in the server being without a network.

This method is not suitable for use on PVEs that open any NAT VMs/containers.

+ \ No newline at end of file diff --git a/en/guide/dashboard.html b/en/guide/dashboard.html index ee1d24612f..f5c6ac8545 100644 --- a/en/guide/dashboard.html +++ b/en/guide/dashboard.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Preparation Work

To virtualize a server, you will need:

  1. A server (VPS or Dedicated Server) that can connect to the public internet. It's preferable if this server can access GitHub's RAW pages perfectly, as some projects and components might not use CDN acceleration.

  2. A stable SSH connection from your local machine. If the connection isn't stable, you can use the screen command to create a window and execute commands within that window.

TIP

If you're unfamiliar with the screen command, please search for relevant tutorials to learn it, or you can use tmux as an alternative.

  1. Ensure that the server's system and hardware meet the requirements specified by the corresponding project. Refer to the project's documentation for detailed information.

This document will use a VPS as an example, and the VPS should be clean without any native environment issues. If necessary, reinstall the system to ensure the initial environment's cleanliness.

WARNING

The PVE project might cause problems on the host machine. If you're not familiar with debugging bugs and fixing system issues, it's not recommended to use PVE in a production environment. When using PVE-related scripts, make sure the host machine can be reinstalled at any time.

Project Repository

Welcome Star and Fork, all resources are open source, no non-open source parts, reproduced as well as the use of please write on the source of this site, thank you!

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

- +
Skip to content

Preparation Work

To virtualize a server, you will need:

  1. A server (VPS or Dedicated Server) that can connect to the public internet. It's preferable if this server can access GitHub's RAW pages perfectly, as some projects and components might not use CDN acceleration.

  2. A stable SSH connection from your local machine. If the connection isn't stable, you can use the screen command to create a window and execute commands within that window.

TIP

If you're unfamiliar with the screen command, please search for relevant tutorials to learn it, or you can use tmux as an alternative.

  1. Ensure that the server's system and hardware meet the requirements specified by the corresponding project. Refer to the project's documentation for detailed information.

This document will use a VPS as an example, and the VPS should be clean without any native environment issues. If necessary, reinstall the system to ensure the initial environment's cleanliness.

WARNING

The PVE project might cause problems on the host machine. If you're not familiar with debugging bugs and fixing system issues, it's not recommended to use PVE in a production environment. When using PVE-related scripts, make sure the host machine can be reinstalled at any time.

Project Repository

Welcome Star and Fork, all resources are open source, no non-open source parts, reproduced as well as the use of please write on the source of this site, thank you!

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

+ \ No newline at end of file diff --git a/en/guide/dashboardq.html b/en/guide/dashboardq.html index 7c13a0f19d..8093e7b270 100644 --- a/en/guide/dashboardq.html +++ b/en/guide/dashboardq.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/en/guide/docker/docker_android.html b/en/guide/docker/docker_android.html index 981d5ae921..4c559976dd 100644 --- a/en/guide/docker/docker_android.html +++ b/en/guide/docker/docker_android.html @@ -5,27 +5,30 @@ Running Android Virtual Machine in Docker | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Running Android Virtual Machine in Docker

One-Click Deployment

  • Customizable Android version
  • Automatically creates a validated web website
  • Automatically installs Nginx and configures reverse proxy. Option to bind a domain is available. Default is port 80 if no domain binding is chosen.
  • No need to worry about host machine supporting nested virtualization
  • Supports x86_64 and ARM architectures

Host machine should have a minimum configuration of 1 core, 2GB RAM, and 15GB storage, else starting the setup might lead to host machine freezing.

Ubuntu is recommended for hosting, Debian may cause white screen on Android.

Newer Android versions occupy more resources. The above configuration requirements are for the minimum version of Android. (Personally tested with the tag "12.0.0-latest", higher versions resulted in a blank screen. Test which version works for you.)

If, after 5 minutes after opening, the login verification of the browser page still keeps failing, then please check the logs of the Android container, it is probable that the Android container has crashed, and it is recommended to replace the container with a lower version of the Android system for installation.

Setup:

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

After executing the command, follow the prompts to input the required information. Make sure to choose the version by entering the corresponding number index. Once the installation is complete, open YourMachineIPv4+80Port to log in.

If you need to check the generated Android information and web login details, execute cat /root/android_info to retrieve the information.

Default username: onea Default password: oneclick

For remote desktop, click on H264 Converter to initiate the redirection.

Please note that currently only one Android container can be generated. Do not generate duplicates. If you need to replace the version, please execute the subsequent commands after deletion.

Temporarily only support the opening has been used, can not restart the server, reboot may not be able to restart after the mapping success, self-test

Deletion:

  • Delete the container
  • Delete the corresponding container image
  • Delete the configuration file
shell
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
- +
Skip to content

Running Android Virtual Machine in Docker

One-Click Deployment

  • Customizable Android version
  • Automatically creates a validated web website
  • Automatically installs Nginx and configures reverse proxy. Option to bind a domain is available. Default is port 80 if no domain binding is chosen.
  • No need to worry about host machine supporting nested virtualization
  • Supports x86_64 and ARM architectures

Host machine should have a minimum configuration of 1 core, 2GB RAM, and 15GB storage, else starting the setup might lead to host machine freezing.

Ubuntu is recommended for hosting, Debian may cause white screen on Android.

Newer Android versions occupy more resources. The above configuration requirements are for the minimum version of Android. (Personally tested with the tag "12.0.0-latest", higher versions resulted in a blank screen. Test which version works for you.)

If, after 5 minutes after opening, the login verification of the browser page still keeps failing, then please check the logs of the Android container, it is probable that the Android container has crashed, and it is recommended to replace the container with a lower version of the Android system for installation.

Setup:

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

After executing the command, follow the prompts to input the required information. Make sure to choose the version by entering the corresponding number index. Once the installation is complete, open YourMachineIPv4+80Port to log in.

If you need to check the generated Android information and web login details, execute cat /root/android_info to retrieve the information.

Default username: onea Default password: oneclick

For remote desktop, click on H264 Converter to initiate the redirection.

Please note that currently only one Android container can be generated. Do not generate duplicates. If you need to replace the version, please execute the subsequent commands after deletion.

Temporarily only support the opening has been used, can not restart the server, reboot may not be able to restart after the mapping success, self-test

Deletion:

  • Delete the container
  • Delete the corresponding container image
  • Delete the configuration file
shell
docker rm -f android
+docker rmi $(docker images | grep "redroid" | awk '{print $3}')
+rm -rf /etc/nginx/sites-enabled/reverse-proxy
+rm -rf /etc/nginx/sites-available/reverse-proxy
+rm -rf /etc/nginx/passwd_scrcpy_web
+rm -rf /root/android_info
+ \ No newline at end of file diff --git a/en/guide/docker/docker_build.html b/en/guide/docker/docker_build.html index 6ca7591503..da92781422 100644 --- a/en/guide/docker/docker_build.html +++ b/en/guide/docker/docker_build.html @@ -5,45 +5,48 @@ Introduction | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Introduction

There are two methods of building

Setting Up Standalone

  • Generate only one docker
  • Can be configured to bind a separate IPV6 address, but requires a docker previously installed using the environment installation command of this set of scripts, and requires the host to be bound to at least the /112 IPV6 subnet
  • Support for x86_64 and ARM architecture servers

Download the Script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

Example

Run

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

Currently, the system only supports selecting:

  • alpine
  • debian
  • ubuntu
  • almalinux

with Debian being the default choice.

The following is the information for the created example container:

AttributeValue
Container Nametest
Username for SSH Loginroot
Password for SSH Login123456
Number of CPU Cores1
Memory Size512MB
SSH Port25000
Port Range for Internal and External Mapping34975 to 35000
Operating Systemdebian
Whether to bind a separate IPV6 addressN
shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

Deleting the test container

shell
docker rm -f test
-rm -rf test
-ls

Accessing the test container

shell
docker exec -it test /bin/bash

To exit the container, simply execute exit.

Inquiry Information

shell
cat Container_Name(change me)

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

The docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration

Batch Deployment

  • Run inheritance configuration generation multiple times in bulk.
  • When generating multiple instances, it is recommended to execute within a screen session to avoid SSH connection interruptions.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

Querying information on batch openings

shell
cat dclog

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

One line corresponds to information about a container, the docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration.

Uninstall all Docker containers and images

The following command offload ignores ndpresponder to prevent IPV6 configuration failure

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

Start all containers after host reboot

The default containers are not set to restart themselves after stopping, you need to execute the following command to start all stopped containers.

docker start $(docker ps -aq)

Start SSH service for all containers after host reboot

Since the container itself does not have a daemon, the SSH service cannot start itself, and you need to execute the following command to start the SSH process for all containers.

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
- +
Skip to content

Introduction

There are two methods of building

Setting Up Standalone

  • Generate only one docker
  • Can be configured to bind a separate IPV6 address, but requires a docker previously installed using the environment installation command of this set of scripts, and requires the host to be bound to at least the /112 IPV6 subnet
  • Support for x86_64 and ARM architecture servers

Download the Script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

Example

Run

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

Currently, the system only supports selecting:

  • alpine
  • debian
  • ubuntu
  • almalinux

with Debian being the default choice.

The following is the information for the created example container:

AttributeValue
Container Nametest
Username for SSH Loginroot
Password for SSH Login123456
Number of CPU Cores1
Memory Size512MB
SSH Port25000
Port Range for Internal and External Mapping34975 to 35000
Operating Systemdebian
Whether to bind a separate IPV6 addressN
shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

Deleting the test container

shell
docker rm -f test
+rm -rf test
+ls

Accessing the test container

shell
docker exec -it test /bin/bash

To exit the container, simply execute exit.

Inquiry Information

shell
cat Container_Name(change me)

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

The docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration

Batch Deployment

  • Run inheritance configuration generation multiple times in bulk.
  • When generating multiple instances, it is recommended to execute within a screen session to avoid SSH connection interruptions.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

Querying information on batch openings

shell
cat dclog

The output format is

Container_Name SSH_Port Root_Password Number_of_Cores Memory Start_of_Public_Port End_of_Public_Port

One line corresponds to information about a container, the docker's ipv6 address can only be looked up within the container itself, it doesn't exist in the docker's configuration.

Uninstall all Docker containers and images

The following command offload ignores ndpresponder to prevent IPV6 configuration failure

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
+docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
+rm -rf dclog
+ls

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/onedocker.sh
+rm -rf /root/create_docker.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

Start all containers after host reboot

The default containers are not set to restart themselves after stopping, you need to execute the following command to start all stopped containers.

docker start $(docker ps -aq)

Start SSH service for all containers after host reboot

Since the container itself does not have a daemon, the SSH service cannot start itself, and you need to execute the following command to start the SSH process for all containers.

container_ids=$(docker ps -q)
+for container_id in $container_ids
+do
+    docker exec -it $container_id bash -c "service ssh start"
+    docker exec -it $container_id bash -c "service sshd restart"
+    docker exec -it $container_id sh -c "service ssh start"
+    docker exec -it $container_id sh -c "/usr/sbin/sshd"
+done
+ \ No newline at end of file diff --git a/en/guide/docker/docker_custom.html b/en/guide/docker/docker_custom.html index 67925dc398..3a3690962b 100644 --- a/en/guide/docker/docker_custom.html +++ b/en/guide/docker/docker_custom.html @@ -5,31 +5,34 @@ Script for One-Click Installation of Certain Containers using Docker | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Script for One-Click Installation of Certain Containers using Docker

Each container has specific configuration requirements; please refer to them individually.

If the configured memory is not enough, then it's okay to make up for it with the virtual memory here.

Note that the following scripts must be pre-installed using the environment installation scripts in this set of tutorials before using them

One-Click Setup of Firefox Browser Container

  • Crash recovery on startup has been configured.
  • Chinese fonts have been integrated into the container.
  • Built-in web validation with the option to set a custom password.
  • Maximum memory usage for the container is customizable.
  • Choice to enable VNC port, disabled by default.
  • No need to consider support for nested virtualization or server architecture.
  • Audio mapping is not supported; sound transmission is unavailable on both the web and VNC.

The host machine should have at least 1 core, 1GB RAM, and 5GB disk space. The created container will occupy a minimum of 1GB disk space.

Setup:

After setup, the default password is oneclick.

The default web port is 3003. Once the setup is complete, simply open HOST_IPV4:PORT in your browser.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

Deletion

Modify the following port number 3003 to your actual port number, and then execute the command to delete the container, configuration file, and corresponding image

shell
PORT="3003"
-docker stop firefox_${PORT}
-docker rm -f firefox_${PORT}
-rm -rf /usr/local/bin/firefox_${PORT}
-docker rmi jlesage/firefox

One-Click Setup of Chrome Browser Container

  • Crashing self-start has been set
  • Web checksums and passwords can be set.
  • Customizable maximum container memory footprint
  • No need to consider whether to support nested virtualization and server architecture.
  • Supports sound mapping

Host requires at least 1 core, 2G RAM, and 10G hard disk, and the size of the container to be opened will take up a minimum of 1G hard disk

It is better to hang the execution in the screen during the first installation, to avoid long running SSH connection disconnection

Opening

If no custom username is set, the default username after opening is oneclick.

If no custom password is set, the default password after opening is oneclick.

The default http port is 3004, open http://IPV4:3004 after opening.

The default https port is 3005, open https://IPV4:3005 after opening.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

Delete

Change the following port number 3004 to your actual http port number, then execute the command enter twice to delete the container, configuration file, and corresponding image

shell
PORT="3004"
-docker stop chromium_${PORT}
-docker rm -f chromium_${PORT}
-rm -rf /usr/local/bin/config_${PORT}
-rm -rf /usr/local/bin/password_${PORT}
-docker rmi lscr.io/linuxserver/chromium

One-Click Setup of Desktop Container

  • Crashes automatically restart have been configured.
  • Chinese fonts are included in the setup.
  • Built-in web validation with the ability to set your own username and password.
  • Customizable maximum memory usage for the container.
  • No need to consider nested virtualization support and server architecture.
  • Sound mapping is supported, and sound can be transmitted via the web interface.

A complete Linux desktop on which you can use a browser

The host system requires at least 1 core, 2 GB of RAM, and 5 GB of hard disk space. The created container will occupy a minimum of 3.2 GB of hard disk space.

Setup Instructions:

After setup, the default username is onew and the password is oneclick. The default maximum memory usage is 2 GB.

The default web port for HTTP protocol is 3004, and for HTTPS protocol is 3005. After setup, open the corresponding protocol with localhost's IPV4:port in your web browser.

Run the following command to download and execute the setup script:

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

Deletion

Command:

shell
docker ps -a

Query for containers with a prefix of 'webtop' in their names, and record the IDs of these containers.

shell
docker rm -f container_ID

To remove the corresponding image, you can use the following command after deleting all associated containers:

shell
docker rmi lscr.io/linuxserver/webtop

One-Click Installation of Guacamole

A web-based tool for controlling servers using protocols like SSH or RDP.

Website: http://your_IPV4_address:80/guacamole

Default Username: guacadmin

Default Password: guacadmin

After installation, remember to change the password upon login.

The host machine should have at least 1 core, 2GB RAM, and 10GB of disk space; otherwise, launching might lead to host machine freezing!

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh
- +
Skip to content

Script for One-Click Installation of Certain Containers using Docker

Each container has specific configuration requirements; please refer to them individually.

If the configured memory is not enough, then it's okay to make up for it with the virtual memory here.

Note that the following scripts must be pre-installed using the environment installation scripts in this set of tutorials before using them

One-Click Setup of Firefox Browser Container

  • Crash recovery on startup has been configured.
  • Chinese fonts have been integrated into the container.
  • Built-in web validation with the option to set a custom password.
  • Maximum memory usage for the container is customizable.
  • Choice to enable VNC port, disabled by default.
  • No need to consider support for nested virtualization or server architecture.
  • Audio mapping is not supported; sound transmission is unavailable on both the web and VNC.

The host machine should have at least 1 core, 1GB RAM, and 5GB disk space. The created container will occupy a minimum of 1GB disk space.

Setup:

After setup, the default password is oneclick.

The default web port is 3003. Once the setup is complete, simply open HOST_IPV4:PORT in your browser.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

Deletion

Modify the following port number 3003 to your actual port number, and then execute the command to delete the container, configuration file, and corresponding image

shell
PORT="3003"
+docker stop firefox_${PORT}
+docker rm -f firefox_${PORT}
+rm -rf /usr/local/bin/firefox_${PORT}
+docker rmi jlesage/firefox

One-Click Setup of Chrome Browser Container

  • Crashing self-start has been set
  • Web checksums and passwords can be set.
  • Customizable maximum container memory footprint
  • No need to consider whether to support nested virtualization and server architecture.
  • Supports sound mapping

Host requires at least 1 core, 2G RAM, and 10G hard disk, and the size of the container to be opened will take up a minimum of 1G hard disk

It is better to hang the execution in the screen during the first installation, to avoid long running SSH connection disconnection

Opening

If no custom username is set, the default username after opening is oneclick.

If no custom password is set, the default password after opening is oneclick.

The default http port is 3004, open http://IPV4:3004 after opening.

The default https port is 3005, open https://IPV4:3005 after opening.

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

Delete

Change the following port number 3004 to your actual http port number, then execute the command enter twice to delete the container, configuration file, and corresponding image

shell
PORT="3004"
+docker stop chromium_${PORT}
+docker rm -f chromium_${PORT}
+rm -rf /usr/local/bin/config_${PORT}
+rm -rf /usr/local/bin/password_${PORT}
+docker rmi lscr.io/linuxserver/chromium

One-Click Setup of Desktop Container

  • Crashes automatically restart have been configured.
  • Chinese fonts are included in the setup.
  • Built-in web validation with the ability to set your own username and password.
  • Customizable maximum memory usage for the container.
  • No need to consider nested virtualization support and server architecture.
  • Sound mapping is supported, and sound can be transmitted via the web interface.

A complete Linux desktop on which you can use a browser

The host system requires at least 1 core, 2 GB of RAM, and 5 GB of hard disk space. The created container will occupy a minimum of 3.2 GB of hard disk space.

Setup Instructions:

After setup, the default username is onew and the password is oneclick. The default maximum memory usage is 2 GB.

The default web port for HTTP protocol is 3004, and for HTTPS protocol is 3005. After setup, open the corresponding protocol with localhost's IPV4:port in your web browser.

Run the following command to download and execute the setup script:

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

Deletion

Command:

shell
docker ps -a

Query for containers with a prefix of 'webtop' in their names, and record the IDs of these containers.

shell
docker rm -f container_ID

To remove the corresponding image, you can use the following command after deleting all associated containers:

shell
docker rmi lscr.io/linuxserver/webtop

One-Click Installation of Guacamole

A web-based tool for controlling servers using protocols like SSH or RDP.

Website: http://your_IPV4_address:80/guacamole

Default Username: guacadmin

Default Password: guacadmin

After installation, remember to change the password upon login.

The host machine should have at least 1 core, 2GB RAM, and 10GB of disk space; otherwise, launching might lead to host machine freezing!

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh
+ \ No newline at end of file diff --git a/en/guide/docker/docker_install.html b/en/guide/docker/docker_install.html index bc0e701d7d..6539595a28 100644 --- a/en/guide/docker/docker_install.html +++ b/en/guide/docker/docker_install.html @@ -5,22 +5,25 @@ Preface | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Preface

Support for running Docker virtualization on various systems, including Linux, Android, and Windows.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Setting Up Virtual Memory

TIP

Allocate some swap space to prevent your machine from crashing.

Unit conversion: Inputting 1024 results in 1G of SWAP - virtual memory. Virtual memory occupies disk space and is automatically utilized when the physical memory is insufficient. However, this leads to high IO usage and CPU performance overhead.

It is recommended to allocate virtual memory twice the size of your physical memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Environment Setup

  • Detect the system environment and install the corresponding components
  • Install docker and docker-compose.
  • Download some configuration scripts required by default
  • Detect if there is an IPV6 address, check if it is greater than or equal to /112, and if so, configure the docker's ipv6 network.
  • If all the above conditions are met, create ndpresponder docker and radvd so that IPV6 allocation supports ndp broadcasting and auto-allocation.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

OR

bash dockerinstall.sh

TIP

The environment installation process may require you to reboot the server and then execute the script again, see the instructions after the script is run for more details

- +
Skip to content

Preface

Support for running Docker virtualization on various systems, including Linux, Android, and Windows.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Setting Up Virtual Memory

TIP

Allocate some swap space to prevent your machine from crashing.

Unit conversion: Inputting 1024 results in 1G of SWAP - virtual memory. Virtual memory occupies disk space and is automatically utilized when the physical memory is insufficient. However, this leads to high IO usage and CPU performance overhead.

It is recommended to allocate virtual memory twice the size of your physical memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Environment Setup

  • Detect the system environment and install the corresponding components
  • Install docker and docker-compose.
  • Download some configuration scripts required by default
  • Detect if there is an IPV6 address, check if it is greater than or equal to /112, and if so, configure the docker's ipv6 network.
  • If all the above conditions are met, create ndpresponder docker and radvd so that IPV6 allocation supports ndp broadcasting and auto-allocation.
  • Support for x86_64 and ARM architecture servers

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

OR

bash dockerinstall.sh

TIP

The environment installation process may require you to reboot the server and then execute the script again, see the instructions after the script is run for more details

+ \ No newline at end of file diff --git a/en/guide/docker/docker_macos.html b/en/guide/docker/docker_macos.html index f2633b840b..3f7554c052 100644 --- a/en/guide/docker/docker_macos.html +++ b/en/guide/docker/docker_macos.html @@ -5,22 +5,25 @@ Running macOS Virtual Machines in Docker | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page
- + + \ No newline at end of file diff --git a/en/guide/docker/docker_precheck.html b/en/guide/docker/docker_precheck.html index d5ad1cc7ce..641b739d9c 100644 --- a/en/guide/docker/docker_precheck.html +++ b/en/guide/docker/docker_precheck.html @@ -5,22 +5,25 @@ Introduction | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Introduction

The following is an introduction to the non-customized sections. Please ensure that you don't confuse them with the customized parts.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

WARNING

If the host has an IPV6 network, the installation will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/docker

Project Features

Bulk or individual NAT server provisioning via docker

Default use of debian system optional alpine system, each container comes with 1 external ssh port, 25 internal and external network ports, you can choose whether to bind IPV6 address

The default creation of unprivileged containers, and does not mount and host docker daemon communication, so ** host created docker virtualization NAT servers can not be nested within the virtualization docker **

By default, lxcfs is installed and enabled, so that when querying resources within a container, CPU and memory use the configured view instead of the host's view.

Since most cloud servers have ext4 filesystems, even xfs filesystems do not enable the pquota option, so sharing the host's hard disk by default does not limit the disk size of each container.

Configuration requirements

The system can be installed docker can be used, the network can connect to the Github raw interface can be used, hardware configuration as long as not pull across the line, free hard disk has 3G on it!

(If you need to bind an IPV6 address, then please make sure to use the installation script of this set of scripts for docker installation, you need it to automatically preset some of the settings)

If the hardware resources are just a little bit better, need to limit more things and need to limit the size of the hard disk, you can use the incus partition of the script batch open LXC virtualization containers

If the hardware is very good and you have a lot of resources, you can use the PVE partition script to batch open KVM virtualized VMs.

- +
Skip to content

Introduction

The following is an introduction to the non-customized sections. Please ensure that you don't confuse them with the customized parts.

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

WARNING

If the host has an IPV6 network, the installation will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/docker

Project Features

Bulk or individual NAT server provisioning via docker

Default use of debian system optional alpine system, each container comes with 1 external ssh port, 25 internal and external network ports, you can choose whether to bind IPV6 address

The default creation of unprivileged containers, and does not mount and host docker daemon communication, so ** host created docker virtualization NAT servers can not be nested within the virtualization docker **

By default, lxcfs is installed and enabled, so that when querying resources within a container, CPU and memory use the configured view instead of the host's view.

Since most cloud servers have ext4 filesystems, even xfs filesystems do not enable the pquota option, so sharing the host's hard disk by default does not limit the disk size of each container.

Configuration requirements

The system can be installed docker can be used, the network can connect to the Github raw interface can be used, hardware configuration as long as not pull across the line, free hard disk has 3G on it!

(If you need to bind an IPV6 address, then please make sure to use the installation script of this set of scripts for docker installation, you need it to automatically preset some of the settings)

If the hardware resources are just a little bit better, need to limit more things and need to limit the size of the hard disk, you can use the incus partition of the script batch open LXC virtualization containers

If the hardware is very good and you have a lot of resources, you can use the PVE partition script to batch open KVM virtualized VMs.

+ \ No newline at end of file diff --git a/en/guide/docker/docker_qa.html b/en/guide/docker/docker_qa.html index 800220660c..0c0f4d1fea 100644 --- a/en/guide/docker/docker_qa.html +++ b/en/guide/docker/docker_qa.html @@ -5,22 +5,25 @@ Solve the puzzle | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Solve the puzzle

Common Docker Commands

Check real-time resource usage of a specific container

docker stats <container_name>

Enter a specific container

docker exec -it <container_name> /bin/bash

Clean Docker cache, remove unused resources including images, containers, networks, etc.

docker system prune -a

Uninstall all Docker images and containers

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

View logs of a specific container

docker logs <container_name_or_ID>

View overall disk usage of Docker

docker system df

List all containers

docker ps -a

List all images

docker images

Remove a specific container

docker rm -f <container_name_or_ID>

Remove a specific image

docker rmi <image_name_or_ID>
- +
Skip to content

Solve the puzzle

Common Docker Commands

Check real-time resource usage of a specific container

docker stats <container_name>

Enter a specific container

docker exec -it <container_name> /bin/bash

Clean Docker cache, remove unused resources including images, containers, networks, etc.

docker system prune -a

Uninstall all Docker images and containers

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

View logs of a specific container

docker logs <container_name_or_ID>

View overall disk usage of Docker

docker system df

List all containers

docker ps -a

List all images

docker images

Remove a specific container

docker rm -f <container_name_or_ID>

Remove a specific image

docker rmi <image_name_or_ID>
+ \ No newline at end of file diff --git a/en/guide/docker/docker_thanks.html b/en/guide/docker/docker_thanks.html index d8b2f9a1f7..691a6e1e05 100644 --- a/en/guide/docker/docker_thanks.html +++ b/en/guide/docker/docker_thanks.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/en/guide/docker/docker_windows.html b/en/guide/docker/docker_windows.html index e740011e9b..1e85484f36 100644 --- a/en/guide/docker/docker_windows.html +++ b/en/guide/docker/docker_windows.html @@ -5,47 +5,50 @@ Running Windows Virtual Machine in Docker | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Running Windows Virtual Machine in Docker

One-Click Deployment (Using Vagrant)

  • Shares all resources of the host machine; based on Docker, so it only occupies the size of the system, suitable for multiple instances.
  • Shares IP; Docker's NAT mapping is employed. You can choose whether to map to the external network or just the internal network.
  • The configured Windows system is set to use a maximum of 1 core, 2GB RAM, and 50GB hard disk by default. Actual usage may vary based on usage patterns.
  • No need for iptables for NAT mapping; port mappings are automatically deleted when containers are removed, making maintenance easier.
  • Ensure that the host machine supports nested virtualization, and currently, only X86_64 architecture systems are supported. I haven't compiled corresponding images for ARM devices at the moment.

The host machine needs to support nested virtualization and currently only supports systems based on the X86_64 architecture; I don't have an ARM machine on hand to compile the corresponding image at the moment.

Command:

shell
egrep -c '(vmx|svm)' /proc/cpuinfo

The result should be greater than or equal to 1 and cannot be 0.

Next, you need to configure Docker to start using the v1 version of cgroup.

shell
sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

If there are no errors during execution, run the reboot command to restart the system and apply the settings.

Supported Images

We are using custom-built images: https://hub.docker.com/r/spiritlhl/wds

Image NameImage Size
1020GB
202217.5GB
201917GB

The size of the created container will be slightly larger than the image size, but not by much.

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

Usage Instructions

Make sure to execute the following commands in a 'screen' session before proceeding, to avoid potential disconnection or freezing of the SSH connection.

./onewindows.sh <container_name> <system_version> <RDP_port> <external_mapping>
  • Replace <container_name> with the name.
  • Replace <system_version> with the desired Windows system version.
  • Replace <RDP_port> with the port number for RDP access.
  • If you want to enable external mapping, replace <external_mapping> with 'Y'. If not, leave it blank or use 'N'.

Before initiating the setup, ensure that the host machine has a disk size at least twice the size of the image, plus an additional 10GB, as Docker needs to pull the image locally before creating the container.

During the creation process, the peak disk usage will be host_system_size + image_size + container_size.

For example, to set up a container with the name test, the container with the lowest occupancy Windows 2019 system, map the extranet RDP port 13389 and set it to extranet mapping (mapping to your server's extranet IPV4 address)

shell
./onewindows.sh test 2019 13389 Y

After it, the default usernames are Administrator and vagrant, with the default password being vagrant.

If you choose to open a mapped extranet port, be sure to log in and change the password of the corresponding account (both accounts may have, try it yourself), otherwise it may be abused by someone blasting

Deletion

To delete the corresponding image and container, first use the command docker ps -a and docker images to find the ID of the image named spiritlhl/wds. Then, use the following commands accordingly:

docker rm -f container_ID
-docker rmi image_ID

After deletion, you can create containers of different versions of Windows.

Other similar projects

https://github.com/dockur/windows - Similar project that support more systems, but have more resource requirements

https://github.com/dockur/windows-arm/ - It's great that he has ARM servers for mirror compilation, my project doesn't have

Note that both of the above projects require a host with at least 4 cores of CPU, at least 4G of RAM, and at least 64G of hard disk, which is greater than the mirroring requirements of my project. (The advantage of his project is that you can customize many configuration items, see his corresponding project description for details.)

Manual Provisioning (via the Dockur Project)

This project supports VM creation using QEMU even on host systems that do not support nested virtualization.

Original Project Repositories

⚠️ Notes:

  • The original project provides only the launcher, not a Windows image.

  • The first container startup may take up to 4 hours on domestic (China) networks, due to image download and installation.

  • The host system should meet the following minimum hardware requirements (can be adjusted via script modifications):

    • CPU: At least 4 cores
    • RAM: At least 4 GB
    • Disk: At least 64 GB

For customization such as reducing resource usage or changing launch parameters, refer to:

For x86_64 Architecture Users

A pre-modified single-file launcher is available to simplify building a Windows image. This version writes system files and images directly into Docker’s writable layer—no external image mounting required.

Download link: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

Import Docker image:

bash
docker load -i builder.tar

Launching the Container with a Custom Windows ISO

Download a Windows ISO image from: https://down.idc.wiki/ISOS/Windows/

Sample command to start the container:

bash
docker run -it -d \
-  -e RAM_SIZE="8G" \
-  -e CPU_CORES="4" \
-  --name win2022 \
-  -p 8006:8006 \
-  --device=/dev/kvm \
-  --device=/dev/net/tun \
-  --cap-add NET_ADMIN \
-  -v "$(pwd)/WindowsImage.iso:/boot.iso" \
-  --stop-timeout 120 \
-  windows:builder

We also offer a ready-to-use image with the system and configuration already integrated. Features:

  • Image size: ~26 GB (includes system image and default config)
  • Supports auto disk expansion and startup tasks
  • Just download, import, and run
  • ⚠️ Note: Combined download will require ~60 GB of free space

Download and Merge Split Files

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

Start the Container

bash
docker load -i win2022.tar
-docker run -it -d \
-  -e RAM_SIZE="4G" \
-  -e CPU_CORES="2" \
-  --name win2022 \
-  -p 8006:8006 \
-  --device=/dev/kvm \
-  --device=/dev/net/tun \
-  --cap-add NET_ADMIN \
-  --stop-timeout 120 \
-  windows:2022

Important Notes

It is not recommended to use docker commit to save changes to this image, as repeated layer stacking may cause the image size to exceed 40 GB.

For personalized configuration or additional software integration, always start from the builder image to ensure a clean and maintainable result.

- +
Skip to content

Running Windows Virtual Machine in Docker

One-Click Deployment (Using Vagrant)

  • Shares all resources of the host machine; based on Docker, so it only occupies the size of the system, suitable for multiple instances.
  • Shares IP; Docker's NAT mapping is employed. You can choose whether to map to the external network or just the internal network.
  • The configured Windows system is set to use a maximum of 1 core, 2GB RAM, and 50GB hard disk by default. Actual usage may vary based on usage patterns.
  • No need for iptables for NAT mapping; port mappings are automatically deleted when containers are removed, making maintenance easier.
  • Ensure that the host machine supports nested virtualization, and currently, only X86_64 architecture systems are supported. I haven't compiled corresponding images for ARM devices at the moment.

The host machine needs to support nested virtualization and currently only supports systems based on the X86_64 architecture; I don't have an ARM machine on hand to compile the corresponding image at the moment.

Command:

shell
egrep -c '(vmx|svm)' /proc/cpuinfo

The result should be greater than or equal to 1 and cannot be 0.

Next, you need to configure Docker to start using the v1 version of cgroup.

shell
sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
+update-grub
+ls

If there are no errors during execution, run the reboot command to restart the system and apply the settings.

Supported Images

We are using custom-built images: https://hub.docker.com/r/spiritlhl/wds

Image NameImage Size
1020GB
202217.5GB
201917GB

The size of the created container will be slightly larger than the image size, but not by much.

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

Usage Instructions

Make sure to execute the following commands in a 'screen' session before proceeding, to avoid potential disconnection or freezing of the SSH connection.

./onewindows.sh <container_name> <system_version> <RDP_port> <external_mapping>
  • Replace <container_name> with the name.
  • Replace <system_version> with the desired Windows system version.
  • Replace <RDP_port> with the port number for RDP access.
  • If you want to enable external mapping, replace <external_mapping> with 'Y'. If not, leave it blank or use 'N'.

Before initiating the setup, ensure that the host machine has a disk size at least twice the size of the image, plus an additional 10GB, as Docker needs to pull the image locally before creating the container.

During the creation process, the peak disk usage will be host_system_size + image_size + container_size.

For example, to set up a container with the name test, the container with the lowest occupancy Windows 2019 system, map the extranet RDP port 13389 and set it to extranet mapping (mapping to your server's extranet IPV4 address)

shell
./onewindows.sh test 2019 13389 Y

After it, the default usernames are Administrator and vagrant, with the default password being vagrant.

If you choose to open a mapped extranet port, be sure to log in and change the password of the corresponding account (both accounts may have, try it yourself), otherwise it may be abused by someone blasting

Deletion

To delete the corresponding image and container, first use the command docker ps -a and docker images to find the ID of the image named spiritlhl/wds. Then, use the following commands accordingly:

docker rm -f container_ID
+docker rmi image_ID

After deletion, you can create containers of different versions of Windows.

Other similar projects

https://github.com/dockur/windows - Similar project that support more systems, but have more resource requirements

https://github.com/dockur/windows-arm/ - It's great that he has ARM servers for mirror compilation, my project doesn't have

Note that both of the above projects require a host with at least 4 cores of CPU, at least 4G of RAM, and at least 64G of hard disk, which is greater than the mirroring requirements of my project. (The advantage of his project is that you can customize many configuration items, see his corresponding project description for details.)

Manual Provisioning (via the Dockur Project)

This project supports VM creation using QEMU even on host systems that do not support nested virtualization.

Original Project Repositories

⚠️ Notes:

  • The original project provides only the launcher, not a Windows image.

  • The first container startup may take up to 4 hours on domestic (China) networks, due to image download and installation.

  • The host system should meet the following minimum hardware requirements (can be adjusted via script modifications):

    • CPU: At least 4 cores
    • RAM: At least 4 GB
    • Disk: At least 64 GB

For customization such as reducing resource usage or changing launch parameters, refer to:

For x86_64 Architecture Users

A pre-modified single-file launcher is available to simplify building a Windows image. This version writes system files and images directly into Docker’s writable layer—no external image mounting required.

Download link: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

Import Docker image:

bash
docker load -i builder.tar

Launching the Container with a Custom Windows ISO

Download a Windows ISO image from: https://down.idc.wiki/ISOS/Windows/

Sample command to start the container:

bash
docker run -it -d \
+  -e RAM_SIZE="8G" \
+  -e CPU_CORES="4" \
+  --name win2022 \
+  -p 8006:8006 \
+  --device=/dev/kvm \
+  --device=/dev/net/tun \
+  --cap-add NET_ADMIN \
+  -v "$(pwd)/WindowsImage.iso:/boot.iso" \
+  --stop-timeout 120 \
+  windows:builder

We also offer a ready-to-use image with the system and configuration already integrated. Features:

  • Image size: ~26 GB (includes system image and default config)
  • Supports auto disk expansion and startup tasks
  • Just download, import, and run
  • ⚠️ Note: Combined download will require ~60 GB of free space

Download and Merge Split Files

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
+chmod +x mergew.sh
+bash mergew.sh

Start the Container

bash
docker load -i win2022.tar
+docker run -it -d \
+  -e RAM_SIZE="4G" \
+  -e CPU_CORES="2" \
+  --name win2022 \
+  -p 8006:8006 \
+  --device=/dev/kvm \
+  --device=/dev/net/tun \
+  --cap-add NET_ADMIN \
+  --stop-timeout 120 \
+  windows:2022

Important Notes

It is not recommended to use docker commit to save changes to this image, as repeated layer stacking may cause the image size to exceed 40 GB.

For personalized configuration or additional software integration, always start from the builder image to ensure a clean and maintainable result.

+ \ No newline at end of file diff --git a/en/guide/incus/incus_custom.html b/en/guide/incus/incus_custom.html index 9e9651ef91..3036ac0721 100644 --- a/en/guide/incus/incus_custom.html +++ b/en/guide/incus/incus_custom.html @@ -5,101 +5,104 @@ Custom | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of incus is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
+    
Skip to content

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
+systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of incus is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
+EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
+ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
+Client IPv4
+Server IPv6
+Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify here
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
+ip tunnel del server-ipv6

client

ip link set user-ipv6 down
+ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
+apt update -y
+
+# Install WireGuard runtime dependencies
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# Install WireGuard protocol-compatible toolset
+apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
+yum update -y
+
+# Install additional package components
+yum install -y epel-release 
+
+# Install WireGuard runtime dependencies
+yum install -y net-tools
+
+# Install WireGuard protocol-compatible toolset
+yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6 >/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
 
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
 
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

- +[Peer] +PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo= +AllowedIPs = 0.0.0.0/0 +Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
+sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
+wg-quick up warp
+
+# Check IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# Check IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# Disconnect from Warp after successful test.
+wg-quick down warp
+
+# Reconnect and set process daemon to take effect automatically after reboot.
+systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

+ \ No newline at end of file diff --git a/en/guide/incus/incus_extra_config.html b/en/guide/incus/incus_extra_config.html index f6634d86c9..88beeaf73b 100644 --- a/en/guide/incus/incus_extra_config.html +++ b/en/guide/incus/incus_extra_config.html @@ -5,32 +5,35 @@ Custom Configuration | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for incus containers created with incus.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for incus Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

One-Click Installation of the official incus Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

- +
Skip to content

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for incus containers created with incus.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for incus Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

One-Click Installation of the official incus Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
apt-get install -y incus-ui-canonical
+incus config set core.https_address [::]

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

+ \ No newline at end of file diff --git a/en/guide/incus/incus_install.html b/en/guide/incus/incus_install.html index 7f5f80e4fd..33a15025d1 100644 --- a/en/guide/incus/incus_install.html +++ b/en/guide/incus/incus_install.html @@ -5,38 +5,41 @@ incus Installation Guide | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

incus Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both update and curl are working properly before executing this script.

  • Prerequisites: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

OR

shell
bash incus_install.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

TIP

The execution process may require a manual reboot to load the storage type into the kernel, the installation is completed at the end of the execution will automatically reboot the server, the first time after the complete installation of the reboot will take about 400 ~ 500 seconds, please be patient

WARNING

If you need to open more than 200 Incus containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Manual Installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing incus

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

If there are no exceptions, continue execution

incus admin init

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

- +
Skip to content

incus Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both update and curl are working properly before executing this script.

  • Prerequisites: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

OR

shell
bash incus_install.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

TIP

The execution process may require a manual reboot to load the storage type into the kernel, the installation is completed at the end of the execution will automatically reboot the server, the first time after the complete installation of the reboot will take about 400 ~ 500 seconds, please be patient

WARNING

If you need to open more than 200 Incus containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Manual Installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing incus

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

sudo -i
+mkdir -p /etc/apt/keyrings/
+curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
+sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
+Enabled: yes
+Types: deb
+URIs: https://pkgs.zabbly.com/incus/stable
+Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
+Components: main
+Architectures: $(dpkg --print-architecture)
+Signed-By: /etc/apt/keyrings/zabbly.gpg
+EOF'
+apt-get update
+apt-get install incus -y
+incus -h

If there are no exceptions, continue execution

incus admin init

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

+ \ No newline at end of file diff --git a/en/guide/incus/incus_lxc.html b/en/guide/incus/incus_lxc.html index 4acad733a2..758814c3b7 100644 --- a/en/guide/incus/incus_lxc.html +++ b/en/guide/incus/incus_lxc.html @@ -5,46 +5,49 @@ Running LXC Container in Incus | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Running LXC Container in Incus

Images available for creating LXC Containers

A portion of the available system parameters are shown here for your reference:

  • debian10, debian11, debian12
  • ubuntu18, ubuntu20, ubuntu22
  • centos8, centos9 (actually opened out of the Stream version)
  • alpine3.15, alpine3.16, alpine3.17, alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (CGroupV1 needs to be enabled in GRUB or it won't start.)
  • kali,archlinux
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

TIP

The version number has ended the long-term maintenance of the general no longer have an official mirror, temporarily did not find the archive address of the historical mirror, if you find welcome to leave a message I will add support!

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Download script

Downloading the boot script is NOT REQUIRED, if you have used the command to install incus with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian11)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port`` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that ```can't be null, and it needs to be set to 0 if it's not to be mapped.

Support custom server system, do not fill in the leave blank default use debian11, pay attention to the incoming parameters for the system name + version number

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

incus if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put ```screen`` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

incus if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the ```screen`` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, incus virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common incus commands

View all containers:

bash
incus list

View details of a specific container:

bash
incus info container_name

Start a specific container:

bash
incus start container_name

Stop a specific container:

bash
incus stop container_name

Delete a specific container:

bash
incus delete -f container_name

Enter the container's shell:

bash
incus exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type ```exit`` and enter.

Delete all incus containers

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

- +
Skip to content

Running LXC Container in Incus

Images available for creating LXC Containers

A portion of the available system parameters are shown here for your reference:

  • debian10, debian11, debian12
  • ubuntu18, ubuntu20, ubuntu22
  • centos8, centos9 (actually opened out of the Stream version)
  • alpine3.15, alpine3.16, alpine3.17, alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (CGroupV1 needs to be enabled in GRUB or it won't start.)
  • kali,archlinux
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

TIP

The version number has ended the long-term maintenance of the general no longer have an official mirror, temporarily did not find the archive address of the historical mirror, if you find welcome to leave a message I will add support!

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Download script

Downloading the boot script is NOT REQUIRED, if you have used the command to install incus with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian11)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port`` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that ```can't be null, and it needs to be set to 0 if it's not to be mapped.

Support custom server system, do not fill in the leave blank default use debian11, pay attention to the incoming parameters for the system name + version number

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
incus stop test
+incus delete test
+rm -rf test
+rm -rf test_v6
+ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

incus if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put ```screen`` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

incus if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the ```screen`` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
+Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, incus virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common incus commands

View all containers:

bash
incus list

View details of a specific container:

bash
incus info container_name

Start a specific container:

bash
incus start container_name

Stop a specific container:

bash
incus stop container_name

Delete a specific container:

bash
incus delete -f container_name

Enter the container's shell:

bash
incus exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type ```exit`` and enter.

Delete all incus containers

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

+ \ No newline at end of file diff --git a/en/guide/incus/incus_precheck.html b/en/guide/incus/incus_precheck.html index 790782f129..3f6f70e227 100644 --- a/en/guide/incus/incus_precheck.html +++ b/en/guide/incus/incus_precheck.html @@ -5,22 +5,25 @@ Preface | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/incus

Requirements

Hardware requirements.

  • System: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu24 and Debian12, other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open incus containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for incus containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
- +
Skip to content

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the incus module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/incus

Requirements

Hardware requirements.

  • System: Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu24 and Debian12, other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open incus containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for incus containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
+ \ No newline at end of file diff --git a/en/guide/incus/incus_qa.html b/en/guide/incus/incus_qa.html index 5766be82de..1af03a78a9 100644 --- a/en/guide/incus/incus_qa.html +++ b/en/guide/incus/incus_qa.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Solve the puzzle

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

- +
Skip to content

Solve the puzzle

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

+ \ No newline at end of file diff --git a/en/guide/incus/incus_thanks.html b/en/guide/incus/incus_thanks.html index 91f99ad492..5cdb07a4b4 100644 --- a/en/guide/incus/incus_thanks.html +++ b/en/guide/incus/incus_thanks.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/en/guide/incus/incus_windows.html b/en/guide/incus/incus_windows.html index 54e6674e82..01c8dbca59 100644 --- a/en/guide/incus/incus_windows.html +++ b/en/guide/incus/incus_windows.html @@ -5,49 +5,52 @@ Running Windows Virtual Machines in Incus | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Running Windows Virtual Machines in Incus

Verify the Incus Driver

Ensure that incus info output contains qemu, otherwise you cannot create VMs:

shell
incus info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, incus drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

Supported Windows image versions for patching: https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \
-  --windows-arch=amd64 \
-  win.iso \
-  win.incus.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
# Initialize empty VM
-incus init winvm --empty --vm
+    
Skip to content

Running Windows Virtual Machines in Incus

Verify the Incus Driver

Ensure that incus info output contains qemu, otherwise you cannot create VMs:

shell
incus info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, incus drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install distrobuilder --classic
+# reboot to load some config
+reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

Supported Windows image versions for patching: https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+distrobuilder repack-windows \
+  --windows-arch=amd64 \
+  win.iso \
+  win.incus.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
# Initialize empty VM
+incus init winvm --empty --vm
 
-# Adjust root disk size, CPU, and memory
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
+# Adjust root disk size, CPU, and memory
+incus config device override winvm root size=30GiB
+incus config set winvm limits.cpu=3
+incus config set winvm limits.memory=5GiB
 
-# Add TPM device (for Secure Boot/BitLocker support)
-incus config device add winvm vtpm tpm path=/dev/tpm0
+# Add TPM device (for Secure Boot/BitLocker support)
+incus config device add winvm vtpm tpm path=/dev/tpm0
 
-# Mount installation ISO and set as first boot device
-incus config device add winvm install disk \
-  source=/root/win.incus.iso \
-  boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
incus start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the incus list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, incus will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then incus delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
incus config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

- +# Mount installation ISO and set as first boot device +incus config device add winvm install disk \ + source=/root/win.incus.iso \ + boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
+apt install -y spice-html5 websockify lsof

Start the VM:

shell
incus start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the incus list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
incus stop winvm
+incus config device remove winvm install
+incus start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, incus will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then incus delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
incus config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_custom.html b/en/guide/lxd/lxd_custom.html index 52975043aa..99d3f30206 100644 --- a/en/guide/lxd/lxd_custom.html +++ b/en/guide/lxd/lxd_custom.html @@ -5,101 +5,104 @@ Custom | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
-systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of LXD is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
-EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
-ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
-Client IPv4
-Server IPv6
-Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify the
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
-# Modify here
-EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
-systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
-ip tunnel del server-ipv6

client

ip link set user-ipv6 down
-ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
-apt update -y
-
-# Install WireGuard runtime dependencies
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# Install WireGuard protocol-compatible toolset
-apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
-yum update -y
-
-# Install additional package components
-yum install -y epel-release 
-
-# Install WireGuard runtime dependencies
-yum install -y net-tools
-
-# Install WireGuard protocol-compatible toolset
-yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6 >/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
+    
Skip to content

Custom

Attach free IPV6 address segments to host machines

Some machines don't have an IPV6 /64 subnet on the machine itself, here is a method given to attach an IPV6 subnet for free.

Here is a solution using the 6in4 method for a host machine that doesn't have an IPV6 address on its own.

TIP

The operations on this page must be performed on the original system, and ensure that no other scripts from this project are installed(Except for PVE, which needs to be installed first), as this may lead to environment conflicts.

Here are the platforms that are currently running in 2023 that offer IPV6 subnets for free.

Supported PlatformsCorresponding Required Installation PackagesProtocolsNumber of Channels/Subnets
tunnelbroker.netifupdown OR ifupdown2v4tunnel OR sit3✖/64 OR 5✖/64
tunnelbroker.chifupdown OR ifupdown2v4tunnel OR sit3✖/64
ip4market.ruifupdown OR ifupdown2v4tunnel OR sit1✖/64
netassist.uaifupdown OR ifupdown2v4tunnel OR sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipipcustom

The free platform only solves the problem that IPV6 is not available, it does not provide premium IPV6 bandwidth.

If you need high quality bandwidth, please build your own tunnel. When both ifupdown and ifupdown2 are available, try ifupdown first to see if it can be installed successfully, otherwise install ifupdown2.

After the installation is complete, select which package is installed behind to convert the format.

Initial environment modifications

Execute

touch /etc/cloud/cloud-init.disabled

Turn off the automated overwrite of cloud-init first, and then to see what the local machine is using to manage the network, run

systemctl is-active systemd-networkd

and

systemctl is-active networking

See which case this falls into, if it's the former active and the latter inactive, you need to reinstall/DD a system that isn't configured this way, or switch the local machine to use ifupdown/ifupdown2 to manage network execution

# Judge for yourself whether you need to disable the original network management or not
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

If you want to install ifupdown to control the network, this tool is available on all major linux systems.

apt-get install ifupdown -y

If you want to install ifupdown2 for network management, which is generally only available on debian systems, you can install

apt-get install ifupdown2 -y

After the installation is complete, select which package is installed behind to convert the format.

systemctl start networking
+systemctl enable networking

Then restart the server, check whether the machine's network will be rebooted due to the modification of the case of loss of connection, and runuptimeto observe that the startup has been more than 1 minute before proceeding to the next steps

If it is inactive and active, there is no need to switch the network management program and you can proceed directly to the next step.

Since some servers have default intranet IPV6 routes that will conflict with the tunnel, you can use the following command to remove the default IPV6 routes

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

This assumes that your client's server's default NIC is eth0, you can use ip -6 route to see the default route and replace it, the default route starts with default via, and uses dev to specify the default NIC, you just need to find it according to this rule

Currently supported platforms

tunnelbroker_net

Combined with a script that opens containers with IPV6 addresses with a single click, you can attach an IPV6 address from he to each container

The downside is that the addresses are dark/dirty, and cloudflare's cdn will most likely not be able to latch on, test it yourself

  1. Register an account at https://tunnelbroker.net/ and clickCreate Regular Tunnelon the left.

1

  1. Fill in your server's IPV4 address in the red box, choose a connection point that is physically close to your server, for example, if your machine is in Los Angeles, choose a connection point on the west coast of the United States, and then clickCreate Tunnelto create the tunnel when you are prompted by the green box!

2

3

4

  1. Wait for the following screen, clickExample Configurationsand select the corresponding system, for example, the host of LXD is definitely Debian/Ubuntu.

5

6

  1. The boxed part is the file to be modified and the content to be filled in.

7

  1. Exchange the format of the command then add IPV6 settings to your network configuration file.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerNet, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Here, copy and paste the contents of the configuration file in the red box, and then run this command.
+EOF

Then you can usecat /etc/network/interfacesto see if the configuration file is written correctly.

  1. If all of the above is OK, then you need to enable the network interfaces
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. Then you can test the IP address of the network interface.

Execute theifconfigcommand, and there should be a he-ipv6 interface, similar to the following:

8

Or execute:

curl ipv6.ip.sb

Returns the IPV6 address you bound to

  1. Additional settings for NAT VPS

IPv4 NAT VPS may require some additional settings beyond the IP replacement operation mentioned earlier, otherwise it may still not be able to access the IPv6 network.

apt-get install ufw -y
+ufw allow 41

Add the relevant routing rules

route -A inet6 add ::/0 dev he-ipv6
  1. If the IPV6 network is no longer needed and you want to delete it, delete the he-ipv6 network interface configuration.

If you want to delete the he-ipv6 network interface configuration (if not, it will be enabled automatically after reboot), remember to modify the/etc/network/interfacesfile to remove the content added in the red box before.

Then reboot the server to remove the

tunnelbroker_ch

Similar to the above, first register an account at https://www.tunnelbroker.ch/ and click on the activation email after registering.

Then you have to fill in the IPV4 address of your server.

After creating an account, you need to go to the Config page instead of the details page.

Don't use the following page, first refresh the page without the light blue box and then stop refreshing it

Don't stop refreshing after the light blue box pops up

Record the content of the last red box on the following page, and prepare to modify the host configuration file.

Copy the last red box of the page without the blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforTunnelBrokerCh, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the format, and wait for the page to refresh to show the converted configuration file.

Then use vim or vi to modify the/etc/network/interfacesfile to add content, or modify the following command to add new content

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

ip4market_ru

Similar to the above, first register an account at https://tb.ip4market.ru, the registered email address must be an unseen email address, the phone number can be written randomly without verification, and the IP address should be the IPV4 address of the host you want to attach.

The IP address is the IPV4 address of the host computer you are attaching to

Then you have to go through Recaptcha's human-machine verification, and click register.

You will receive an activation email with your password, memorize it.

Then login on the homepage

Then you will be taken to this page

Hold down the right button and copy the four lines framed in red, which are

Server IPv4.
+Client IPv4
+Server IPv6
+Client IPv6

For these four lines, press ctrl+c to copy or right-click to copy

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforip4market, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then clickCovertto convert the formatting

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

netassist_ua

Similar to the above operation, first in https://tb.netassist.ua/ register an account first, after registration, click on the activation of the mail, the activation page will have a password display, remember to record!

Then fill in the IPV4 address of your server, you can change it later, just fill in a random one first.

Then you will get to this page

a

The first red box is the location of your host's IPV4 address, if you want to modify it, modify it there, and then click change to save.

The second red box is for```Linux``, and then click on show

b

The above content will appear, copy all the boxed parts without blank lines.

Then open https://ipv6tunnel.spiritlhl.top/ and selectOptionforNetAssist, another drop-down selection box to choose the name of the package you successfully installed previously, then paste what you copied in the input box.

Then click onCovertto convert the formatting

c

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify the
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Transfer IPV6 subnets between different servers

Related repository: https://github.com/oneclickvirt/6in4

This method will provide a way to split a /80 out of the IPV6 segment on A and attach it to B to use.

Features

  • Self-built IPv6 tunnel for sit/gre/ipip protocols
  • Support to customize the IPV6 subnet size to be cut out, and the appropriate IPV6 subnet information in CIDR format will be calculated automatically.
  • Automatically recognizes the IPV6 subnet size of the server side
  • will automatically set up the tunnel server and print the commands that the client needs to execute
  • Setting up the IPV6 tunnel is easy to understand and easy to remove

Environmental Preparation

VPS(A)VPS(B)
one IPV4 address (server_ipv4)one IPV4 address (clinet_ipv4)
one IPV6 subnetno IPV6 address
Hereafter referred to as serverHereafter referred to as client

Usage

Download Script

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

Execute it

./6in4.sh client_ipv4 <mode_type> <subnet_size>
OptionsOptional Option 1Optional Option 2Optional Option 3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type> only support those three protocols for now, the more advanced the more recommended, no fill in the default is sit protocol

<subnet_size> as long as it is larger than the original system subnet mask, and is a multiple of 8, if you don't fill it in, it defaults to 80.

Remember to replace client_ipv4 with the IPV4 address of the machine you want to attach IPV6 to, and the command you need to execute on the client side will be sent back to you after execution, see the instructions after execution for details.

To prevent you from forgetting to copy the commands, the commands themselves will be written to the 6in4.log file under the current path, you can use cat 6in4.log to query the commands that need to be executed on the client side

For copied commands, be sure to select option 6in4 in https://ipv6tunnel.spiritlhl.top/ before converting!

Then the page will be refreshed automatically and you need to modify the contents of the/etc/network/interfacesfile with vim or vi commands, or modify the following commands to add new contents.

tee -a /etc/network/interfaces <<EOF
+# Modify here
+EOF

Then you'll need to reboot the system a bit, or run

apt-get install net-tools iproute2 -y
+systemctl restart networking

Make sure the environment is OK before you do anything else

Check server status

systemctl status ndpresponder
ip addr show

Check client status

ip addr show
curl ipv6.ip.sb

Delete tunnel

server

ip link set server-ipv6 down
+ip tunnel del server-ipv6

client

ip link set user-ipv6 down
+ip tunnel del user-ipv6

The above deletion is only temporary, for permanent deletion you must modify and delete the contents of the /etc/network/interfaces file that you have previously added.

one more thing

In fact https://tunnelbroker.net/ supports the application of IPV6 subnets of size /48

Make the request here, then when converting the format change the original /64 IPV6 address to a /48 IPV6 address and you'll get a larger IPV6 subnet!

Supplemental CloudFlare WARP IPv4 / IPv6 outbound

1: Benefits

  • By installing it on the host machine, all enabled machines can benefit from the advantages of Warp without the need for individual configurations, thus saving resources and simplifying management.
  • The use of kernel WireGuard on the host machine enables more efficient operation of WireGuard compared to user-space WireGuard-Go.

2: Manual Installation

2-1 Installing WireGuard Dependencies

  • Debian and Ubuntu systems
# Update dependent libraries
+apt update -y
+
+# Install WireGuard runtime dependencies
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# Install WireGuard protocol-compatible toolset
+apt install -y --no-install-recommends wireguard-tools
  • CentOS systems
# Update dependent libraries
+yum update -y
+
+# Install additional package components
+yum install -y epel-release 
+
+# Install WireGuard runtime dependencies
+yum install -y net-tools
+
+# Install WireGuard protocol-compatible toolset
+yum install -y wireguard-tools

2-2 Getting warp account information

Visit https://warp.cloudflare.now.cc/?run=register&format=yaml and record private_key, v6 2 values

image.png

2-3: Modifying Configuration Files

  • Create and edit the /etc/wireguard/warp.conf file, replacing any parts that contain <> (pointy brackets) together, just to make it look obvious.

  • For IPv4-only hosts, Warp takes over IPv6 egress only

shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6 >/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
 
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
-PrivateKey = <Your PrivateKey>
-Address = 172.16.0.2/32
-Address = <Your Address-v6>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • For IPv6 only hosts, Warp takes over IPv4 egress only.
shell
[Interface]
+PrivateKey = <Your PrivateKey>
+Address = 172.16.0.2/32
+Address = <Your Address-v6>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
 
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
-sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
-wg-quick up warp
-
-# Check IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# Check IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# Disconnect from Warp after successful test.
-wg-quick down warp
-
-# Reconnect and set process daemon to take effect automatically after reboot.
-systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

- +[Peer] +PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo= +AllowedIPs = 0.0.0.0/0 +Endpoint = [2606:4700:d0::a29f:c101]:2408
  • There's no need to target dual-stack, after all, native network outlets are better than relaying through Warp

2-4: Setting the Address Resolution Priority

For IPv4-only host machines, Warp only takes control of the IPv6 outbound, prioritizing the use of the native network's IPv4 outbound.

shell
# IPv4 priority
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf

For IPv6-only host machines, Warp only takes control of the IPv4 outbound, prioritizing the use of the native network's IPv6 outbound.

shell
# IPv6 priority
+sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

2-5: Connecting to Warp and setting up the systemd process daemon

# Run wireguard to connect to Warp. If this step gets stuck and causes the connection to be lost, reboot the host in the background to resolve it.
+wg-quick up warp
+
+# Check IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# Check IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# Disconnect from Warp after successful test.
+wg-quick down warp
+
+# Reconnect and set process daemon to take effect automatically after reboot.
+systemctl enable --now wg-quick@warp

3: Autorun: fscarmen's one-click scripts

Finally, the one-click script for fscarmen is introduced. The script is mentioned as a handy tool to simplify the configuration process. It also automatically handles advanced parameters such as Optimal MTU, Optimal Endpoint, etc.

Project: https://github.com/fscarmen/warp-sh

# Run one-key script
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_extra_config.html b/en/guide/lxd/lxd_extra_config.html index 33f3dd6a46..b083666b39 100644 --- a/en/guide/lxd/lxd_extra_config.html +++ b/en/guide/lxd/lxd_extra_config.html @@ -5,37 +5,40 @@ Custom Configuration | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for LXC containers created with LXD.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for LXD Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

Enable the official lxd control panel with a single click

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

One-Click Installation of Hosted Third-Party Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
  • Original author's repository: Link
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

After the installation is complete, open the hen IP address, follow the prompts to set the password for admin, other all the way to the default will be able to use the panel!

- +
Skip to content

Custom Configuration

TIP

The following configurations may increase the load on the server. Only install them if necessary.

Automatic IPV6 Address Configuration

  • (Optional, not required if not using)
  • This script is only suitable for servers that have an IPV6 subnet with a prefix, and the server has bound the first IP of the subnet as its IPV6 address or IPV6 gateway.
  • Automatically configures IPV6 addresses for LXC containers created with LXD.
  • Integrated into buildone.sh and can be controlled by variables without needing to be downloaded beforehand. You don't need to manually use this script; when using buildone.sh, configure with variable Y to enable it.

Download Script

Command:

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

Automatically configure IPV6 mapped addresses for containers

bash
bash build_ipv6_network.sh Container_Name(change_me)

A message is printed when the mapping is complete (Default mapping without iptables)

Example (automatically configure the test container with an IPV6 address, a test_v6 file is written when the configuration is complete)

bash
bash build_ipv6_network.sh test

PS: Add ipv6 processing can choose whether to use ip6tables for mapping, the default is not to use ip6tables for mapping but to add new network devices for mapping.

Use ip6tables for mapping

bash
bash build_ipv6_network.sh Container_name Y

If ip6tables is used for mapping, remove all IPV6 mapped rules available:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

Uninstall the IPV6 address binding daemon and corresponding files

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

One-click Installation of Common Pre-configured Environment for LXD Hosts with vnstat Integration

  • (Optional, this script is only for easy monitoring integration with the site, it's fine if you choose not to install)

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

Enable the official lxd control panel with a single click

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
shell
sudo snap refresh lxd --channel=latest/stable
+snap set lxd ui.enable=true
+lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
+systemctl reload snap.lxd.daemon
+snap restart --reload lxd

Then you can type in your browser

https://your_public_ipv4_address:8443

You can enter the official visualization panel, subsequent operation configuration in accordance with the UI prompts can be operated.

One-Click Installation of Hosted Third-Party Visualization Dashboard

  • (Optional, this panel is just for convenient visualization operations, it's okay if not present)
  • Original author's repository: Link
shell
lxc config set core.https_address [::]
+lxc config set core.trust_password your_password
+snap install lxdmosaic

After the installation is complete, open the hen IP address, follow the prompts to set the password for admin, other all the way to the default will be able to use the panel!

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_install.html b/en/guide/lxd/lxd_install.html index 0371f4abc1..20b0f14bb8 100644 --- a/en/guide/lxd/lxd_install.html +++ b/en/guide/lxd/lxd_install.html @@ -3,29 +3,32 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXD Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both apt update and apt install curl are working properly before executing this script.

TIP

It's recommended to wait for at least 5 minutes after the system boots up before executing the following commands. This is to avoid the script being executed by the default system settings, which could cause issues with apt sources.

  • Prerequisites: Ubuntu 18+ (recommended above 20.04), Debian 8+ (recommended above 11)
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

OR

shell
bash lxdinstall.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

WARNING

If you need to open more than 200 LXD containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Installation of WEB Control Panel

Customization There are tutorials on how to enable the official panel, but here do not choose to use the official panel, because the official panel in order to security, at the expense of a lot of user experience, this piece of using the

https://github.com/turtle0x1/LxdMosaic

third-party panels

shell
sudo snap install lxdmosaic

Do a straightforward one-click install, then open the current host's https://<public IP address>/ and force access to it to get to the setup page

lxd

lxd

lxd

This piece can be changed if you need to set up the site name

lxd

Better than nothing can only mean that there is no RBAC access control for sub-user segregation

Manual installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing LXD

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

If the following error occurs in the above command

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

Use the command patch before installing lxd

snap install core

If there are no exceptions, the results of the above three lines of commands are as follows

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

Test whether symbolic links are functioning in LXC.

lxc -h

If an error is reported then execute the following command to soft connect the lxc command

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

After connecting, test the lxc command again to see if there is an error about not being able to find it

- +
Skip to content

LXD Installation Guide

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

One-Click Installation

WARNING

If this is a new server, make sure that both apt update and apt install curl are working properly before executing this script.

TIP

It's recommended to wait for at least 5 minutes after the system boots up before executing the following commands. This is to avoid the script being executed by the default system settings, which could cause issues with apt sources.

  • Prerequisites: Ubuntu 18+ (recommended above 20.04), Debian 8+ (recommended above 11)
  • The virtual memory here is talking about the size of the SWAP to be opened, and the storage pool is the sum of the sizes of the disks occupied by all your servers to be opened
  • The server needs to be restarted after the environment installation process to load some default configurations
  • By default, lxd's lxcfs-related configuration is enabled, so that in-container querying of container information changes to information about the container itself rather than the host

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

OR

shell
bash lxdinstall.sh

Example of initialization configuration:

If there is 18GB of unused disk space on the system disk, after deducting the space already occupied, and you want to allocate 2GB of virtual memory (2048MB of SWAP) and a 15GB storage pool, then following the prompts in the command line, enter 2048 and 15.

WARNING

If you need to open more than 200 LXD containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Installation of WEB Control Panel

Customization There are tutorials on how to enable the official panel, but here do not choose to use the official panel, because the official panel in order to security, at the expense of a lot of user experience, this piece of using the

https://github.com/turtle0x1/LxdMosaic

third-party panels

shell
sudo snap install lxdmosaic

Do a straightforward one-click install, then open the current host's https://<public IP address>/ and force access to it to get to the setup page

lxd

lxd

lxd

This piece can be changed if you need to set up the site name

lxd

Better than nothing can only mean that there is no RBAC access control for sub-user segregation

Manual installation (optional)

Not recommended, just for some odd environments where one-click scripts won't run.

Disable Firewall

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

Enabling Virtual Memory SWAP

The amount of memory depends on how many instances you want to run. If you want to run 8 instances and calculate, you'll need 2GB of memory. If your actual physical memory is 512MB, you'll need an additional 1.5GB. To be cautious, allocate 2GB of virtual memory.

Execute the following commands: Enter '1', then enter '2048'. This signifies allocating 2GB of virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

Installing LXD

Actually, the virtual memory allocated for swap should be twice the size of the actual memory. So, it's reasonable to allocate 1GB if the actual memory is 500MB. The scenario I described above is an excessive allocation.

apt install snapd -y
+snap install lxd
+/snap/bin/lxd init

If the following error occurs in the above command

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

Use the command patch before installing lxd

snap install core

If there are no exceptions, the results of the above three lines of commands are as follows

Just enter the default for the normal options

Choose the size of the physical disk (hint: select the default option with a minimum of 1GB). Generally, I fill in the available disk space minus the memory size, then multiply by 0.95 and round down. Here, I entered 10GB.

Remember to select 'no' for options containing 'auto' when prompted to update the image, in order to avoid occupying the system.

Test whether symbolic links are functioning in LXC.

lxc -h

If an error is reported then execute the following command to soft connect the lxc command

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

After connecting, test the lxc command again to see if there is an error about not being able to find it

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_lxc.html b/en/guide/lxd/lxd_lxc.html index f2c55da1cb..5c260f07ca 100644 --- a/en/guide/lxd/lxd_lxc.html +++ b/en/guide/lxd/lxd_lxc.html @@ -5,46 +5,49 @@ LXC virtualization | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXC virtualization

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Downloading the boot script is NOT REQUIRED, if you have used the command to install LXD with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian12)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port`` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that ```can't be null, and it needs to be set to 0 if it's not to be mapped.

Support for customizing the system of the server, do not fill out the default use of debian12 when left blank, note that the incoming parameters for the system name + version number, such as:

  • debian12, debian13
  • ubuntu22, ubuntu24
  • centos8,centos9
  • alpine3.16, alpine3.17, alpine3.18,alpine3.19
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put ```screen`` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the ```screen`` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
-Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, LXC virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common LXD commands

View all containers:

bash
lxc list

View details of a specific container:

bash
lxc info container_name

Start a specific container:

bash
lxc start container_name

Stop a specific container:

bash
lxc stop container_name

Delete a specific container:

bash
lxc delete -f container_name

Enter the container's shell:

bash
lxc exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type ```exit`` and enter.

Delete all LXC containers

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

- +
Skip to content

LXC virtualization

Generate only one NAT server

  • Generate only one NAT server, with customizable restrictions on all content.

Downloading the boot script is NOT REQUIRED, if you have used the command to install LXD with one click, the corresponding boot script will be downloaded automatically, so you don't need to download the script again.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

Usage

. /buildone.sh name Cpu_num Memory_size Hard_disk_size SSH_port Extranet_start_port Extranet_stop_port Download_speed Upload_speed Whether_IPV6_is_enabled(Y or N) System(leave blank for debian12)

Memory size is calculated in MB, hard disk size is calculated in GB, download speed upload speed is calculated in Mbit, whether to enable IPV6 does not have to fill in Y or N, no this parameter can also be left blank default does not enable IPV6

If external start port`` and external stop port are both set to 0, then we don't do interval port mapping, only the basic SSH port is mapped, note that ```can't be null, and it needs to be set to 0 if it's not to be mapped.

Support for customizing the system of the server, do not fill out the default use of debian12 when left blank, note that the incoming parameters for the system name + version number, such as:

  • debian12, debian13
  • ubuntu22, ubuntu24
  • centos8,centos9
  • alpine3.16, alpine3.17, alpine3.18,alpine3.19
  • Note that the combination of lowercase letters + numbers or only lowercase letters, try it yourself, if the search is not the system will automatically exit the script
  • The version number can be with English decimal point, in order to adapt to the alpine version number has been supported.
  • If you can't open it, it may be that the hard disk is not big enough or it doesn't fit the host, try it by yourself.
  • The images currently in use are triple filtered and prioritized: self-hostedofficial-hostedopsmaru
  • A complete list of supported systems for self-compiling images: x86_64_fixed_images.txt and arm64_fixed_images.txt

Example

Here is the information about the example chick that is being raised:

AttributeValue
server's Nametest
Username for SSH Loginroot
Password for SSH LoginRandomly generated
Number of CPU Cores1
Memory Size256MB
Disk Size2G
Range of Internal and External Port Mapping20002 to 20025
Upload Bandwidth500Mbit
Download Bandwidth500Mbit
Automatically Set External IPv6 AddressNo
Operating SystemDebian 12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

If you need to see the information, run

shell
cat ct_name_change_me

For example, the information for the query example is

shell
cat test

If you have already generated chicks through the above methods and still need to batch generate chicks, you can use a customized batch generation version of the script, but note that you should first delete the test chicks before batch generating chicks

Delete Test Chick

shell
lxc stop test
+lxc delete test
+rm -rf test
+rm -rf test_v6
+ls

Normal version batch generation

Opened Chick Configuration:

  • 1 core 256MB RAM 1GB hard disk limited to 300Mbit bandwidth
  • With 1 SSH port, 24 extranet ports
  • Default memory and hard disk size

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the servers, this step is best to put ```screen`` in the background to suspend the execution of the opening of the servers, the length of time with you to open a few and the mother hen configuration-related

Execute the following command to load the boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

The following command opens 10 chicks with the name prefix tj.

shell
./init.sh tj 10

Sometimes there is a problem with the path where init.sh is run, in this case it is recommended to add sudo in front of it to force it to run in the root directory

Bulk generation of pure SSH port versions

Opened Chick Configuration:

  • 1 core 128MB RAM 300MB hard disk limited to 300Mbit bandwidth
  • Only one SSH port
  • Unable to mount warp

TIP

lxc if the command is no problem, the execution of the initialization of the opening of the chick, this step is best to put the ```screen`` in the background to hang the execution of the opening of the chick, the length of time you open the chick with the opening of a few and the mother hen configuration-related

Load boot script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

The last line of the following command opens 10 chicks with the chick name prefix tj

shell
./least.sh tj 10

Sometimes there is a problem with the path where last.sh is run, in this case it is recommended to force the root directory to run by adding sudo in front of it.

Custom Batch Generation of Versions

  • Customizable memory and hard disk sizes
  • It's also fine if you have manually executed the above batch generation before; the configuration inherits without overwriting

If you need to batch-generate servers multiple times, you can use the following:

Command:

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

Can be run multiple times to batch generate chicks, and inherit the previous part has been generated in the back to add, customizable memory and hard disk size

View the information of the batch opened chicks

After opening the chicks, the specific information will be generated in the log file in the current directory, with the following format

shell
Server_1_Name Password SSH_Port Public_Port_Start Public_Port_End
+Server_2_Name Password SSH_Port Public_Port_Start Public_Port_End

To view it, simply print the log file by executing the following command in the current directory

shell
cat log

WARNING

Don't use the chicks opened by this script as a production environment, LXC virtualization doesn't support changing kernel, dd, turning on bbr, etc.

Some common LXD commands

View all containers:

bash
lxc list

View details of a specific container:

bash
lxc info container_name

Start a specific container:

bash
lxc start container_name

Stop a specific container:

bash
lxc stop container_name

Delete a specific container:

bash
lxc delete -f container_name

Enter the container's shell:

bash
lxc exec container_name /bin/bash

TIP

Instead of /bin/bash, you can use /bin/sh in alpine, which is /bin/bash on regular systems.

To exit, type ```exit`` and enter.

Delete all LXC containers

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

Perform deletion of useless logs within a container

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

Delete the original configuration script

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

Download back the relevant configuration scripts for the new version

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

Just download the other one-click scripts yourself.

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_precheck.html b/en/guide/lxd/lxd_precheck.html index edaf6063de..8d173349e6 100644 --- a/en/guide/lxd/lxd_precheck.html +++ b/en/guide/lxd/lxd_precheck.html @@ -5,22 +5,25 @@ Preface | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/lxd

Requirements

Hardware requirements.

  • System: Debian 8+, Ubuntu 18+ (20.04 recommended).
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu20, Ubuntu other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open LXC containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for LXC containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
- +
Skip to content

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If your host does not have an IPV6 subnet and you want to assign IPV6 addresses to containers, then please check the Customize partition in the LXD module for the Attach a free IPV6 address segment to the host, and attach an IPV6 subnet to the host before installing the environment.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/lxd

Requirements

Hardware requirements.

  • System: Debian 8+, Ubuntu 18+ (20.04 recommended).
  • Virtualization: KVM, VMWARE recommended.
  • Memory: At least 512MB of RAM
  • Hard disk: hard disk (system disk) at least 10G
  • Network: Independent IPV4 address, IPV6 is optional, bandwidth can download scripts on the line, the network can connect to the Github raw page on the line

PS: If the hardware is very good and has a lot of resources, you can use PVE to batch open KVM virtualized VMs Jump

PS: If the hardware resources are even worse, virtualization is not supported, you can use the docker version, the adaption surface is wider Jump

Project Features

  • This set of script development using Ubuntu20, Ubuntu other long-term maintenance version should also be no problem, automatically switch to another storage type if btrfs not supported

  • Set up both TCP and UDP forwarding, in addition to SSH ports, other mapping intranet and extranet ports are the same.

  • Support for docker nested virtualization of open LXC containers has been set up, and the default normal version and pure probe version use the debian11 system.

  • lxcfs has been set to be enabled by default, so that querying resources within a container uses the configured view rather than the host's view

  • Have blocked the container may be used to abuse the toolkit and IPV4 network TCP/UDP protocol ports ( 3389 8888 54321 65432 ), to prevent the container is used for scanning and blasting, and can be external process checking for problems automatically shut down

  • Has supported one-click configuration of IPV6 addresses for LXC containers (provided that the mother hen has an IPV6 subnet, no IPV6 address is not configured), automatically adapted to the size of the subnet

  • Ensure that the disk you want to open is the default system disk (sda or sda1) and not the mounted disk (sdb and so on), if you are not sure, use fdisk -l and df to check.

  • See Other notes for details on mounting other disks.

  • One-click scripts support custom restrictions on all content, the normal version supports multiple runs of the batch generation does not overwrite the previously generated configuration

Detecting the environment

Use the subsequent script must execute this command to detect the hen whether it meets the requirements

Command:

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_qa.html b/en/guide/lxd/lxd_qa.html index 3933728ace..502d6790f2 100644 --- a/en/guide/lxd/lxd_qa.html +++ b/en/guide/lxd/lxd_qa.html @@ -3,25 +3,28 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Solve the puzzle

What if the lxc command says it can't be found after LXD is installed?

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

After executing this command try

lxc -h

to see if the lxc command is fixed.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

- +
Skip to content

Solve the puzzle

What if the lxc command says it can't be found after LXD is installed?

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

After executing this command try

lxc -h

to see if the lxc command is fixed.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

Currently verified VPS vendors that can open containers with separate IPV6 addresses.

kuroit Phoenix, USA regular

datalix German AMD Promotions

+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_thanks.html b/en/guide/lxd/lxd_thanks.html index 9ebd78cc57..e40c5d536c 100644 --- a/en/guide/lxd/lxd_thanks.html +++ b/en/guide/lxd/lxd_thanks.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/en/guide/lxd/lxd_windows.html b/en/guide/lxd/lxd_windows.html index 75a16127b2..c2ab01c3cb 100644 --- a/en/guide/lxd/lxd_windows.html +++ b/en/guide/lxd/lxd_windows.html @@ -5,39 +5,42 @@ Running Windows Virtual Machines in LXD | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Running Windows Virtual Machines in LXD

Verify the LXD Driver

Ensure that lxc info output contains qemu, otherwise you cannot create VMs:

shell
lxc info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, lxd drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# reboot to load some config
-reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \
-  --windows-arch=amd64 \
-  win.iso \
-  win.lxc.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
-apt install -y spice-html5 websockify lsof

Start the VM:

shell
lxc start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the lxc list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, lxd will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then lxc delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
lxc config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

- +
Skip to content

Running Windows Virtual Machines in LXD

Verify the LXD Driver

Ensure that lxc info output contains qemu, otherwise you cannot create VMs:

shell
lxc info | grep -i driver:

If it only shows lxc, no need to read the subsequent tutorials, lxd drivers don't support opening a VM.

Prepare the Environment and Patch the Image

Execute the following commands in sequence in the /root directory:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install lxd-imagebuilder --classic --edge
+# reboot to load some config
+reboot

Download the image and apply the patch. If you're using a different image, replace the download link accordingly.

(You don't need to download the image that comes with virtio, the original image will suffice)

Windows image download link: https://down.idc.wiki/ISOS/Windows/

The following guide will use Windows 2019 as an example:

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+lxd-imagebuilder repack-windows \
+  --windows-arch=amd64 \
+  win.iso \
+  win.lxc.iso

The patching time depends on when the program adds the drivers needed for booting (it will add one by one until successful).

Some may take a short time, others may take longer, potentially exceeding 10~30 minutes. It's recommended to run this in screen or tmux.

After patching is complete, you can delete the original image:

shell
rm -f win.iso

Create the VM and Mount the Installation ISO

Here I'm using a configuration of 3 CPUs, 5GB RAM, and 30GB storage. If you're using Windows 10 or newer versions, you'll need at least 4 CPUs, 6GB RAM, and 40GB storage.

It's recommended to use more CPU and RAM than the resources I have set up now to avoid the system getting stuck to the point of crashing.

If you don't have enough memory, we recommend checking the Add SWAP item in the Other Useful Items section of this guide to add more virtual memory on your own.

shell
lxc init winvm --vm --empty
+lxc config device override winvm root size=30GiB
+lxc config set winvm limits.cpu=3 limits.memory=5GiB
+lxc config device add winvm vtpm tpm path=/dev/tpm0
+lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

Start the VM and Access the Desktop Remotely via Browser

Install the components needed for browser access:

shell
apt update
+apt install -y spice-html5 websockify lsof

Start the VM:

shell
lxc start winvm

Start remote access components:

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

At the first boot, you'll need to press the Ctrl+Alt+Delete button in the upper left corner of the browser page. After restarting, follow the prompts on the default interface. You'll need to wait 5-10 minutes for the ISO to be loaded for the actual installation.

Eventually, the Zabbly icon will appear and spin for at least 2 minutes. Please be patient.

Once the spinning stops, you'll enter the normal Windows VM installation process, similar to PVE operations.

Here the hard disk can not be selected, choose to view the yellow tips in the lower left corner, and then follow the prompts will be offline hard disk online point to confirm the button, you can select the hard disk.

Once the installation is complete, the virtual machine will automatically reboot a few times to update the network, and the web side of spice will show up in the user setup interface, while in the background you can use the lxc list to see that the network is automatically attached.

After setting up the user to enter the system login page, execute the following command to shut down/exit Windows, then remove the ISO device to ensure that the next boot is from the hard disk, and then start the virtual machine again.

shell
lxc stop winvm
+lxc config device remove winvm install
+lxc start winvm

The following image can be seen after startup (test visit a website)

No need to configure your own network, lxd will automatically assign IPV4 addresses and connect to the network.

Remove the remote component to restart the browser mapping

If you need to delete the VM and recreate it due to resource limitations or other reasons, use pkill -f websockify to terminate all SPICE signal forwarding, then lxc delete -f winvm to forcibly delete the VM.

shell
lsof -i :6080

Check if the PID for the corresponding port still exists to ensure it has completely stopped (if you have signal forwarding for multiple VMs, it's better not to use pkill to delete all of them; use kill -9 to delete the PID for the specific port).

If it crashes and stops within a few minutes of first startup

Need to add CPU passthrough

shell
lxc config set winvm raw.qemu -- "-cpu host"

Just start the virtual machine again

Disadvantages

The frontend lacks authentication, so you can't set user passwords.

If you need frontend authentication, you'll need to use Guacamole with additional settings to implement it, which won't be covered in detail here.

The VM piece doesn't have some well established interactive panels and adaptations, spice is too old (although there is a web-based spice client), and the official panels don't support rbac with a username and password and can only be used with certificates.

+ \ No newline at end of file diff --git a/en/guide/pve/images/readme.html b/en/guide/pve/images/readme.html index 7f70936f13..52028b187e 100644 --- a/en/guide/pve/images/readme.html +++ b/en/guide/pve/images/readme.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/en/guide/pve/pve_android.html b/en/guide/pve/pve_android.html index b371fdec1c..ee9d8a527d 100644 --- a/en/guide/pve/pve_android.html +++ b/en/guide/pve/pve_android.html @@ -5,22 +5,25 @@ Android Virtual Machine | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Android Virtual Machine

Android System Image Download

Download links for Android system version 9 and earlier:

International

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

Domestic (China)

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Download links for Android system version 10 and later:

https://blissos.org/index.html#download

Virtual Machine Setup

Setting up an Android Virtual Machine with version 9 and earlier images

This guide demonstrates using:

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

as an example

1

Template Configuration

Create a virtual machine with VMID 100 and select the corresponding storage disk

2

Select the Android image, then choose Linux for Type and choose an option with version 2.6 for Version

3

Select Vmware compatible for Graphic card, other options are default as shown

4

Choose SATA for disk format, allocate at least 30GB of disk space (size can be chosen based on your needs)

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface

9

System Installation

After entering the boot menu, select the option starting with Installation

10

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it

11

Choose not to use GPT format

12

When the empty disk is displayed, select New

13

Select partition type Primary

14

Then you'll be prompted to specify the size of the space. Just press Enter to use all available space

15

Then select Flags, move to Bootable, press Enter until Boot appears under Flags

16

Then move to Write and press Enter to write changes

17

You'll be asked to confirm whether to continue. Type yes and press Enter to continue

18

After a progress bar completes, you'll return to the initial menu. Select Quit to exit the menu, everything is now ready

19

Then you'll return to the UI interface. Use the previously initialized disk and select the OK button

20

Use the arrow keys to select ext4 file system type, then select the OK button

21

Confirm formatting by selecting the Yes button

22

Confirm GRUB boot installation by selecting the OK button

23

Confirm the file system is readable and writable by selecting the OK button

24

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button

25

After a while, you'll enter the Android logo screen

26

Removing the Image

Then there will be a black screen. If it's still black after 3-5 minutes, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

ar

Then execute qm start 100 on the host machine again, and you should enter the Android system initialization interface

System Initialization

In the initialization interface, select the language and click the confirm button

27

It will try to connect to WiFi. Since our PVE installation uses a completely static network configuration, just skip this and set it up later

31

Click the next button to confirm the time settings

32

Click to cancel screen protection, confirm to skip again

33

After a period of black screen, the main screen application selection will appear. If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine as before, and it should display after entering VNC

Select Quickstep

34

Network Settings

After entering the desktop, you need to set up the network. Click the settings icon in the upper left corner

35

A dropdown appears, click and hold to pull down

36

Click the gear button

37

Enter Network & Internet settings

38

Double-click WIFI with the left mouse button

39

Modify the detected VirtWIFI. Right-click to bring up the selection box, then click Modify network

40

Advanced options appear, click to open hidden options

41

Configure the network settings as shown

IP address 172.16.1.xxx (replace xxx with your desired IP, I used 100 because my vmid is 100 for convenience)

Subnet mask 24

Default gateway 172.16.1.1

DNS 8.8.8.8 or 144.144.144.144

Then click the save button

42

At this point, the settings may still not be applied. Turn off WiFi and then turn it back on, it should then show as connected

43

Then exit to the main interface, click on Google Chrome, and try to open a webpage

44

You can see that opening this guide's URL works without problems, proving that the network is connected

45

Setting up an Android Virtual Machine with version 10 and later images

This guide demonstrates using:

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

as an example

1

Template Configuration

The host machine needs to execute the following command to install graphics environment dependencies

shell
apt install libgl1 libegl1 -y

Then start creating the virtual machine by clicking the Create VM button in the upper right corner. Fill in VMID, Name, Resource Pool

2

Select the Android image, then choose Linux for Type and an option with version 2.6 for Version

3

If the host machine has a GPU, select VirGL GPU for Graphic card.

If the host machine doesn't have a GPU, select VirtIO or Vmware compatible for Graphic card.

Select q35 for Machine, select OVMF (UEFI) for BIOS, and select local for EFI Storage.

4

Choose SATA for disk format. How much disk space to allocate is up to you, but at least 30GB is recommended

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface.

System Installation

After entering the boot menu, select the option ending with Installation

9

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it.

10

Choose not to use GPT format, continue using cfdisk format.

11

When the format selection box appears, select gpt.

12

When the empty disk is displayed, select New.

13

Because you need to create an EFI partition, you need to change the size rather than using the default. Change the number to 1 to allocate 1GB of disk space, then press Enter.

14

Then you'll return to the menu bar. Use the arrow keys to select Type, then press Enter to choose the format type for the partition

15

Use the arrow keys to select the first option EFI System, then press Enter

16

Now you're back at the menu bar. In the upper half of the page, you can see the specific partition size and format

17

Then press the down arrow key to select the next empty partition line

18

Select New from the menu bar, then press Enter

19

Here you need to fill in the partition size. Match it with the empty partition size shown in the upper right corner, then press Enter.

20

Return to the menu bar, select Write, press Enter to write the partition.

21

You'll be prompted to enter yes to confirm. Enter it and press Enter.

22

After a progress bar runs, you should return to the menu bar. Select Quit to exit the menu, everything is now ready

23

Then you'll return to the UI interface. Use the previously initialized 1GB disk and select the OK button

24

Use the arrow keys to select fat32 file system type, then select the OK button

25

Confirm not to modify the name by selecting the OK button

26

Confirm formatting by selecting the Yes button

27

Then you'll return to the initial UI bar. Select the second partition that is not 1GB in size and select the OK button

28

Use the arrow keys to select ext4 file system type, then select the OK button

29

Confirm not to modify the name by selecting the OK button

30

Confirm formatting by selecting the Yes button

31

Choose not to use extra space for updates by selecting the No button

32

Confirm GRUB2 EFI BootLoader by selecting the OK button

33

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button.

34

System Initialization

After a while, you'll enter the logo screen.

35

After some more time, you should enter the initial Android interface. You'll see a popup and the time. Hold the left mouse button and swipe up

36

The main screen application selection will appear. Select Quickstep

If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine, and it should display after entering VNC

37

Removing the Image

After the Android interface appears, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

br

Then execute qm start 100 on the host machine again, and you should enter the system's initial interface.

Network Settings

After entering the desktop, you need to set up the network. Hold the left mouse button in the indicated position and swipe up

38

A bunch of applications will pop up. Find the one called Bliss Ethernet Manager and click to open it

39

Click to open IP Assignment, select Static type, click the OK button to confirm

40

Click to open IP Address, enter 172.16.1.xxx/24 (I used 100 for xxx because my virtual machine VMID is 100 for easy identification), click the OK button to confirm

41

Click to open Gateway Address, enter 172.16.1.1, click the OK button to confirm

42

Click to open DNS Address, enter 8.8.8.8, click the OK button to confirm

43

Then in the application interface, click Interface Up and Refresh, then press the exit key on the keyboard to exit the program

44

Open the browser in the main interface to verify that the network is working properly

45

You can see that opening this guide works without problems, the network is functioning

46

- +
Skip to content

Android Virtual Machine

Android System Image Download

Download links for Android system version 9 and earlier:

International

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

Domestic (China)

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Download links for Android system version 10 and later:

https://blissos.org/index.html#download

Virtual Machine Setup

Setting up an Android Virtual Machine with version 9 and earlier images

This guide demonstrates using:

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

as an example

1

Template Configuration

Create a virtual machine with VMID 100 and select the corresponding storage disk

2

Select the Android image, then choose Linux for Type and choose an option with version 2.6 for Version

3

Select Vmware compatible for Graphic card, other options are default as shown

4

Choose SATA for disk format, allocate at least 30GB of disk space (size can be chosen based on your needs)

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface

9

System Installation

After entering the boot menu, select the option starting with Installation

10

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it

11

Choose not to use GPT format

12

When the empty disk is displayed, select New

13

Select partition type Primary

14

Then you'll be prompted to specify the size of the space. Just press Enter to use all available space

15

Then select Flags, move to Bootable, press Enter until Boot appears under Flags

16

Then move to Write and press Enter to write changes

17

You'll be asked to confirm whether to continue. Type yes and press Enter to continue

18

After a progress bar completes, you'll return to the initial menu. Select Quit to exit the menu, everything is now ready

19

Then you'll return to the UI interface. Use the previously initialized disk and select the OK button

20

Use the arrow keys to select ext4 file system type, then select the OK button

21

Confirm formatting by selecting the Yes button

22

Confirm GRUB boot installation by selecting the OK button

23

Confirm the file system is readable and writable by selecting the OK button

24

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button

25

After a while, you'll enter the Android logo screen

26

Removing the Image

Then there will be a black screen. If it's still black after 3-5 minutes, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

ar

Then execute qm start 100 on the host machine again, and you should enter the Android system initialization interface

System Initialization

In the initialization interface, select the language and click the confirm button

27

It will try to connect to WiFi. Since our PVE installation uses a completely static network configuration, just skip this and set it up later

31

Click the next button to confirm the time settings

32

Click to cancel screen protection, confirm to skip again

33

After a period of black screen, the main screen application selection will appear. If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine as before, and it should display after entering VNC

Select Quickstep

34

Network Settings

After entering the desktop, you need to set up the network. Click the settings icon in the upper left corner

35

A dropdown appears, click and hold to pull down

36

Click the gear button

37

Enter Network & Internet settings

38

Double-click WIFI with the left mouse button

39

Modify the detected VirtWIFI. Right-click to bring up the selection box, then click Modify network

40

Advanced options appear, click to open hidden options

41

Configure the network settings as shown

IP address 172.16.1.xxx (replace xxx with your desired IP, I used 100 because my vmid is 100 for convenience)

Subnet mask 24

Default gateway 172.16.1.1

DNS 8.8.8.8 or 144.144.144.144

Then click the save button

42

At this point, the settings may still not be applied. Turn off WiFi and then turn it back on, it should then show as connected

43

Then exit to the main interface, click on Google Chrome, and try to open a webpage

44

You can see that opening this guide's URL works without problems, proving that the network is connected

45

Setting up an Android Virtual Machine with version 10 and later images

This guide demonstrates using:

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

as an example

1

Template Configuration

The host machine needs to execute the following command to install graphics environment dependencies

shell
apt install libgl1 libegl1 -y

Then start creating the virtual machine by clicking the Create VM button in the upper right corner. Fill in VMID, Name, Resource Pool

2

Select the Android image, then choose Linux for Type and an option with version 2.6 for Version

3

If the host machine has a GPU, select VirGL GPU for Graphic card.

If the host machine doesn't have a GPU, select VirtIO or Vmware compatible for Graphic card.

Select q35 for Machine, select OVMF (UEFI) for BIOS, and select local for EFI Storage.

4

Choose SATA for disk format. How much disk space to allocate is up to you, but at least 30GB is recommended

5

CPU count should be at least 2 cores

If your host machine supports nested virtualization, choose host for CPU type (verified to work)

If your host machine doesn't support nested virtualization, choose qemu64 for CPU type, and after creating the template, go to Options and uncheck KVM hardware virtualization before starting the virtual machine (no guarantee that system initialization will work properly)

6

Memory should be at least 4GB, enter at least 4096

7

Select vmbr1 for the network bridge, choose VirtIO (paravirtualized) for Model, and uncheck Firewall

8

After clicking the continue button, the template is successfully created. You need to manually start it and enter the VNC interface.

System Installation

After entering the boot menu, select the option ending with Installation

9

Then you need to create disk partitions. If you can't select it, press the keyboard button 'c' to select it.

10

Choose not to use GPT format, continue using cfdisk format.

11

When the format selection box appears, select gpt.

12

When the empty disk is displayed, select New.

13

Because you need to create an EFI partition, you need to change the size rather than using the default. Change the number to 1 to allocate 1GB of disk space, then press Enter.

14

Then you'll return to the menu bar. Use the arrow keys to select Type, then press Enter to choose the format type for the partition

15

Use the arrow keys to select the first option EFI System, then press Enter

16

Now you're back at the menu bar. In the upper half of the page, you can see the specific partition size and format

17

Then press the down arrow key to select the next empty partition line

18

Select New from the menu bar, then press Enter

19

Here you need to fill in the partition size. Match it with the empty partition size shown in the upper right corner, then press Enter.

20

Return to the menu bar, select Write, press Enter to write the partition.

21

You'll be prompted to enter yes to confirm. Enter it and press Enter.

22

After a progress bar runs, you should return to the menu bar. Select Quit to exit the menu, everything is now ready

23

Then you'll return to the UI interface. Use the previously initialized 1GB disk and select the OK button

24

Use the arrow keys to select fat32 file system type, then select the OK button

25

Confirm not to modify the name by selecting the OK button

26

Confirm formatting by selecting the Yes button

27

Then you'll return to the initial UI bar. Select the second partition that is not 1GB in size and select the OK button

28

Use the arrow keys to select ext4 file system type, then select the OK button

29

Confirm not to modify the name by selecting the OK button

30

Confirm formatting by selecting the Yes button

31

Choose not to use extra space for updates by selecting the No button

32

Confirm GRUB2 EFI BootLoader by selecting the OK button

33

After a progress bar runs for some time, it will show that installation was successful. Select Reboot and the OK button.

34

System Initialization

After a while, you'll enter the logo screen.

35

After some more time, you should enter the initial Android interface. You'll see a popup and the time. Hold the left mouse button and swipe up

36

The main screen application selection will appear. Select Quickstep

If this interface doesn't appear after waiting 3-5 minutes, restart the virtual machine, and it should display after entering VNC

37

Removing the Image

After the Android interface appears, execute qm stop 100 on the host machine, then start removing the image file.

Remove the installed ISO file by manually clicking on the corresponding CD in the Hardware section of the ProxmoxVE web interface and selecting Remove

br

Then execute qm start 100 on the host machine again, and you should enter the system's initial interface.

Network Settings

After entering the desktop, you need to set up the network. Hold the left mouse button in the indicated position and swipe up

38

A bunch of applications will pop up. Find the one called Bliss Ethernet Manager and click to open it

39

Click to open IP Assignment, select Static type, click the OK button to confirm

40

Click to open IP Address, enter 172.16.1.xxx/24 (I used 100 for xxx because my virtual machine VMID is 100 for easy identification), click the OK button to confirm

41

Click to open Gateway Address, enter 172.16.1.1, click the OK button to confirm

42

Click to open DNS Address, enter 8.8.8.8, click the OK button to confirm

43

Then in the application interface, click Interface Up and Refresh, then press the exit key on the keyboard to exit the program

44

Open the browser in the main interface to verify that the network is working properly

45

You can see that opening this guide works without problems, the network is functioning

46

+ \ No newline at end of file diff --git a/en/guide/pve/pve_custom.html b/en/guide/pve/pve_custom.html index 7007496cd0..4fb83140d5 100644 --- a/en/guide/pve/pve_custom.html +++ b/en/guide/pve/pve_custom.html @@ -5,51 +5,54 @@ Customized partitions | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Customized partitions

Installing Proxmox VE 7 on a non-Debian system

Minimum local hardware requirements are the same as for the previous normal installation.

You need to install docker first.

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

Then use uname -m to query the architecture and use the command corresponding to the architecture

The opened PVE panel information is:

Login username and password are both root, after logging in be sure to use web SSH to change the password to avoid being blown up.

When using host SSH, be sure to log into the corresponding https://IPV4:8006 to use SSH on the web panel, do not use the host's port 22 to manipulate the PVE.

Because the SSH on the web panel is inside Docker, it does not support subsequent one-click configurations, so please configure your own gateway, etc. to use it.

X86 architecture

bash
docker run -idt --network host \
---privileged \
---name pve \
---add-host pve:10.13.14.101 \
---hostname pve \
-spiritlhl/pve:7_x86_64

ARM architecture

bash
docker run -idt --network host \
---privileged \
---name pve \
---add-host pve:10.13.14.101 \
---hostname pve \
-spiritlhl/pve:7_aarch64

The web panel is actually opened in the container, but the network has used the host mode, the port of the PVE is about the same as the port of the host used.

But here the login username and password become root and root, if you need to change it please docker exec -it pve /bin/bash enter and change the password of root, then press ctrl key and A+D to exit.

There are many bugs need to be fixed, welcome to PR to solve the problem, the actual test on the Ubuntu system host machine to install Proxmox VE panel success, solved the problem of installing Proxmox VE over the network can only be used to use the Debian system as a host machine!

Optimizing the memory footprint of Proxmox-VE on low-configuration systems

The following optimization can reduce at least 400M memory occupation, some machines can reduce more than 6GB, the actual reduction of how much memory occupation to test by yourself.

Reduce the number of max_workers

Execute the following command to query

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

you can see

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

The default max_workers is 3, you can modify the corresponding file, the minimum max_workers can be 1, you can use the following commands to modify them:

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

Deactivation of HA services

Clusters (multi-nodes) can use the HA service, if it is a single node, or there is no need for HA use, you can execute the following command:

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

Disable firewall service

The service can be deactivated by executing the following command:

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

Discontinuation of cheduler service

If you don't need scheduled tasks, such as backups and synchronizations, you can deactivate the service by executing the following command:

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

Discontinuation of Spiceproxy service

If you do not need to use Spice for VM/container linking (the Arm version itself does not support Spice), you can deactivate the service by executing the following command:

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

Deleting the memory cache using a timed task

Clearing different types of caches and performing TRIM operations on file systems

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

The above commands require the sudo and crontab commands to be available on the host itself.

Self-mapping of public ports on KVM VMs with open NATs

Use the nano or vim command to modify the file to add port mapping:

/etc/iptables/rules.v4

For example, if I have a KVM VM with an intranet IP of 172.16.1.152, and MYSQL has been set up to listen to 3306, and I need to use the tcp protocol to map out to the 33306 port on the host IP, I would add the following line to the COMMIT line in the file above, then add the following line

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

Save the file and exit file editing and then execute:

service netfilter-persistent restart

Reload Port Mapping

At this point, on the host machine, execute the

lsof -i:33306

To see if the port mapping rule is in effect

Customizing the CPU TYPE when opening a Linux virtual machine

On the host computer, use something like

shell
echo "kvm64" > /usr/local/bin/cpu_type

Specifying the default CPU TYPE in this way allows you to replace kvm64 with the type you want

- +
Skip to content

Customized partitions

Installing Proxmox VE 7 on a non-Debian system

Minimum local hardware requirements are the same as for the previous normal installation.

You need to install docker first.

curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

Then use uname -m to query the architecture and use the command corresponding to the architecture

The opened PVE panel information is:

Login username and password are both root, after logging in be sure to use web SSH to change the password to avoid being blown up.

When using host SSH, be sure to log into the corresponding https://IPV4:8006 to use SSH on the web panel, do not use the host's port 22 to manipulate the PVE.

Because the SSH on the web panel is inside Docker, it does not support subsequent one-click configurations, so please configure your own gateway, etc. to use it.

X86 architecture

bash
docker run -idt --network host \
+--privileged \
+--name pve \
+--add-host pve:10.13.14.101 \
+--hostname pve \
+spiritlhl/pve:7_x86_64

ARM architecture

bash
docker run -idt --network host \
+--privileged \
+--name pve \
+--add-host pve:10.13.14.101 \
+--hostname pve \
+spiritlhl/pve:7_aarch64

The web panel is actually opened in the container, but the network has used the host mode, the port of the PVE is about the same as the port of the host used.

But here the login username and password become root and root, if you need to change it please docker exec -it pve /bin/bash enter and change the password of root, then press ctrl key and A+D to exit.

There are many bugs need to be fixed, welcome to PR to solve the problem, the actual test on the Ubuntu system host machine to install Proxmox VE panel success, solved the problem of installing Proxmox VE over the network can only be used to use the Debian system as a host machine!

Optimizing the memory footprint of Proxmox-VE on low-configuration systems

The following optimization can reduce at least 400M memory occupation, some machines can reduce more than 6GB, the actual reduction of how much memory occupation to test by yourself.

Reduce the number of max_workers

Execute the following command to query

cd /usr/share/perl5/PVE/Service
+grep 'max_workers => 3' *

you can see

pvedaemon.pm:    max_workers => 3,
+pveproxy.pm:    max_workers => 3,
+spiceproxy.pm:    max_workers => 3, # todo: do we need more?

The default max_workers is 3, you can modify the corresponding file, the minimum max_workers can be 1, you can use the following commands to modify them:

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

Deactivation of HA services

Clusters (multi-nodes) can use the HA service, if it is a single node, or there is no need for HA use, you can execute the following command:

systemctl stop pve-ha-lrm.service 
+systemctl stop pve-ha-crm.service 
+systemctl disable pve-ha-lrm.service 
+systemctl disable pve-ha-crm.service

Disable firewall service

The service can be deactivated by executing the following command:

systemctl stop pve-firewall.service 
+systemctl disable pve-firewall.service

Discontinuation of cheduler service

If you don't need scheduled tasks, such as backups and synchronizations, you can deactivate the service by executing the following command:

systemctl stop pvescheduler.service
+systemctl disable pvescheduler.service

Discontinuation of Spiceproxy service

If you do not need to use Spice for VM/container linking (the Arm version itself does not support Spice), you can deactivate the service by executing the following command:

systemctl stop spiceproxy.service 
+systemctl disable spiceproxy.service

Deleting the memory cache using a timed task

Clearing different types of caches and performing TRIM operations on file systems

shell
TEMP_CRON=$(mktemp)
+sudo crontab -l > $TEMP_CRON
+echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
+sudo crontab $TEMP_CRON
+rm $TEMP_CRON

The above commands require the sudo and crontab commands to be available on the host itself.

Self-mapping of public ports on KVM VMs with open NATs

Use the nano or vim command to modify the file to add port mapping:

/etc/iptables/rules.v4

For example, if I have a KVM VM with an intranet IP of 172.16.1.152, and MYSQL has been set up to listen to 3306, and I need to use the tcp protocol to map out to the 33306 port on the host IP, I would add the following line to the COMMIT line in the file above, then add the following line

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

Save the file and exit file editing and then execute:

service netfilter-persistent restart

Reload Port Mapping

At this point, on the host machine, execute the

lsof -i:33306

To see if the port mapping rule is in effect

Customizing the CPU TYPE when opening a Linux virtual machine

On the host computer, use something like

shell
echo "kvm64" > /usr/local/bin/cpu_type

Specifying the default CPU TYPE in this way allows you to replace kvm64 with the type you want

+ \ No newline at end of file diff --git a/en/guide/pve/pve_install.html b/en/guide/pve/pve_install.html index 83d79d3eb9..d327fc3a13 100644 --- a/en/guide/pve/pve_install.html +++ b/en/guide/pve/pve_install.html @@ -5,22 +5,25 @@ PVE Body Installation | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

PVE Body Installation

If you don't know how to choose an option during installation, just press enter.

TIP

For low-configuration hosts, it is recommended to check the contents of the Custom partition after all the content has been installed to perform memory tuning and reduce the memory footprint.

One-click PVE installation

TIP

Suggest debian12, the actual test part of the independent server debian11 system will appear a reboot network will be lost, debian12 does not have such a problem!

  • The installation is the latest PVE from the apt source at the moment.
  • For example, debian10 is pve6.4, debian11 is pve7.x, debian12 is pve8.x
  • Changes to the /etc/hosts file (to fix the wrong hostname setting for merchants and to add the required content for PVE)
  • /etc/cloud/cloud.cfg file modification (to avoid overwriting modified hostname etc.)
  • /etc/network/interfaces file modification (fix auto, dhcp type to static, add vmbr0 gateway)
  • Detect whether it is China IP, if it is China IP use Tsinghua mirror source, otherwise use the official source, and at the same time deal with the source of apt and the corresponding nameserver, to avoid disconnections
  • Create vmbr0 (independent IP gateway), the host allows addr and gateway for intranet IP or extranet IP, has been automatically recognized
  • vmbr0 creation support to open pure IPV4, pure IPV6, dual-stack virtual machine, automatic identification of IPV4 address and IPV6 address, automatic identification of the corresponding IP interval
  • Installation of the necessary toolkit for PVE to open a virtual machine
  • x86_64 replace enterprise subscriptions in apt sources with community sources, arm sources built using third-party patches for fixes
  • Print query Linux system kernel and PVE kernel installed or not
  • Setting up DNS detection 8.8.8.8.8 for boot add DNS systemd service
  • Download PVE and printout of login information after adding APT source link for PVE

All modified files have been set to read-only mode to avoid overwriting after reboot.

If you want to modify the file, please use chattr -i file path to cancel the read-only lock, and run chattr +i file path to lock the read-only lock when you finish modifying the file.

You will be prompted to reboot your system once during the execution process, After rebooting, be sure to wait at least 20 seconds to make sure the system does not reboot automatically again.

Because the original environment may be missing ifupdown or ifupdown2 environment, there is a self-installation daemon loaded for the installation, after the installation of the system will automatically reboot the system again, wait for 20 seconds without reboot to ensure that the installation has been run.

If the host itself exists SLAAC assigned IPV6 address, will be able to choose whether to use the largest IPV6 subnet range, the default carriage return does not use the largest IPV6 subnet range only use the local IPV6, if you subsequently need to attach a separate IPV6 address to the virtual machine/container, the option must be selected y.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

or

shell
bash install_pve.sh

TIP

After successful installation, the web page may not be safe to open, click on Advanced or More Options and insist on accessing it!

The login information is your SSH account and password.

Pre-configure the environment

  • Creating a resource pool mypool
  • Remove the subscription popup
  • Attempt to enable hardware passthrough
  • Detect and auto-install AppArmor modules.
  • Before rebooting the system, it is recommended to hook up nezha probe to facilitate the use of the command line in the background without SSH, to avoid the possibility that SSH may lead to the loss of the root password after the reboot due to the merchant's strange presets.
  • Before executing reboot, you need to wait for the background task to finish executing, some host system apt command execution is very slow, you have to wait for a while to finish executing, of course, most of the machines are not so bad!

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

Automatically configure the host's gateway

WARNING

Before using this command, please make sure that you have restarted the server and that PVE can use the WEB terminal normally before executing this command. Do not execute this command immediately after restarting the machine, wait for at least 1 minute after the WEB terminal is successfully started before executing this command. If the WEB side doesn't start, run systemctl status pveproxy to see if it starts, if it's stuck, run systemctl start pveproxy to start the WEB side.

TIP

This step is most likely to cause SSH disconnections, the reason is to modify the network without waiting for the PVE kernel to start, which will result in setting conflicts, so wait at least a few minutes until the kernel is started, that is, the WEB side is started successfully before execution.

TIP

If the host needs to attach an IPV6 tunnel (add an IPV6 subnet to a host that does not have an IPV6 address) before executing this command, please check the IPV6 free subnet attachment section to attach to the corresponding configuration file, but please ignore 'initial environment modifications' and attach directly, and then execute the following one-click gateway configuration commands after verifying that you have an IPV6 address.

  • If vmbr0 is not created, it is automatically created with the same logic as the main installation
  • Create vmbr1 (NAT gateway) to support IPV4 servers that open NAT for IPV6 networks with NAT.
  • Create vmbr2 (standalone IPV6 gateway), use ndppd to solve the problem of MAC verification of IPV6 addresses by the host, support the opening of servers with standalone IPV6 networks.
  • If you want to see the complete settings, you can execute cat /etc/network/interfaces to see, if you need to modify the gateway you need to modify the file, the web site can not be modified!
  • Load iptables and set back to source and allow NAT port forwarding.

In short, vmbr0 is responsible for v4 standalone IPs, and vmbr1 is responsible for complex v4/v6 NATs, vmbr2 is responsible for v6 standalone IPs.

Open independent IPV4 virtual machine using vmbr0, gateway with the host, IPV4/CIDR using the same network segment address and the same subnet mask, using the host's unbound IPV4 address for IPV4/CIDR, of course, if the subsequent use of this script does not need to pay attention to this point of the nuances of the thing

Use vmbr1 for IPV4 VM with NAT, 172.16.1.1 for gateway, 172.16.1.x/24 for IPV4/CIDR, where x can't be 1, but of course you don't need to pay attention to this minutia if you use this script later.

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

This step may require you to reboot your system after a few minutes of successful execution, see the final execution of the script at the end of the tip. However, a reboot will ensure that some of the hidden settings are loaded successfully, so be sure to reboot the server once if you are in a position to do so.

- +
Skip to content

PVE Body Installation

If you don't know how to choose an option during installation, just press enter.

TIP

For low-configuration hosts, it is recommended to check the contents of the Custom partition after all the content has been installed to perform memory tuning and reduce the memory footprint.

One-click PVE installation

TIP

Suggest debian12, the actual test part of the independent server debian11 system will appear a reboot network will be lost, debian12 does not have such a problem!

  • The installation is the latest PVE from the apt source at the moment.
  • For example, debian10 is pve6.4, debian11 is pve7.x, debian12 is pve8.x
  • Changes to the /etc/hosts file (to fix the wrong hostname setting for merchants and to add the required content for PVE)
  • /etc/cloud/cloud.cfg file modification (to avoid overwriting modified hostname etc.)
  • /etc/network/interfaces file modification (fix auto, dhcp type to static, add vmbr0 gateway)
  • Detect whether it is China IP, if it is China IP use Tsinghua mirror source, otherwise use the official source, and at the same time deal with the source of apt and the corresponding nameserver, to avoid disconnections
  • Create vmbr0 (independent IP gateway), the host allows addr and gateway for intranet IP or extranet IP, has been automatically recognized
  • vmbr0 creation support to open pure IPV4, pure IPV6, dual-stack virtual machine, automatic identification of IPV4 address and IPV6 address, automatic identification of the corresponding IP interval
  • Installation of the necessary toolkit for PVE to open a virtual machine
  • x86_64 replace enterprise subscriptions in apt sources with community sources, arm sources built using third-party patches for fixes
  • Print query Linux system kernel and PVE kernel installed or not
  • Setting up DNS detection 8.8.8.8.8 for boot add DNS systemd service
  • Download PVE and printout of login information after adding APT source link for PVE

All modified files have been set to read-only mode to avoid overwriting after reboot.

If you want to modify the file, please use chattr -i file path to cancel the read-only lock, and run chattr +i file path to lock the read-only lock when you finish modifying the file.

You will be prompted to reboot your system once during the execution process, After rebooting, be sure to wait at least 20 seconds to make sure the system does not reboot automatically again.

Because the original environment may be missing ifupdown or ifupdown2 environment, there is a self-installation daemon loaded for the installation, after the installation of the system will automatically reboot the system again, wait for 20 seconds without reboot to ensure that the installation has been run.

If the host itself exists SLAAC assigned IPV6 address, will be able to choose whether to use the largest IPV6 subnet range, the default carriage return does not use the largest IPV6 subnet range only use the local IPV6, if you subsequently need to attach a separate IPV6 address to the virtual machine/container, the option must be selected y.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

or

shell
bash install_pve.sh

TIP

After successful installation, the web page may not be safe to open, click on Advanced or More Options and insist on accessing it!

The login information is your SSH account and password.

Pre-configure the environment

  • Creating a resource pool mypool
  • Remove the subscription popup
  • Attempt to enable hardware passthrough
  • Detect and auto-install AppArmor modules.
  • Before rebooting the system, it is recommended to hook up nezha probe to facilitate the use of the command line in the background without SSH, to avoid the possibility that SSH may lead to the loss of the root password after the reboot due to the merchant's strange presets.
  • Before executing reboot, you need to wait for the background task to finish executing, some host system apt command execution is very slow, you have to wait for a while to finish executing, of course, most of the machines are not so bad!

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

Automatically configure the host's gateway

WARNING

Before using this command, please make sure that you have restarted the server and that PVE can use the WEB terminal normally before executing this command. Do not execute this command immediately after restarting the machine, wait for at least 1 minute after the WEB terminal is successfully started before executing this command. If the WEB side doesn't start, run systemctl status pveproxy to see if it starts, if it's stuck, run systemctl start pveproxy to start the WEB side.

TIP

This step is most likely to cause SSH disconnections, the reason is to modify the network without waiting for the PVE kernel to start, which will result in setting conflicts, so wait at least a few minutes until the kernel is started, that is, the WEB side is started successfully before execution.

TIP

If the host needs to attach an IPV6 tunnel (add an IPV6 subnet to a host that does not have an IPV6 address) before executing this command, please check the IPV6 free subnet attachment section to attach to the corresponding configuration file, but please ignore 'initial environment modifications' and attach directly, and then execute the following one-click gateway configuration commands after verifying that you have an IPV6 address.

  • If vmbr0 is not created, it is automatically created with the same logic as the main installation
  • Create vmbr1 (NAT gateway) to support IPV4 servers that open NAT for IPV6 networks with NAT.
  • Create vmbr2 (standalone IPV6 gateway), use ndppd to solve the problem of MAC verification of IPV6 addresses by the host, support the opening of servers with standalone IPV6 networks.
  • If you want to see the complete settings, you can execute cat /etc/network/interfaces to see, if you need to modify the gateway you need to modify the file, the web site can not be modified!
  • Load iptables and set back to source and allow NAT port forwarding.

In short, vmbr0 is responsible for v4 standalone IPs, and vmbr1 is responsible for complex v4/v6 NATs, vmbr2 is responsible for v6 standalone IPs.

Open independent IPV4 virtual machine using vmbr0, gateway with the host, IPV4/CIDR using the same network segment address and the same subnet mask, using the host's unbound IPV4 address for IPV4/CIDR, of course, if the subsequent use of this script does not need to pay attention to this point of the nuances of the thing

Use vmbr1 for IPV4 VM with NAT, 172.16.1.1 for gateway, 172.16.1.x/24 for IPV4/CIDR, where x can't be 1, but of course you don't need to pay attention to this minutia if you use this script later.

Command:

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

This step may require you to reboot your system after a few minutes of successful execution, see the final execution of the script at the end of the tip. However, a reboot will ensure that some of the hidden settings are loaded successfully, so be sure to reboot the server once if you are in a position to do so.

+ \ No newline at end of file diff --git a/en/guide/pve/pve_kvm.html b/en/guide/pve/pve_kvm.html index d0438e98bd..3c8853fa3b 100644 --- a/en/guide/pve/pve_kvm.html +++ b/en/guide/pve/pve_kvm.html @@ -5,36 +5,39 @@ Linux Virtual Machine (KVM/TCG Virtualization) | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Linux Virtual Machine (KVM/TCG Virtualization)

SSH Login Instructions

When open a virtual machine, the default generated username can be something other than root, in which case you need to run sudo -i to switch to root!

If the default username is not root, the default unset root password is password or oneclickvirt.

After logging into SSH and switching to root privileges, be sure to change the root password, which can be changed using the following command:

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

Considerations for opening a virtual machine with an IPV6 address

Due to long-term inactivity IPV6 does not use may lead to NDP broadcast cache invalidation reset, generally idle for about 50 minutes will appear IPV6 unavailable, commonly known as "IPV6 cutoff", at this time it is necessary to set up a timer task.

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

Executing the above commands in the opened virtual machine ensures that the IPV6 network is always used and does not fail over.

Images available for creating virtual machines

  • Pre-installed with cloud-init enabled.
  • Enabled SSH login.
  • Pre-configured SSH to listen on ports 22 for both IPv4 and IPv6.
  • Enabled password authentication for login.
  • Enabled root login.
  • Partially pre-installed QEMU guest agent.

The list of currently available image names is as follows:

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

and

https://github.com/oneclickvirt/pve_kvm_images

Daily patch images stored in the Release of this repository.

Virtual machines with standalone NAT configuration.

  • Automatically deploy NAT servers with the default Debian 10 image, chosen for its minimal footprint.
  • It's possible to customize the image used through the command, and pre-configured images are available. These images come with storage settings ranging from 2 to 10 GB of disk space. For regular use, at least 10 GB of disk space is recommended. You can increase the disk size if certain images fail to start.
  • The command allows for specifying the storage disk location. When not specified, it defaults to the local disk, which is the system disk. It can also be set to a mount disk as displayed in PVE.
  • Recommended custom memory size is 512 MB.
  • Automatic internal and external port mapping, including ports 22, 80, 443, and 25 other port numbers shared between internal and external networks.
  • After generation, there's a wait time for the virtual machine's internal cloud-init configuration to establish network and login information. This process takes approximately 5 minutes.
  • Pertinent virtual machine information will be stored in the NOTES section of the corresponding VM on the web interface, accessible for viewing through the web portal.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically added. However, there won't be any public IPV6 addresses.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

System Support:

  • For x86_64 architecture systems listed in this link, simply use the filename without the .qcow2 extension when using.
  • For arm architecture systems listed at this link, use the system name and version number, such as ubuntu20 or ubuntu22.

TIP

Note that usernames consisting of only numbers may cause issues with cloud-init. It's preferable to use usernames that are entirely in English or start with an English character.

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

Meaning of each parameter

shell
# ./buildvm.sh VMID Username Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Public_Port_Start Public_Port_End System Storage_Disk Independent_IPV6_address(leave default N blank)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

After setup is completed, you can execute cat vm111 to view the information or check the NOTES section for the corresponding VM on the WEB interface.

Below is the information for the example VM that has been set up:

AttributeValue
VMID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size10G
SSH Port40001
Port 8040002
Port 44340003
Port Range for NAT50000 to 50025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific VM

  • Stop VM
  • Delete VM
  • Delete port mapping
  • Restart network
  • Delete log files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the VM with the corresponding VMID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each VMID, and more than one can be deleted at a time.

Batch Creation of Virtual Machines with NAT

WARNING

Before initial use, ensure that the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port forwarding, as conflicting settings may result in bugs.

TIP

Before initiating the batch creation process, please use the 'screen' command to execute it in the background. This will help avoid interruptions due to the instability of SSH caused by extended batch creation times.

  • The batch creation process can be run multiple times to generate multiple virtual machines (VMs).
  • NAT servers are automatically created during the process. If left blank, the default Debian 11 image will be used. You can also customize the image name. Refer to the list of supported images in the previous section.
  • Automatic internal and external port mapping is performed, including ports 22, 80, 443, and other ports with identical internal and external numbers (25 ports in total).
  • After generation, a waiting period is required for the cloud-init configuration of the VM's network and login information to be set up. This process takes approximately 5 minutes. There is a 60-second interval between creating each VM to avoid potential performance issues.
  • The default network configuration for VMs created in batches includes port mappings for ports 22, 80, 443, and a range of 25 ports for internal and external communication.
  • You can customize the number of CPU cores, memory size, disk size, and which storage disk on the host machine to use for batch creation. Ensure you calculate available resources before proceeding.
  • Relevant information about the virtual machines will be stored in the 'NOTES' section of the corresponding VM on the web interface, where you can view them.
  • If the host machine comes with an IPv6 subnet, an IPv6 network will be automatically attached, although there will be no public IPv6 addresses available.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

After the setup is completed, you can execute cat vmlog to view the information, or check the NOTES in the corresponding VM on the web interface.

Delete All Virtual Machines

  • Delete all VMs
  • Delete all NAT port mappings
  • Restart the network
  • Delete log files
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

Before modifying the VM configuration for PVE, you must shut it down first. After making the configuration changes, start it again to avoid configuration reload errors.

Setting Up Virtual Machines with Dedicated IPv4 Addresses

Three scripts, each with its own advantages and disadvantages.

The first two scripts don't require an additional IPV4 address to be bound to the vmbr0 interface beforehand, and the opened VM will directly bind the additional IPV4 address.

The last script requires additional IPV4 addresses to be bound to the vmbr0 interface beforehand, and the opened VM will do NAT full port mapping to the intranet IPV4 address, **without directly binding additional IPV4 addresses.

Automatically selects additional IPV4 addresses on the same subnet as the host machine to open the virtual machine

WARNING

Before use, ensure that the current host machine has at least 2 available IP addresses within its IP range, and there are unallocated IP addresses. These unallocated IP addresses should not be bound to the host machine.

TIP

At this point, the IPV4 address appended is the address following the host's current IPV4 address in sequence. For example, if the current host address is 1.1.1.32 and then 1.1.1.33 there is already a virtual machine, then this script appends an IP address of 1.1.1.34.

  • Automatically detect available IP ranges. Use ping to identify unallocated IP addresses and select one to bind to the virtual machine.
  • If the host machine has an accompanying IPv6 subnet, there will be an option to attach an IPv6 address.
  • Relevant system information will be stored in the corresponding virtual machine's NOTE section, accessible for viewing on the web interface.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • The automatically appended IPV4 address is within the same subnet as the host's IPV4 address (IP address prefix is the same)
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

Meaning of each parameter

shell
# ./buildvm_extra_ip.sh VMID Username Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB OS Storage_Disk Attach_IPV6(Default is N)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

The above command is used to create a virtual machine with a dedicated IPv4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
OSdebian12
Storagelocal disk
IPv6 AddonNot attached by default

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Manually Assign Additional IPV4 Addresses to Open Virtual Machines

  • Manual specification of IPV4 address with subnet length in the command is required.
  • If the host machine comes with an IPV6 subnet, you can choose whether to add an IPV6 address additionally.
  • If the vendor has provided an IPV4 address and subnet length, please carefully compare and write the parameters in the command format shown below.
  • Relevant system information will be stored in the NOTE of the corresponding virtual machine and can be viewed on the WEB end.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • Manually appended IPV4 addresses that are in different subnets from the host's IPV4 address (different IP address prefixes) will use the host's IP address as the gateway
  • Manually appended IPV4 addresses that are within the same subnet as the host's IPV4 address (same IP address prefix) will use the host's gateway as the gateway
  • Optionally specify the MAC address of the virtual machine
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

TIP

If IP addresses within different subnets are appended without a MAC address, the router will not recognize the source MAC address, and the traffic will be flagged as “misuse” and “may” cause the server to be blocked. (If you are using a Hetzner standalone server, it is recommended that you provide the MAC address of the attached IPV4 address to prevent abuse from being reported.)

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

Meaning of each parameter

shell
# ./buildvm_manual_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N) MAC_ADDRESS(Optional whether to specify)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
Subnet/24 Subnet
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Host manually appends an additional IPV4 address and then specifies the IPV4 address to open the virtual machine

  • You need to add the extra IPV4 address to vmbr0 in /etc/network/interfaces (note that chattr -i unlocks the file and then chattr +i locks it back).
  • Other features are similar to opening a NAT-enabled VM, except that here the mapping is no longer partial port mapping or mapping to the host's IPV4 address, but full-port one-by-one mapping to additional IPV4 addresses
  • Traffic coming into the VM from outside the VM goes to the bound additional IPV4 address, and traffic going out of the VM goes to the original host's IPV4 address

TIP

Make sure you can SSH into the host with the extra IPV4 address before opening, but curl ip.sb still shows the original host IPV4 address.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

Meaning of each parameter

shell
# ./buildvm_fullnat_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Incoming and outgoing traffic goes to the bound IPV4 address

execute

line="-A POSTROUTING -s 172.16.1.0\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

This will cause the host to lose the ability to open VMs/containers with NAT that do not have a separate IPV4 address, so be careful!

After this, You will only be able to open VMs with separate IPV4 addresses.

Creating Virtual Machines with Pure IPv6 Addresses

The prerequisite is that the host provides an IPv6 subnet instead of just a standalone IPv6 address, and the host does not have MAC address verification enabled.

Automatic Selection of IPv6 Addresses without Manual Specification

  • Pure IPV6 refers to a bound public IPV6 address, where the actual VM still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address, based on the virtual machine's number, to the virtual machine.
  • System-related information will be stored in the NOTES section of the respective virtual machine, accessible for viewing on the web interface.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

Meaning of each parameter

shell
# ./buildvm_onlyv6.sh VMID username password CPU_cores memory_GB disk_GB operating_system storage_disk

TIP

Note that the password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

The above command is used to create a virtual machine with only IPv6 addresses.

ParameterValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage Disklocal

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Delete Example vm152

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
- +
Skip to content

Linux Virtual Machine (KVM/TCG Virtualization)

SSH Login Instructions

When open a virtual machine, the default generated username can be something other than root, in which case you need to run sudo -i to switch to root!

If the default username is not root, the default unset root password is password or oneclickvirt.

After logging into SSH and switching to root privileges, be sure to change the root password, which can be changed using the following command:

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

Considerations for opening a virtual machine with an IPV6 address

Due to long-term inactivity IPV6 does not use may lead to NDP broadcast cache invalidation reset, generally idle for about 50 minutes will appear IPV6 unavailable, commonly known as "IPV6 cutoff", at this time it is necessary to set up a timer task.

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

Executing the above commands in the opened virtual machine ensures that the IPV6 network is always used and does not fail over.

Images available for creating virtual machines

  • Pre-installed with cloud-init enabled.
  • Enabled SSH login.
  • Pre-configured SSH to listen on ports 22 for both IPv4 and IPv6.
  • Enabled password authentication for login.
  • Enabled root login.
  • Partially pre-installed QEMU guest agent.

The list of currently available image names is as follows:

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

and

https://github.com/oneclickvirt/pve_kvm_images

Daily patch images stored in the Release of this repository.

Virtual machines with standalone NAT configuration.

  • Automatically deploy NAT servers with the default Debian 10 image, chosen for its minimal footprint.
  • It's possible to customize the image used through the command, and pre-configured images are available. These images come with storage settings ranging from 2 to 10 GB of disk space. For regular use, at least 10 GB of disk space is recommended. You can increase the disk size if certain images fail to start.
  • The command allows for specifying the storage disk location. When not specified, it defaults to the local disk, which is the system disk. It can also be set to a mount disk as displayed in PVE.
  • Recommended custom memory size is 512 MB.
  • Automatic internal and external port mapping, including ports 22, 80, 443, and 25 other port numbers shared between internal and external networks.
  • After generation, there's a wait time for the virtual machine's internal cloud-init configuration to establish network and login information. This process takes approximately 5 minutes.
  • Pertinent virtual machine information will be stored in the NOTES section of the corresponding VM on the web interface, accessible for viewing through the web portal.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically added. However, there won't be any public IPV6 addresses.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

System Support:

  • For x86_64 architecture systems listed in this link, simply use the filename without the .qcow2 extension when using.
  • For arm architecture systems listed at this link, use the system name and version number, such as ubuntu20 or ubuntu22.

TIP

Note that usernames consisting of only numbers may cause issues with cloud-init. It's preferable to use usernames that are entirely in English or start with an English character.

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

Meaning of each parameter

shell
# ./buildvm.sh VMID Username Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Public_Port_Start Public_Port_End System Storage_Disk Independent_IPV6_address(leave default N blank)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

After setup is completed, you can execute cat vm111 to view the information or check the NOTES section for the corresponding VM on the WEB interface.

Below is the information for the example VM that has been set up:

AttributeValue
VMID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size10G
SSH Port40001
Port 8040002
Port 44340003
Port Range for NAT50000 to 50025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific VM

  • Stop VM
  • Delete VM
  • Delete port mapping
  • Restart network
  • Delete log files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the VM with the corresponding VMID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each VMID, and more than one can be deleted at a time.

Batch Creation of Virtual Machines with NAT

WARNING

Before initial use, ensure that the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port forwarding, as conflicting settings may result in bugs.

TIP

Before initiating the batch creation process, please use the 'screen' command to execute it in the background. This will help avoid interruptions due to the instability of SSH caused by extended batch creation times.

  • The batch creation process can be run multiple times to generate multiple virtual machines (VMs).
  • NAT servers are automatically created during the process. If left blank, the default Debian 11 image will be used. You can also customize the image name. Refer to the list of supported images in the previous section.
  • Automatic internal and external port mapping is performed, including ports 22, 80, 443, and other ports with identical internal and external numbers (25 ports in total).
  • After generation, a waiting period is required for the cloud-init configuration of the VM's network and login information to be set up. This process takes approximately 5 minutes. There is a 60-second interval between creating each VM to avoid potential performance issues.
  • The default network configuration for VMs created in batches includes port mappings for ports 22, 80, 443, and a range of 25 ports for internal and external communication.
  • You can customize the number of CPU cores, memory size, disk size, and which storage disk on the host machine to use for batch creation. Ensure you calculate available resources before proceeding.
  • Relevant information about the virtual machines will be stored in the 'NOTES' section of the corresponding VM on the web interface, where you can view them.
  • If the host machine comes with an IPv6 subnet, an IPv6 network will be automatically attached, although there will be no public IPv6 addresses available.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

After the setup is completed, you can execute cat vmlog to view the information, or check the NOTES in the corresponding VM on the web interface.

Delete All Virtual Machines

  • Delete all VMs
  • Delete all NAT port mappings
  • Restart the network
  • Delete log files
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4
+rm -rf vmlog
+rm -rf vm*

TIP

Before modifying the VM configuration for PVE, you must shut it down first. After making the configuration changes, start it again to avoid configuration reload errors.

Setting Up Virtual Machines with Dedicated IPv4 Addresses

Three scripts, each with its own advantages and disadvantages.

The first two scripts don't require an additional IPV4 address to be bound to the vmbr0 interface beforehand, and the opened VM will directly bind the additional IPV4 address.

The last script requires additional IPV4 addresses to be bound to the vmbr0 interface beforehand, and the opened VM will do NAT full port mapping to the intranet IPV4 address, **without directly binding additional IPV4 addresses.

Automatically selects additional IPV4 addresses on the same subnet as the host machine to open the virtual machine

WARNING

Before use, ensure that the current host machine has at least 2 available IP addresses within its IP range, and there are unallocated IP addresses. These unallocated IP addresses should not be bound to the host machine.

TIP

At this point, the IPV4 address appended is the address following the host's current IPV4 address in sequence. For example, if the current host address is 1.1.1.32 and then 1.1.1.33 there is already a virtual machine, then this script appends an IP address of 1.1.1.34.

  • Automatically detect available IP ranges. Use ping to identify unallocated IP addresses and select one to bind to the virtual machine.
  • If the host machine has an accompanying IPv6 subnet, there will be an option to attach an IPv6 address.
  • Relevant system information will be stored in the corresponding virtual machine's NOTE section, accessible for viewing on the web interface.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • The automatically appended IPV4 address is within the same subnet as the host's IPV4 address (IP address prefix is the same)
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

Meaning of each parameter

shell
# ./buildvm_extra_ip.sh VMID Username Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB OS Storage_Disk Attach_IPV6(Default is N)

TIP

Note that the Password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the Password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

The above command is used to create a virtual machine with a dedicated IPv4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
OSdebian12
Storagelocal disk
IPv6 AddonNot attached by default

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Manually Assign Additional IPV4 Addresses to Open Virtual Machines

  • Manual specification of IPV4 address with subnet length in the command is required.
  • If the host machine comes with an IPV6 subnet, you can choose whether to add an IPV6 address additionally.
  • If the vendor has provided an IPV4 address and subnet length, please carefully compare and write the parameters in the command format shown below.
  • Relevant system information will be stored in the NOTE of the corresponding virtual machine and can be viewed on the WEB end.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.
  • Manually appended IPV4 addresses that are in different subnets from the host's IPV4 address (different IP address prefixes) will use the host's IP address as the gateway
  • Manually appended IPV4 addresses that are within the same subnet as the host's IPV4 address (same IP address prefix) will use the host's gateway as the gateway
  • Optionally specify the MAC address of the virtual machine
  • Inbound and outbound traffic in and out of the VM goes to the additional IPV4 address of the binding

TIP

If IP addresses within different subnets are appended without a MAC address, the router will not recognize the source MAC address, and the traffic will be flagged as “misuse” and “may” cause the server to be blocked. (If you are using a Hetzner standalone server, it is recommended that you provide the MAC address of the attached IPV4 address to prevent abuse from being reported.)

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

Meaning of each parameter

shell
# ./buildvm_manual_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N) MAC_ADDRESS(Optional whether to specify)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
Subnet/24 Subnet
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Host manually appends an additional IPV4 address and then specifies the IPV4 address to open the virtual machine

  • You need to add the extra IPV4 address to vmbr0 in /etc/network/interfaces (note that chattr -i unlocks the file and then chattr +i locks it back).
  • Other features are similar to opening a NAT-enabled VM, except that here the mapping is no longer partial port mapping or mapping to the host's IPV4 address, but full-port one-by-one mapping to additional IPV4 addresses
  • Traffic coming into the VM from outside the VM goes to the bound additional IPV4 address, and traffic going out of the VM goes to the original host's IPV4 address

TIP

Make sure you can SSH into the host with the extra IPV4 address before opening, but curl ip.sb still shows the original host IPV4 address.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

Meaning of each parameter

shell
# ./buildvm_fullnat_ip.sh VMID USERNAME PASSWORD CPU_CORES MEMORY_SIZE_GB STORAGE_SIZE_GB OS STORAGE_DISK IPV4_ADDRESS ATTACH_IPV6(defaults to N)

TIP

Note that the PASSWORD here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the PASSWORD due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

The above command is used to create a virtual machine with an independent IPV4 address.

AttributeValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)
IPV4 Addressa.b.c.d
IPV6None
MAC_ADDRESSNone

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Incoming and outgoing traffic goes to the bound IPV4 address

execute

line="-A POSTROUTING -s 172.16.1.0\/24 -o vmbr0 -j MASQUERADE"
+sed -i "\|$line|d" /etc/iptables/rules.v4
+service netfilter-persistent restart

This will cause the host to lose the ability to open VMs/containers with NAT that do not have a separate IPV4 address, so be careful!

After this, You will only be able to open VMs with separate IPV4 addresses.

Creating Virtual Machines with Pure IPv6 Addresses

The prerequisite is that the host provides an IPv6 subnet instead of just a standalone IPv6 address, and the host does not have MAC address verification enabled.

Automatic Selection of IPv6 Addresses without Manual Specification

  • Pure IPV6 refers to a bound public IPV6 address, where the actual VM still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address, based on the virtual machine's number, to the virtual machine.
  • System-related information will be stored in the NOTES section of the respective virtual machine, accessible for viewing on the web interface.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

Meaning of each parameter

shell
# ./buildvm_onlyv6.sh VMID username password CPU_cores memory_GB disk_GB operating_system storage_disk

TIP

Note that the password here should be a mix of English and numbers only, and start with English, so as to avoid failing to set the password due to special characters being escaped during the setup process.

Test Example

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

The above command is used to create a virtual machine with only IPv6 addresses.

ParameterValue
VMID152
Usernameroot
Passwordoneclick123
CPU1 core
Memory1024MB
Disk10GB
Operating Systemdebian12
Storage Disklocal

TIP

Note that only VMIDs from 100 to 256 can be used here, no other numbers can be used.

Delete Example vm152

shell
qm stop 152
+qm destroy 152
+systemctl restart ndpresponder.service
+rm -rf vm152
+ \ No newline at end of file diff --git a/en/guide/pve/pve_lxc.html b/en/guide/pve/pve_lxc.html index 0bc19a220a..b0a8a434b0 100644 --- a/en/guide/pve/pve_lxc.html +++ b/en/guide/pve/pve_lxc.html @@ -5,33 +5,36 @@ LXC Virtualization | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXC Virtualization

WARNING

If you need to open more than 200 LXC containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Images available for creating LXC Containers

x86_64:

Auto-patching images: https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

Automated daily pulls for compilation and patching

Self-patching images: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

Some of these images are flawed and not guaranteed to be available for all PVEs, with names like ubuntu16.04, debian6, centos7, opensuse42.2, opensuse42.3 Don't use them unless necessary.

and

Run pveam available --section system to see the names and version numbers of the officially available systems.

Priority: Self-patching images (not supported by Proxmox-VE 5 and below) > Official default images (both supported) image

The version has been automatically recognized by a script to use the corresponding image.

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

Supported systems can be viewed in the file above, which lists debian and ubuntu systems do not use the aliases in it, just use the numeric designators.

TIP

All system parameters are lowercase system names spliced with version numbers, e.g. debian11, ubuntu22, etc. (Self-patched images support some out-of-the-way systems, such as centos6, centos7, debian8, debian9, etc.)

The default CT username for all systems is root

TIP

Of course, sometimes there are special cases where the version may be current/base, in which case it is sufficient to use only the English system name, e.g. archlinux, gentoo, kali.

Creating Individual LXC Containers for Virtualization

WARNING

Before initial use, ensure that the current PVE (Proxmox Virtual Environment) is clean and the host machine has not undergone any port mapping, as conflicts in settings could lead to bugs.

TIP

Before creating containers, use the 'screen' command to run them in the background. This helps to avoid extended creation times that might lead to interruptions due to unstable SSH connections.

  • Automatically create NAT servers using the default Debian 11 image, or customize the system image as needed.
  • Automatically perform internal and external network port mapping, including ports 22, 80, 443, and 25 additional ports with identical numbers for both internal and external networks.
  • After generation, allow some time for the virtual machine to configure its internal network and login information. This process takes approximately 3 minutes.
  • The default network configuration includes port mappings for 22, 80, 443, and a range of 25 ports for both internal and external networks.
  • Customize the number of cores, memory size, disk size, and the storage disk on the host machine for allocation. Ensure that you calculate available resources before creating containers.
  • Optionally specify the storage disk location in the command. When not specified, it defaults to the local disk, which is the system disk. Alternatively, you can specify a mount disk as displayed in PVE.
  • The created containers are enabled with SSH by default, allowing root login. They are also configured to support nested virtualization for Docker.
  • Relevant container information will be stored in the respective container's notes, accessible through the web interface.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically attached, but no public IPV6 addresses will be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

Meaning of each parameter

shell
# ./buildct.sh CTID Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Start_Public_Port End_Public_Port System Storage_Disk Independent_IPV6_address(leave default N blank)

Test Example

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

After setting up, you can execute cat ct111 to view the information, or check the NOTES section on the web interface.

Here is the information for the created example CT:

Please note that "CT" and other technical terms might have specific meanings in different contexts. If "CT" stands for something specific in your domain, you might want to provide additional context for accurate translation.

AttributeValue
CTID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size5G
SSH Port20001
Port 8020002
Port 44320003
Port Range for NAT30000 to 30025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific CT

  • Stop CT
  • Delete CT
  • Delete Port Mapping
  • Restart Network
  • Delete Log Files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the CT with the corresponding CTID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each CTID, and more than one can be deleted at a time.

Batch Creation of LXC Containers with NAT

WARNING

Make sure the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port mapping before the first use, as conflicting settings may result in bugs.

TIP

Before initiating the creation process, it's recommended to use the 'screen' command to execute the batch creation. This will prevent interruptions due to potential instability in SSH during the extended creation time.

  • It is possible to run the batch container creation process multiple times. However, please be mindful of allocating enough memory to the host machine to prevent system crashes. For adding swap space, refer to this link.
  • There is a 60-second interval between creating each container to avoid sudden performance bottlenecks.
  • Customization options include selecting the number of CPU cores, memory size, disk size, and the storage drive on the host machine. Ensure that you have calculated available resources appropriately before initiating the process.
  • The created containers have SSH enabled by default, allowing root login. Additionally, they are configured to support nested virtualization for Docker usage.
  • Relevant information about the containers will be stored in the corresponding container's notes, which can be viewed on the web interface.
  • If the host machine has an IPv6 subnet, it will be automatically assigned to the containers. However, public IPv6 addresses will not be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

After the setup is complete, you can execute cat ctlog to view the information, or check in the NOTES section on the web interface.

Delete All CT

  • Delete all CTs
  • Delete port mappings for all NATs
  • Restart the network
  • Delete log files
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

Creating Virtual Machines with Pure IPv6 Addresses

The premise is that the host provides an IPv6 subnet rather than a standalone IPv6 address, and the host does not have MAC address filtering enabled.

Automatic Selection of IPv6 Addresses, No Manual Configuration Needed

  • Pure IPV6 refers to a bound public IPV6 address, where the actual container still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address based on the container number to the container.
  • Relevant system information will be stored in the NOTES of the corresponding container, accessible for viewing on the web interface.

Download script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

Example Usage

shell
./buildct_onlyv6.sh CTID Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB Operating_System Storage_Disk
shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

The above command signifies the creation of a container with a pure IPV6 address.

AttributeValue
Container TypeCT
CTID152
Usernameroot
Passwordoneclick123
CPU Cores1
Memory1024MB
Disk10G
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion Example

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
- +
Skip to content

LXC Virtualization

WARNING

If you need to open more than 200 LXC containers on a single server, then it is not recommended to use this project, there may be problems with lxcfs access drift, which generates IO occupancy that cannot be released. (This is a native LXC problem that can't be fixed.)

Images available for creating LXC Containers

x86_64:

Auto-patching images: https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

Automated daily pulls for compilation and patching

Self-patching images: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

Some of these images are flawed and not guaranteed to be available for all PVEs, with names like ubuntu16.04, debian6, centos7, opensuse42.2, opensuse42.3 Don't use them unless necessary.

and

Run pveam available --section system to see the names and version numbers of the officially available systems.

Priority: Self-patching images (not supported by Proxmox-VE 5 and below) > Official default images (both supported) image

The version has been automatically recognized by a script to use the corresponding image.

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

Supported systems can be viewed in the file above, which lists debian and ubuntu systems do not use the aliases in it, just use the numeric designators.

TIP

All system parameters are lowercase system names spliced with version numbers, e.g. debian11, ubuntu22, etc. (Self-patched images support some out-of-the-way systems, such as centos6, centos7, debian8, debian9, etc.)

The default CT username for all systems is root

TIP

Of course, sometimes there are special cases where the version may be current/base, in which case it is sufficient to use only the English system name, e.g. archlinux, gentoo, kali.

Creating Individual LXC Containers for Virtualization

WARNING

Before initial use, ensure that the current PVE (Proxmox Virtual Environment) is clean and the host machine has not undergone any port mapping, as conflicts in settings could lead to bugs.

TIP

Before creating containers, use the 'screen' command to run them in the background. This helps to avoid extended creation times that might lead to interruptions due to unstable SSH connections.

  • Automatically create NAT servers using the default Debian 11 image, or customize the system image as needed.
  • Automatically perform internal and external network port mapping, including ports 22, 80, 443, and 25 additional ports with identical numbers for both internal and external networks.
  • After generation, allow some time for the virtual machine to configure its internal network and login information. This process takes approximately 3 minutes.
  • The default network configuration includes port mappings for 22, 80, 443, and a range of 25 ports for both internal and external networks.
  • Customize the number of cores, memory size, disk size, and the storage disk on the host machine for allocation. Ensure that you calculate available resources before creating containers.
  • Optionally specify the storage disk location in the command. When not specified, it defaults to the local disk, which is the system disk. Alternatively, you can specify a mount disk as displayed in PVE.
  • The created containers are enabled with SSH by default, allowing root login. They are also configured to support nested virtualization for Docker.
  • Relevant container information will be stored in the respective container's notes, accessible through the web interface.
  • If the host machine has an IPV6 subnet, IPV6 networking will be automatically attached, but no public IPV6 addresses will be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

Meaning of each parameter

shell
# ./buildct.sh CTID Password Number_of_CPU_Cores Memory Disk SSH_Port Port_80 Port_443 Start_Public_Port End_Public_Port System Storage_Disk Independent_IPV6_address(leave default N blank)

Test Example

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

After setting up, you can execute cat ct111 to view the information, or check the NOTES section on the web interface.

Here is the information for the created example CT:

Please note that "CT" and other technical terms might have specific meanings in different contexts. If "CT" stands for something specific in your domain, you might want to provide additional context for accurate translation.

AttributeValue
CTID111
SSH Usernameroot
SSH Passwordoneclick123
Number of CPU Cores1
Memory Size512MB
Disk Size5G
SSH Port20001
Port 8020002
Port 44320003
Port Range for NAT30000 to 30025
Operating Systemdebian11
Host Storage Disklocal
IPV6 addressN

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion specific CT

  • Stop CT
  • Delete CT
  • Delete Port Mapping
  • Restart Network
  • Delete Log Files

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

Meaning of each parameter

You can delete the CT with the corresponding CTID, as demonstrated here using the example 111 above

shell
./pve_delete.sh 111

The actual number of deletions is not fixed, a space separates each CTID, and more than one can be deleted at a time.

Batch Creation of LXC Containers with NAT

WARNING

Make sure the current Proxmox Virtual Environment (PVE) is clean and the host machine has not undergone any port mapping before the first use, as conflicting settings may result in bugs.

TIP

Before initiating the creation process, it's recommended to use the 'screen' command to execute the batch creation. This will prevent interruptions due to potential instability in SSH during the extended creation time.

  • It is possible to run the batch container creation process multiple times. However, please be mindful of allocating enough memory to the host machine to prevent system crashes. For adding swap space, refer to this link.
  • There is a 60-second interval between creating each container to avoid sudden performance bottlenecks.
  • Customization options include selecting the number of CPU cores, memory size, disk size, and the storage drive on the host machine. Ensure that you have calculated available resources appropriately before initiating the process.
  • The created containers have SSH enabled by default, allowing root login. Additionally, they are configured to support nested virtualization for Docker usage.
  • Relevant information about the containers will be stored in the corresponding container's notes, which can be viewed on the web interface.
  • If the host machine has an IPv6 subnet, it will be automatically assigned to the containers. However, public IPv6 addresses will not be provided.
  • Optionally enable or disable standalone IPV6, requires the host to have at least one /64 subnet.

Usage Instructions

Download Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

After the setup is complete, you can execute cat ctlog to view the information, or check in the NOTES section on the web interface.

Delete All CT

  • Delete all CTs
  • Delete port mappings for all NATs
  • Restart the network
  • Delete log files
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
+rm -rf ct*
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4

Creating Virtual Machines with Pure IPv6 Addresses

The premise is that the host provides an IPv6 subnet rather than a standalone IPv6 address, and the host does not have MAC address filtering enabled.

Automatic Selection of IPv6 Addresses, No Manual Configuration Needed

  • Pure IPV6 refers to a bound public IPV6 address, where the actual container still has the host's IPV4 network but no external IPV4 port
  • Automatically detect available IPv6 ranges and bind the corresponding V6 address based on the container number to the container.
  • Relevant system information will be stored in the NOTES of the corresponding container, accessible for viewing on the web interface.

Download script

Command:

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

Example Usage

shell
./buildct_onlyv6.sh CTID Password Number_of_CPU_Cores Memory_Size_in_MB Disk_Size_in_GB Operating_System Storage_Disk
shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

The above command signifies the creation of a container with a pure IPV6 address.

AttributeValue
Container TypeCT
CTID152
Usernameroot
Passwordoneclick123
CPU Cores1
Memory1024MB
Disk10G
Operating Systemdebian12
Storage DiskLocal Disk (System Disk)

TIP

Note that only CTIDs from 100 to 256 can be used here, no other numbers can be used.

Deletion Example

shell
rm -rf ct*
+pct stop 152 
+pct destroy 152
+systemctl restart ndpresponder.service
+ \ No newline at end of file diff --git a/en/guide/pve/pve_macos.html b/en/guide/pve/pve_macos.html index 1475b97b7f..6e89f7d1a2 100644 --- a/en/guide/pve/pve_macos.html +++ b/en/guide/pve/pve_macos.html @@ -5,31 +5,34 @@ Setting Up MacOS Virtual Machine | One Click Virtualization - + + + - - - - - - + + + + + + - + + -
Skip to content
On this page

Setting Up MacOS Virtual Machine

Prerequisites

System and hardware configuration requirements --> Environment detection

You can only set up a MacOS virtual machine when the environment detection confirms that the host machine supports KVM nested virtualization. Otherwise, it will be detected by hardware and cannot be set up.

Setting Up the Prerequisites

  • Automatically identify CPU type (AMD or Intel) and set nested virtualization parameters according to the type.
  • Modify GRUB boot parameters to enable IOMMU and disable default framebuffer.
  • Add VFIO module support for hardware device passthrough.
  • Blacklist sound card and graphics card driver modules to avoid conflicts with macOS.
  • Configure KVM-related kernel parameters, ignore MSR errors, and improve compatibility.
  • Patch Proxmox frontend status detection logic to bypass status restrictions.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

After successful execution, it will show that the system will restart in 15 seconds. This is the normal process, as kernel parameters cannot take effect without restarting.

System Image Download

  • All images have pre-installed components and are relatively large (minimum about 4.9GB). Download and extraction tasks will run in the background.
  • Images are complete systems with all components and can be booted and used without internet connection.
  • If the free space on the system disk is less than twice the size of the image, the download will be rejected.
  • Images are in 7z compressed format and need to be extracted before use.
  • You can check the status of current download and extraction tasks at any time. Virtual machines can only be created after completion.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh --lang=en

Or

shell
bash install_macos_images.sh --lang=en

After the background download task starts, you can close the SSH window and wait for 30 minutes to 3 hours (depending on your server bandwidth and connectivity) to download the ISO 7z compressed package.

When the download task is complete and the current download task query shows empty, you can choose to execute the extraction task. The waiting time for extraction depends on your server's CPU performance.

When the extraction task is complete and the current extraction task query shows empty, all preparations are ready.

Tasks of the same type can run concurrently, and any task can be canceled at any time by entering the PID value.

Build from https://github.com/oneclickvirt/macos currently supported image compressed packages:

# Listed by system release date from old to new
-high-sierra.iso.7z (Size: 5.23GB)
-mojave.iso.7z (Size: 6.03GB)
-catalina.iso.7z (Size: 8.33GB)
-big‑sur.iso.7z (Size: 12.21GB)
-monterey.iso.7z (Size: 12.36GB)
-ventura.iso.7z (Size: 12.31GB)
-sonoma.iso.7z (Size: 14.41GB)
-sequoia.iso.7z (Size: 15.02GB)

MACOS Virtual Machine Template Setup

  • Systems high-sierra, mojave, catalina require at least 2 cores, 4G of RAM and 40G of hard disk to run.
  • big-sur and newer MACOS systems require at least 6 cores, 6G RAM and 50G hard disk.
  • The newer the version of the system (the later the serial number of the download), the more hardware is required.
  • All images are boot disk images without any personal data, so disk allocation, login information setup, and network settings need to be manually configured according to the instructions.
  • You need to manually start the virtual machine from the web interface. Before starting, you can check if all templates meet your expectations.

Download Template Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

Parameter Meanings

shell
# ./buildvm_macos.sh VMID CPU_cores Memory Disk SSH_port VNC_port System Storage_disk Independent_IPV6(default_N_if_empty)

TIP

The disk size here is only the size of the virtual machine's disk. During the actual setup process, the program will also mount the boot disk and system image, so the actual disk requirement for setting up a virtual machine is virtual machine disk size + image size + boot disk size (500MB). Always be aware of whether your disk space is sufficient for setting up virtual machines.

Example Command

Using the oldest version (high-sierra) as an example, the supported configuration is as follows (very laggy)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

After the template is set up, you can run cat vm100 to view information, or check the NOTES in the corresponding VM in the WEB interface.

Here is the information for the example VM:

PropertyValue
VMID100
CPU cores2
Memory size4096MB
Disk size45G
SSH port44022
VNC port45901
Systemhigh-sierra
Host storage disklocal
Independent IPV6N

TIP

Note that VMID can only use numbers from 100 to 256, other numbers are not available

MACOS System Boot and Installation

After completing the previous steps, you can see a gray virtual machine waiting to be started in the panel.

mac0

After clicking start, enter the VNC panel. The selection box on the left has a full-screen button. It is recommended to operate in full screen to avoid resolution issues.

mac00

After about 3 minutes of boot disk loading, a startup disk will be displayed on the left center of the screen. Click directly or press Enter.

After another 3-5 minutes of startup disk loading, four selection boxes will appear. Select Disk Utility and click to enter.

mac1

After entering, you can see three disks and one image. Find the disk larger than 40G named QEMU HARDDISK Media, and click Erase.

mac2

A pop-up window will appear, requiring you to rename the name to macos for easy identification and use later, then click Erase to continue initialization.

mac3

After initialization is complete, click Done.

mac4

Now you need to exit the Disk Utility interface. Click Disk Utility in the upper right corner and select Quit Disk Utility to exit the current selection box.

mac5

Then you return to the previous four selection boxes. Select Install macOS XXXX (since I am using Big Sur as an example, XXXX is Big Sur), and click continue.

mac6

In the following steps, continue clicking continue, then click Agree, and then Agree again.

mac7

mac8

mac9

Until those three disks appear again, but here you can see the disk larger than 40G named macos. Select it and click continue.

mac10

After a period of file copying and disk loading (about 12 minutes), you will formally enter the system installation phase. Choose your region based on where the host machine is located.

mac11

After selecting the region, continue clicking continue.

mac12

mac13

Until the Migration Assistant data migration option appears, select Not Now in the lower left corner to not import user data.

mac14

Then you will be prompted to create a user. Fill in the username, account name, and login password. After setting up, click continue.

mac15

After that, you will continue clicking continue until the system installation is complete.

Network Configuration

Since the system installation was performed in an offline environment, you need to manually configure a static network connection to the host's bridge.

Click the WIFI button in the upper right corner, turn off WIFI, and then click Network Preferences ...

mac16

After entering the settings interface, click the Advanced button to enter the advanced settings interface.

mac17

Fill in the static network configuration in the TCP/IP tab.

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx (replace xxx with the IP you want to bind, my vmid is 100, so I wrote 100 for convenience)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

If you need to configure an IPV6 network, similar to the IPV4 settings above, you will need to fill in the public IPV6 address bound to the virtual machine (written in the Note box in the PVE panel), subnet mask 128, and the default gateway obtained by executing cat /usr/local/bin/pve_check_ipv6 on the host.

mac18

Fill in the static network DNS configuration in the DNS tab.

Generally, adding 8.8.8.8 and 1.1.1.1 is sufficient. For use in mainland China, use 114.114.114.114.

mac19

After filling in and applying, the top left of the settings will show that the network is connected.

mac20

Now, opening the default browser and visiting any website will allow you to access public network resources, proving that the network has worked.

Remove ISO

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Macos system is to uninstall opencore.iso and xxxx (the system image used for installation).iso, similar to the Windows system uninstallation of win image and virtio image in the example picture above.

- +
Skip to content

Setting Up MacOS Virtual Machine

Prerequisites

System and hardware configuration requirements --> Environment detection

You can only set up a MacOS virtual machine when the environment detection confirms that the host machine supports KVM nested virtualization. Otherwise, it will be detected by hardware and cannot be set up.

Setting Up the Prerequisites

  • Automatically identify CPU type (AMD or Intel) and set nested virtualization parameters according to the type.
  • Modify GRUB boot parameters to enable IOMMU and disable default framebuffer.
  • Add VFIO module support for hardware device passthrough.
  • Blacklist sound card and graphics card driver modules to avoid conflicts with macOS.
  • Configure KVM-related kernel parameters, ignore MSR errors, and improve compatibility.
  • Patch Proxmox frontend status detection logic to bypass status restrictions.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

After successful execution, it will show that the system will restart in 15 seconds. This is the normal process, as kernel parameters cannot take effect without restarting.

System Image Download

  • All images have pre-installed components and are relatively large (minimum about 4.9GB). Download and extraction tasks will run in the background.
  • Images are complete systems with all components and can be booted and used without internet connection.
  • If the free space on the system disk is less than twice the size of the image, the download will be rejected.
  • Images are in 7z compressed format and need to be extracted before use.
  • You can check the status of current download and extraction tasks at any time. Virtual machines can only be created after completion.
shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh --lang=en

Or

shell
bash install_macos_images.sh --lang=en

After the background download task starts, you can close the SSH window and wait for 30 minutes to 3 hours (depending on your server bandwidth and connectivity) to download the ISO 7z compressed package.

When the download task is complete and the current download task query shows empty, you can choose to execute the extraction task. The waiting time for extraction depends on your server's CPU performance.

When the extraction task is complete and the current extraction task query shows empty, all preparations are ready.

Tasks of the same type can run concurrently, and any task can be canceled at any time by entering the PID value.

Build from https://github.com/oneclickvirt/macos currently supported image compressed packages:

# Listed by system release date from old to new
+high-sierra.iso.7z (Size: 5.23GB)
+mojave.iso.7z (Size: 6.03GB)
+catalina.iso.7z (Size: 8.33GB)
+big‑sur.iso.7z (Size: 12.21GB)
+monterey.iso.7z (Size: 12.36GB)
+ventura.iso.7z (Size: 12.31GB)
+sonoma.iso.7z (Size: 14.41GB)
+sequoia.iso.7z (Size: 15.02GB)

MACOS Virtual Machine Template Setup

  • Systems high-sierra, mojave, catalina require at least 2 cores, 4G of RAM and 40G of hard disk to run.
  • big-sur and newer MACOS systems require at least 6 cores, 6G RAM and 50G hard disk.
  • The newer the version of the system (the later the serial number of the download), the more hardware is required.
  • All images are boot disk images without any personal data, so disk allocation, login information setup, and network settings need to be manually configured according to the instructions.
  • You need to manually start the virtual machine from the web interface. Before starting, you can check if all templates meet your expectations.

Download Template Script

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

Parameter Meanings

shell
# ./buildvm_macos.sh VMID CPU_cores Memory Disk SSH_port VNC_port System Storage_disk Independent_IPV6(default_N_if_empty)

TIP

The disk size here is only the size of the virtual machine's disk. During the actual setup process, the program will also mount the boot disk and system image, so the actual disk requirement for setting up a virtual machine is virtual machine disk size + image size + boot disk size (500MB). Always be aware of whether your disk space is sufficient for setting up virtual machines.

Example Command

Using the oldest version (high-sierra) as an example, the supported configuration is as follows (very laggy)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

After the template is set up, you can run cat vm100 to view information, or check the NOTES in the corresponding VM in the WEB interface.

Here is the information for the example VM:

PropertyValue
VMID100
CPU cores2
Memory size4096MB
Disk size45G
SSH port44022
VNC port45901
Systemhigh-sierra
Host storage disklocal
Independent IPV6N

TIP

Note that VMID can only use numbers from 100 to 256, other numbers are not available

MACOS System Boot and Installation

After completing the previous steps, you can see a gray virtual machine waiting to be started in the panel.

mac0

After clicking start, enter the VNC panel. The selection box on the left has a full-screen button. It is recommended to operate in full screen to avoid resolution issues.

mac00

After about 3 minutes of boot disk loading, a startup disk will be displayed on the left center of the screen. Click directly or press Enter.

After another 3-5 minutes of startup disk loading, four selection boxes will appear. Select Disk Utility and click to enter.

mac1

After entering, you can see three disks and one image. Find the disk larger than 40G named QEMU HARDDISK Media, and click Erase.

mac2

A pop-up window will appear, requiring you to rename the name to macos for easy identification and use later, then click Erase to continue initialization.

mac3

After initialization is complete, click Done.

mac4

Now you need to exit the Disk Utility interface. Click Disk Utility in the upper right corner and select Quit Disk Utility to exit the current selection box.

mac5

Then you return to the previous four selection boxes. Select Install macOS XXXX (since I am using Big Sur as an example, XXXX is Big Sur), and click continue.

mac6

In the following steps, continue clicking continue, then click Agree, and then Agree again.

mac7

mac8

mac9

Until those three disks appear again, but here you can see the disk larger than 40G named macos. Select it and click continue.

mac10

After a period of file copying and disk loading (about 12 minutes), you will formally enter the system installation phase. Choose your region based on where the host machine is located.

mac11

After selecting the region, continue clicking continue.

mac12

mac13

Until the Migration Assistant data migration option appears, select Not Now in the lower left corner to not import user data.

mac14

Then you will be prompted to create a user. Fill in the username, account name, and login password. After setting up, click continue.

mac15

After that, you will continue clicking continue until the system installation is complete.

Network Configuration

Since the system installation was performed in an offline environment, you need to manually configure a static network connection to the host's bridge.

Click the WIFI button in the upper right corner, turn off WIFI, and then click Network Preferences ...

mac16

After entering the settings interface, click the Advanced button to enter the advanced settings interface.

mac17

Fill in the static network configuration in the TCP/IP tab.

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx (replace xxx with the IP you want to bind, my vmid is 100, so I wrote 100 for convenience)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

If you need to configure an IPV6 network, similar to the IPV4 settings above, you will need to fill in the public IPV6 address bound to the virtual machine (written in the Note box in the PVE panel), subnet mask 128, and the default gateway obtained by executing cat /usr/local/bin/pve_check_ipv6 on the host.

mac18

Fill in the static network DNS configuration in the DNS tab.

Generally, adding 8.8.8.8 and 1.1.1.1 is sufficient. For use in mainland China, use 114.114.114.114.

mac19

After filling in and applying, the top left of the settings will show that the network is connected.

mac20

Now, opening the default browser and visiting any website will allow you to access public network resources, proving that the network has worked.

Remove ISO

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Macos system is to uninstall opencore.iso and xxxx (the system image used for installation).iso, similar to the Windows system uninstallation of win image and virtio image in the example picture above.

+ \ No newline at end of file diff --git a/en/guide/pve/pve_precheck.html b/en/guide/pve/pve_precheck.html index f5a2e2ef30..b727b4f747 100644 --- a/en/guide/pve/pve_precheck.html +++ b/en/guide/pve/pve_precheck.html @@ -5,24 +5,27 @@ Preface | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If there are unadapted merchants or machines welcome to contact @spiritlhl_bot, will try to support it sometime!

WARNING

Will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running it.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/pve

Various requirements

It is recommended that debian try to use the latest stable version of the system before use.

Do not use this set of scripts in the dynamic IP server (reboot the machine automatically switch the local IP server is not supported, reboot the machine after the IP does not automatically switch the support)

The one-click installation script of this project only adapts to Debian systems, non-Debian can not be installed through the APT source, the official only gives the image of Debian, other systems can only use the ISO installation, or use custom partitions and other ways to solve the problem in the FAQ partition.

  • System requirements: Debian 8+

TIP

It is recommended to install debian11 instead of debian12, because the latter is a beta version, and the debian11 installation is the stable version.

  • Hardware requirements: 2 cores 2G RAM x86_64 or arm architecture server hard disk at least 20G
  • Hardware requirements for KVM: VM-X or AMD-V support (some VPS and all Dedicated servers support).
  • If hardware or system requirements are not met, you can use incus to batch open LXC containers Jump

If you use IPV6 tunnels for IPV6 subnet attachment on the host, be sure to add the contents in the corresponding file when PVE is successfully installed but the gateway is not automatically set, and do not add IPV6 tunnels at the very beginning (without installing PVE).

Setting up virtual memory (SWAP) (optional, not required)

TIP

Memory to open some swap lest the machine blow up, if your host computer does not have enough memory and a lot of free hard disk.

Unit conversion: Enter 1024 to generate 1G SWAP-virtual memory, virtual memory takes up hard disk space, when the actual memory is not enough to use the virtual memory will automatically use the virtual memory for memory use, but then bring the IO high occupancy and CPU performance occupancy!

It is recommended to use only twice the size of the actual memory as virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Detecting the environment

  • This project related scripts must be executed before the execution of this script to detect the environment, if it does not meet the requirements of the installation of PVE will not be able to use the subsequent scripts
  • Detection of the local IPV6 network configuration (with or without IPV6 can be installed, just query)
  • Detection of the hardware configuration meets the minimum requirements
  • Detection of the hardware environment can be nested virtualization KVM type of servers, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • Detect whether the system environment can be nested virtualization KVM type of server, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • can not be nested virtualization KVM servers do not recommend the installation of the PVE, it is better to use incus for better performance.

Command:

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

If you need to update the IPV6 information before querying, then execute the following command before querying

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

Commands to set up the testing environment for executing this project are as follows:

图片

To perform the above-mentioned query, you only need to use the one-click script below to automatically create a virtual machine. There is no need to manually modify settings on the web interface.

图片

After creating the virtual machines using the subsequent script as mentioned above, it may be necessary to manually modify the settings on the web interface. You will need to disable hardware nested virtualization for each respective virtual machine, as shown in the following diagram.

图片

Stop the virtual machine before making modifications. After the modifications are done, you can start the machine to use NOVNC. Failure to close it may result in bugs that render this virtual machine unusable.

If you forcibly install PVE to enable KVM, even if the startup fails, you can also disable this option and try to start the virtual machine to see if it works.

The reason for these issues is what was stated above, the host does not support nested virtualized KVMs for acceleration.

TIP

Please use the "screen" command to suspend execution before launching the virtual machine, in order to avoid prolonged startup times. Unstable SSH connections could lead to interruptions during the intermediate execution.



- +
Skip to content

Preface

The following is the introduction of the non-customized part, the customized part has its own corresponding introduction, do not get confused!

If there are unadapted merchants or machines welcome to contact @spiritlhl_bot, will try to support it sometime!

WARNING

Will change the network structure of the host, please make sure that the host can reset the system at any time and that there is no important data on the host before running it.

Feel free to give the project a Star for free support!-->https://github.com/oneclickvirt/pve

Various requirements

It is recommended that debian try to use the latest stable version of the system before use.

Do not use this set of scripts in the dynamic IP server (reboot the machine automatically switch the local IP server is not supported, reboot the machine after the IP does not automatically switch the support)

The one-click installation script of this project only adapts to Debian systems, non-Debian can not be installed through the APT source, the official only gives the image of Debian, other systems can only use the ISO installation, or use custom partitions and other ways to solve the problem in the FAQ partition.

  • System requirements: Debian 8+

TIP

It is recommended to install debian11 instead of debian12, because the latter is a beta version, and the debian11 installation is the stable version.

  • Hardware requirements: 2 cores 2G RAM x86_64 or arm architecture server hard disk at least 20G
  • Hardware requirements for KVM: VM-X or AMD-V support (some VPS and all Dedicated servers support).
  • If hardware or system requirements are not met, you can use incus to batch open LXC containers Jump

If you use IPV6 tunnels for IPV6 subnet attachment on the host, be sure to add the contents in the corresponding file when PVE is successfully installed but the gateway is not automatically set, and do not add IPV6 tunnels at the very beginning (without installing PVE).

Setting up virtual memory (SWAP) (optional, not required)

TIP

Memory to open some swap lest the machine blow up, if your host computer does not have enough memory and a lot of free hard disk.

Unit conversion: Enter 1024 to generate 1G SWAP-virtual memory, virtual memory takes up hard disk space, when the actual memory is not enough to use the virtual memory will automatically use the virtual memory for memory use, but then bring the IO high occupancy and CPU performance occupancy!

It is recommended to use only twice the size of the actual memory as virtual memory.

Command:

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

Detecting the environment

  • This project related scripts must be executed before the execution of this script to detect the environment, if it does not meet the requirements of the installation of PVE will not be able to use the subsequent scripts
  • Detection of the local IPV6 network configuration (with or without IPV6 can be installed, just query)
  • Detection of the hardware configuration meets the minimum requirements
  • Detection of the hardware environment can be nested virtualization KVM type of servers, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • Detect whether the system environment can be nested virtualization KVM type of server, can not be nested virtualization KVM can also open QEMU TCG server, performance is poor
  • can not be nested virtualization KVM servers do not recommend the installation of the PVE, it is better to use incus for better performance.

Command:

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

If you need to update the IPV6 information before querying, then execute the following command before querying

bash
rm -rf /usr/local/bin/pve_ipv6*
+rm -rf /usr/local/bin/pve_check_ipv6*
+rm -rf /usr/local/bin/pve_last_ipv6*

Commands to set up the testing environment for executing this project are as follows:

图片

To perform the above-mentioned query, you only need to use the one-click script below to automatically create a virtual machine. There is no need to manually modify settings on the web interface.

图片

After creating the virtual machines using the subsequent script as mentioned above, it may be necessary to manually modify the settings on the web interface. You will need to disable hardware nested virtualization for each respective virtual machine, as shown in the following diagram.

图片

Stop the virtual machine before making modifications. After the modifications are done, you can start the machine to use NOVNC. Failure to close it may result in bugs that render this virtual machine unusable.

If you forcibly install PVE to enable KVM, even if the startup fails, you can also disable this option and try to start the virtual machine to see if it works.

The reason for these issues is what was stated above, the host does not support nested virtualized KVMs for acceleration.

TIP

Please use the "screen" command to suspend execution before launching the virtual machine, in order to avoid prolonged startup times. Unstable SSH connections could lead to interruptions during the intermediate execution.



+ \ No newline at end of file diff --git a/en/guide/pve/pve_qa.html b/en/guide/pve/pve_qa.html index b24b096b78..c38fab76ae 100644 --- a/en/guide/pve/pve_qa.html +++ b/en/guide/pve/pve_qa.html @@ -5,34 +5,37 @@ Solve the puzzle | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Solve the puzzle

Within 30 seconds of executing the script, the machine dropped.

Original system execution

systemctl restart networking

See if it is not directly offline, if so that is the machine native problem, hot plug or dhcp caused by the network can not restart, it is recommended to replace the host system or DD a new system to try!

Generally speaking, this situation occurs in the exclusive service Debian11 system, switch to Debian12 system will not be a problem!

Installation of PVE fails with an error saying that some packages do not exist.

Execute the following command to query the source of apt

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

If you see

deb file://
-deb cdrom:[

A line starting like this proves that the host is using local sources instead of network sources, and you need to replace the sources in /etc/apt/sources.list with a line such as

pct

Replace the network source with the same to install using the PVE one-click install script.

Replacing the network source can be done using the following command for apt source replacement

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

Successful PVE Installation but Lost Connection After Reboot

If the machine successfully installs PVE and the web interface is accessible, but loses connection after a reboot, please execute the following commands after a successful PVE installation and before rebooting:

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

Then report the rebooted disconnected machine to @spiritlhl_bot for the script to be updated and repaired automatically.

Successful PVE Installation but can not resolve host after reboot

Common in low version of Debian system (cloud server) after installing PVE reboot no matter what URL to visit the report error

curl: (6) Could not resolve host:

View the file at this time

cat /etc/resolv.conf

Statements beginning with nameserver may be found to be absent.

You need to set up DNS on this web page

screenshot-1708136079861

After setting up the DNS, check the file again and you will find the following content

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

At this point, requesting any URL again will resolve it successfully

PVE Installation Failed

If you encounter any issues with installing on certain machines, and if you're in a hurry, you can try using the scripts from the following repository to reinstall as Debian 11 first.

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

The system username after dd at this point is root, and the password is oneclickvirt139.

If it doesn't work, check the issues and descriptions in https://github.com/leitbogioro/Tools A common problem is that the machine is raid0 not raid10, and you need to add a parameter to specify the value of the raid.

If you have time or if it's still not working, please contact @spiritlhl_bot for assistance.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

What to do if you accidentally delete a NAT mapping rule

Use the following command to map back

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

Adding a New Node to an Existing PVE Cluster (Create / Join Cluster)

To form a cluster from two independent Proxmox VE instances, the following prerequisites must be met:

Cluster Prerequisites

  1. Unique Hostnames
    The hostname of each node must be unique to avoid conflicts. It is recommended to use names like pve1, pve2, etc.

  2. Unique VMIDs
    There must be no duplicate VMIDs across the two PVE nodes. If conflicts exist, adjust the VMIDs beforehand to prevent issues during cluster merge.

  3. Network Connectivity & Low Latency
    Both nodes must be able to ping each other. A low-latency network (LAN or high-speed public connection) is recommended for reliable cluster communication.

Creating the Cluster (Run on Any Node)

  1. Log in to the web interface of the node where the cluster will be created (e.g., pve1).
  2. Navigate to: Datacenter → Cluster → Create Cluster.
  3. Enter a name for the cluster (Cluster Name).
  4. Select the network interface to be used for cluster communication (e.g., public IP if only one interface is available).
  5. Click Create to initialize the cluster.
  6. Once the cluster is created, click Join Information and copy the displayed information for use on the joining node.

Note: The cluster has no "master" or "slave" nodes—any node can be the one that initiates the cluster.

Joining the Cluster (Run on the Second Node)

  1. Log in to the web interface of the node to be added (e.g., pve2).
  2. Navigate to: Datacenter → Cluster → Join Cluster.
  3. Paste the Join Information from pve1 into the input field.
  4. Enter the password of root user on pve1 in the Peer Password field.
  5. Click Join to begin the joining process.
  6. Wait until the process completes successfully, then refresh the page or re-login. You should now see both nodes in the same cluster.

Cluster Benefits

  • Nodes can share resources and migrate virtual machines.
  • ISO images and templates can be transferred more conveniently between nodes.

Verified VPS Providers

VPS Providers Offering KVM Virtualization with NAT

spartanhost Debian12 on a Dedicated Server (Debian11 has problems)

interserver VPS or dedicated servers

frantech Las Vegas Tier 2

eugamehost US Phoenix Black Friday Special

amhost Testing version

digitalocean Perminu Intel and Regular 4-core versions

skrime Lowest configuration of AMD Ryzen KVM Server

webdock AMD KVM Server

4vps Russian and Greek testing versions

adtaq Storage KVM server with lowest configuration

nocix Dedicated servers

online.net Debian12 on a Dedicated Server (Debian11 has problems)

OVH Public Cloud needs to be installed after dd as a pure system using the following command

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd ' oneclickvirt139' --network "static"

At this point, the system username after dd is root, and the password is oneclickvirt139.

If it doesn't work, please check the issues and instructions in https://github.com/leitbogioro/Tools. A common problem is that OVH standalone servers are dd'd, which requires the source system to be remounted as raid1 on debian12 by default, and then parameterized to specify dd'd as raid0 in order to be successful, using the following command

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

VPS Providers Offering NAT with LXC Virtualization

Tencent Cloud Worry-Free and Student editions

spectraip KVM servers

Linode Lowest configuration with dedicated CPU

hosthatch Special high-configuration servers

hetzner Cloud servers

rackdog Servers with floating IP

vultr Standard Cloud servers

azure Standard machines

scaleway ARM architecture servers

aws EC2 servers

Google cloud platform - GCP AMD servers

- +
Skip to content

Solve the puzzle

Within 30 seconds of executing the script, the machine dropped.

Original system execution

systemctl restart networking

See if it is not directly offline, if so that is the machine native problem, hot plug or dhcp caused by the network can not restart, it is recommended to replace the host system or DD a new system to try!

Generally speaking, this situation occurs in the exclusive service Debian11 system, switch to Debian12 system will not be a problem!

Installation of PVE fails with an error saying that some packages do not exist.

Execute the following command to query the source of apt

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

If you see

deb file://
+deb cdrom:[

A line starting like this proves that the host is using local sources instead of network sources, and you need to replace the sources in /etc/apt/sources.list with a line such as

pct

Replace the network source with the same to install using the PVE one-click install script.

Replacing the network source can be done using the following command for apt source replacement

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

Successful PVE Installation but Lost Connection After Reboot

If the machine successfully installs PVE and the web interface is accessible, but loses connection after a reboot, please execute the following commands after a successful PVE installation and before rebooting:

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
+if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
+    chattr -i /etc/network/interfaces
+    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
+    chattr +i /etc/network/interfaces
+fi

Then report the rebooted disconnected machine to @spiritlhl_bot for the script to be updated and repaired automatically.

Successful PVE Installation but can not resolve host after reboot

Common in low version of Debian system (cloud server) after installing PVE reboot no matter what URL to visit the report error

curl: (6) Could not resolve host:

View the file at this time

cat /etc/resolv.conf

Statements beginning with nameserver may be found to be absent.

You need to set up DNS on this web page

screenshot-1708136079861

After setting up the DNS, check the file again and you will find the following content

search .
+nameserver 8.8.8.8
+nameserver 8.8.4.4

At this point, requesting any URL again will resolve it successfully

PVE Installation Failed

If you encounter any issues with installing on certain machines, and if you're in a hurry, you can try using the scripts from the following repository to reinstall as Debian 11 first.

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

The system username after dd at this point is root, and the password is oneclickvirt139.

If it doesn't work, check the issues and descriptions in https://github.com/leitbogioro/Tools A common problem is that the machine is raid0 not raid10, and you need to add a parameter to specify the value of the raid.

If you have time or if it's still not working, please contact @spiritlhl_bot for assistance.

What to do if you open centos7 and find that CGroupV1 is not supported?

Enable CGroup V1: To enable CGroup V1 on an Ubuntu system, you need to edit the kernel boot parameters.

Please note that before changing kernel boot parameters, make sure to backup important data and settings to prevent unexpected problems.

Edit the ```/etc/default/grubfile and addsystemd.unified_cgroup_hierarchy=0to the end of the parameters inGRUB_CMDLINE_LINUX_DEFAULT``, just like:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

Save the file and run the following command to update the GRUB boot.

bash
sudo update-grub

Reboot the system for the changes to take effect

If the above changes still do not support the opening of centos7, try using a different host system.

What to do if you accidentally delete a NAT mapping rule

Use the following command to map back

shell
iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+cat /etc/iptables/rules.v4 | iptables-restore

Adding a New Node to an Existing PVE Cluster (Create / Join Cluster)

To form a cluster from two independent Proxmox VE instances, the following prerequisites must be met:

Cluster Prerequisites

  1. Unique Hostnames
    The hostname of each node must be unique to avoid conflicts. It is recommended to use names like pve1, pve2, etc.

  2. Unique VMIDs
    There must be no duplicate VMIDs across the two PVE nodes. If conflicts exist, adjust the VMIDs beforehand to prevent issues during cluster merge.

  3. Network Connectivity & Low Latency
    Both nodes must be able to ping each other. A low-latency network (LAN or high-speed public connection) is recommended for reliable cluster communication.

Creating the Cluster (Run on Any Node)

  1. Log in to the web interface of the node where the cluster will be created (e.g., pve1).
  2. Navigate to: Datacenter → Cluster → Create Cluster.
  3. Enter a name for the cluster (Cluster Name).
  4. Select the network interface to be used for cluster communication (e.g., public IP if only one interface is available).
  5. Click Create to initialize the cluster.
  6. Once the cluster is created, click Join Information and copy the displayed information for use on the joining node.

Note: The cluster has no "master" or "slave" nodes—any node can be the one that initiates the cluster.

Joining the Cluster (Run on the Second Node)

  1. Log in to the web interface of the node to be added (e.g., pve2).
  2. Navigate to: Datacenter → Cluster → Join Cluster.
  3. Paste the Join Information from pve1 into the input field.
  4. Enter the password of root user on pve1 in the Peer Password field.
  5. Click Join to begin the joining process.
  6. Wait until the process completes successfully, then refresh the page or re-login. You should now see both nodes in the same cluster.

Cluster Benefits

  • Nodes can share resources and migrate virtual machines.
  • ISO images and templates can be transferred more conveniently between nodes.

Verified VPS Providers

VPS Providers Offering KVM Virtualization with NAT

spartanhost Debian12 on a Dedicated Server (Debian11 has problems)

interserver VPS or dedicated servers

frantech Las Vegas Tier 2

eugamehost US Phoenix Black Friday Special

amhost Testing version

digitalocean Perminu Intel and Regular 4-core versions

skrime Lowest configuration of AMD Ryzen KVM Server

webdock AMD KVM Server

4vps Russian and Greek testing versions

adtaq Storage KVM server with lowest configuration

nocix Dedicated servers

online.net Debian12 on a Dedicated Server (Debian11 has problems)

OVH Public Cloud needs to be installed after dd as a pure system using the following command

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd ' oneclickvirt139' --network "static"

At this point, the system username after dd is root, and the password is oneclickvirt139.

If it doesn't work, please check the issues and instructions in https://github.com/leitbogioro/Tools. A common problem is that OVH standalone servers are dd'd, which requires the source system to be remounted as raid1 on debian12 by default, and then parameterized to specify dd'd as raid0 in order to be successful, using the following command

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

VPS Providers Offering NAT with LXC Virtualization

Tencent Cloud Worry-Free and Student editions

spectraip KVM servers

Linode Lowest configuration with dedicated CPU

hosthatch Special high-configuration servers

hetzner Cloud servers

rackdog Servers with floating IP

vultr Standard Cloud servers

azure Standard machines

scaleway ARM architecture servers

aws EC2 servers

Google cloud platform - GCP AMD servers

+ \ No newline at end of file diff --git a/en/guide/pve/pve_thanks.html b/en/guide/pve/pve_thanks.html index 8b159330fe..3e9a716882 100644 --- a/en/guide/pve/pve_thanks.html +++ b/en/guide/pve/pve_thanks.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/en/guide/pve/pve_windows.html b/en/guide/pve/pve_windows.html index 66d8d96acf..cae4c12849 100644 --- a/en/guide/pve/pve_windows.html +++ b/en/guide/pve/pve_windows.html @@ -5,24 +5,27 @@ Setting Up Windows Visual Machine | One Click Virtualization - + + + - - - - - - + + + + + + - + + -
Skip to content
On this page

Setting Up Windows Visual Machine

Using ISO Image with VirtIO for VM Setup

1. Download the Image

Before installation, you need to download the image file via local(pve) --> ISO images --> Download from URL

For the download link (URL:), you can use files from: https://github.com/ILLKX/Windows-VirtIO

Enter win.iso as the File Name:

download

Click Download. After downloading is complete, you can see the file size of win.iso on the current page, confirming it's in ISO format.

downloaded

2. Setting Up the Template

Click Create VM in the top right corner of the page.

In the General window, select mypool for Resource Pool:, enter win for Name, then click Next.

general

In the OS window, select win.iso for ISO image. For Guest OS, select Microsoft Windows as the Type and choose the appropriate Version for your ISO. For example, if you downloaded Windows 2022, select 11/2022, then click Next.

OS

In the System window, select VirtIO-GPU for Graphic card, q35 for Machine, VirtIO SCSI for SCSI Controller, and Default (SeaBIOS) for BIOS, then click Next.

system

In the Disk window, select Write Back for Cache, enter your desired disk size in Disk size (GiB) (generally not less than 20), and choose the storage location in Storage. In this example, only the system disk local is available, so local is selected. Then click Next.

disk

In the CPU window, enter the number of cores needed in Cores, then click Next.

cpu

In the Memory window, enter the desired memory size in Memory (MiB), then click Next.

memory

In the Network window, select vmbr1 for Bridge, VirtIO (paravirtualized) for Model, uncheck Firewall, then click Next.

Network

In the Confirm window, click Finish.

finish

3. Graphical Installation Configuration

Click on the template you've set up on the left, click Start in the upper right corner to start the virtual machine, then click Console to enter the VNC interface and wait for the operating system to boot.

console

In the VNC, click Next, then Install now, then I don't have a product key, check Accept license, click Next, and then select Custom installation.

win0win1win2win3win4

If the image comes with VirtIO drivers, you should be able to see the available system storage disk and its size. Select it and click Next.

win5win6

Wait for the system to install. It may restart automatically several times and could take more than 10 minutes.

win7

After installation is complete, you'll be asked to set a password during first login.

win8

Once setup is complete, there's a pop-up box on the left side of the NOVNC page. Click the first button, then follow the login prompt by pressing Ctrl+Alt+last button to enter the login page.

4. Network Initialization

Since the PVE is set up with a static network through this project, you need to manually modify the bound IP address after logging in, rather than using DHCP.

Right-click in the bottom right corner of the desktop and select Open Network and Internet settings. In the settings page that appears, click Change adapter options. win9

In the Network Connections, select Ethernet and click Change settings of this connection. win10

In the popup window, select Internet Protocol Version 4 (TCP/IPv4) and click Properties. win11

In the new dialog box, select Use the following IP address and enter: IP address(I): 172.16.1.xxx (replace xxx with your desired IP, I used 100 for convenience as my vmid is 100) Subnet mask(U): 255.255.255.0 Default gateway(D): 172.16.1.1

Then select Use the following DNS server addresses and enter:

8.8.8.8
-144.144.144.144

Click OK in the bottom right corner, and make sure Validate settings upon exit is NOT checked.

win12

Click OK and Yes for any other dialog boxes, and your virtual machine will now have network connectivity.

5. Unmounting the CD Drive

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Using ISO Images without VirtIO for VM Installation

1. Download Images

For Windows images without VirtIO, you can use:

https://down.idc.wiki/ISOS/Windows/

For VirtIO ISO images, you can use:

https://down.idc.wiki/ISOS/Toolkit/

or

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

Alternatively, you can download just the MSI package, package it into an ISO format locally, and then upload it to ProxmoxVE.

This way, the package is smaller. The official package contains support for all Windows images and is about 500MB, while a self-packaged one is around 5MB.

2. VirtIO Import

Note that in ProxmoxVE version 8.x and later, you can select VirtIO boot loading by default in the OS section, as shown in the image:

virtio

In lower versions of ProxmoxVE, such as 7.x and 6.x, you cannot select VirtIO boot loading by default in the OS section:

lower

You need to manually add CD/DVD Drive by clicking Add in the Hardware section and selecting the downloaded VirtIO ISO file:

lower

Then proceed as usual until you reach:

nodisk

At this point, you can't find the hard disk. You need to select Load Driver:

nodisk

Then select the VirtIO as your driver disk, click open, and import the corresponding system driver from the amd64 directory:

nodisk

I'm using a Windows Server 2019 image, so I imported the 2k19 driver. After importing, select the imported driver and click Next:

nodisk

nodisk

Now you should be able to see the hard disk. Select it and continue with the installation steps as in the previous tutorial until the system installation is complete and you reach the desktop.

3. Installing Drivers via virtio-win-guest-tools

Once successfully installed and at the desktop, you still need to manually install the drivers.

Open the VirtIO driver's CD drive directory. At the bottom, there's a virtio-win-guest-tools program that will install the required VirtIO drivers, including the VirtIO network card driver:

wk

wk

wk

After clicking install, the network card driver will be installed. For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

4. Installing Network Card Driver (Alternative)

After successful installation and reaching the desktop, you may still need to manually install the network card driver to connect to the network:

  1. Open Control PanelDevice Manager
  2. Find the Ethernet Controller, right-click and select Update Driver
  3. Select Browse my computer for driver software (R)
  4. Browse to the VirtIO driver's CD drive directory
  5. Open the NetKVM folder
  6. Select the driver folder corresponding to your current system version (like the above operation, I would choose the 2k19 folder with amd64 drivers)
  7. Confirm the installation, and after completion, the VirtIO network card driver will be successfully loaded

wk

wk

wk

For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

5. Unmounting the CD Drive

In the ProxmoxVE web interface, manually click on the corresponding CD in the Hardware section, select Remove, and then restart the virtual machine. This way, you can use it directly:

wk

- +
Skip to content

Setting Up Windows Visual Machine

Using ISO Image with VirtIO for VM Setup

1. Download the Image

Before installation, you need to download the image file via local(pve) --> ISO images --> Download from URL

For the download link (URL:), you can use files from: https://github.com/ILLKX/Windows-VirtIO

Enter win.iso as the File Name:

download

Click Download. After downloading is complete, you can see the file size of win.iso on the current page, confirming it's in ISO format.

downloaded

2. Setting Up the Template

Click Create VM in the top right corner of the page.

In the General window, select mypool for Resource Pool:, enter win for Name, then click Next.

general

In the OS window, select win.iso for ISO image. For Guest OS, select Microsoft Windows as the Type and choose the appropriate Version for your ISO. For example, if you downloaded Windows 2022, select 11/2022, then click Next.

OS

In the System window, select VirtIO-GPU for Graphic card, q35 for Machine, VirtIO SCSI for SCSI Controller, and Default (SeaBIOS) for BIOS, then click Next.

system

In the Disk window, select Write Back for Cache, enter your desired disk size in Disk size (GiB) (generally not less than 20), and choose the storage location in Storage. In this example, only the system disk local is available, so local is selected. Then click Next.

disk

In the CPU window, enter the number of cores needed in Cores, then click Next.

cpu

In the Memory window, enter the desired memory size in Memory (MiB), then click Next.

memory

In the Network window, select vmbr1 for Bridge, VirtIO (paravirtualized) for Model, uncheck Firewall, then click Next.

Network

In the Confirm window, click Finish.

finish

3. Graphical Installation Configuration

Click on the template you've set up on the left, click Start in the upper right corner to start the virtual machine, then click Console to enter the VNC interface and wait for the operating system to boot.

console

In the VNC, click Next, then Install now, then I don't have a product key, check Accept license, click Next, and then select Custom installation.

win0win1win2win3win4

If the image comes with VirtIO drivers, you should be able to see the available system storage disk and its size. Select it and click Next.

win5win6

Wait for the system to install. It may restart automatically several times and could take more than 10 minutes.

win7

After installation is complete, you'll be asked to set a password during first login.

win8

Once setup is complete, there's a pop-up box on the left side of the NOVNC page. Click the first button, then follow the login prompt by pressing Ctrl+Alt+last button to enter the login page.

4. Network Initialization

Since the PVE is set up with a static network through this project, you need to manually modify the bound IP address after logging in, rather than using DHCP.

Right-click in the bottom right corner of the desktop and select Open Network and Internet settings. In the settings page that appears, click Change adapter options. win9

In the Network Connections, select Ethernet and click Change settings of this connection. win10

In the popup window, select Internet Protocol Version 4 (TCP/IPv4) and click Properties. win11

In the new dialog box, select Use the following IP address and enter: IP address(I): 172.16.1.xxx (replace xxx with your desired IP, I used 100 for convenience as my vmid is 100) Subnet mask(U): 255.255.255.0 Default gateway(D): 172.16.1.1

Then select Use the following DNS server addresses and enter:

8.8.8.8
+144.144.144.144

Click OK in the bottom right corner, and make sure Validate settings upon exit is NOT checked.

win12

Click OK and Yes for any other dialog boxes, and your virtual machine will now have network connectivity.

5. Unmounting the CD Drive

Manually click on the corresponding CD in the Hardware on the web side of ProxmoxVE and select Remove, then restart the VM and you can use it directly.

wk

Using ISO Images without VirtIO for VM Installation

1. Download Images

For Windows images without VirtIO, you can use:

https://down.idc.wiki/ISOS/Windows/

For VirtIO ISO images, you can use:

https://down.idc.wiki/ISOS/Toolkit/

or

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

Alternatively, you can download just the MSI package, package it into an ISO format locally, and then upload it to ProxmoxVE.

This way, the package is smaller. The official package contains support for all Windows images and is about 500MB, while a self-packaged one is around 5MB.

2. VirtIO Import

Note that in ProxmoxVE version 8.x and later, you can select VirtIO boot loading by default in the OS section, as shown in the image:

virtio

In lower versions of ProxmoxVE, such as 7.x and 6.x, you cannot select VirtIO boot loading by default in the OS section:

lower

You need to manually add CD/DVD Drive by clicking Add in the Hardware section and selecting the downloaded VirtIO ISO file:

lower

Then proceed as usual until you reach:

nodisk

At this point, you can't find the hard disk. You need to select Load Driver:

nodisk

Then select the VirtIO as your driver disk, click open, and import the corresponding system driver from the amd64 directory:

nodisk

I'm using a Windows Server 2019 image, so I imported the 2k19 driver. After importing, select the imported driver and click Next:

nodisk

nodisk

Now you should be able to see the hard disk. Select it and continue with the installation steps as in the previous tutorial until the system installation is complete and you reach the desktop.

3. Installing Drivers via virtio-win-guest-tools

Once successfully installed and at the desktop, you still need to manually install the drivers.

Open the VirtIO driver's CD drive directory. At the bottom, there's a virtio-win-guest-tools program that will install the required VirtIO drivers, including the VirtIO network card driver:

wk

wk

wk

After clicking install, the network card driver will be installed. For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

4. Installing Network Card Driver (Alternative)

After successful installation and reaching the desktop, you may still need to manually install the network card driver to connect to the network:

  1. Open Control PanelDevice Manager
  2. Find the Ethernet Controller, right-click and select Update Driver
  3. Select Browse my computer for driver software (R)
  4. Browse to the VirtIO driver's CD drive directory
  5. Open the NetKVM folder
  6. Select the driver folder corresponding to your current system version (like the above operation, I would choose the 2k19 folder with amd64 drivers)
  7. Confirm the installation, and after completion, the VirtIO network card driver will be successfully loaded

wk

wk

wk

For subsequent network settings, refer to the network initialization tutorial mentioned earlier.

5. Unmounting the CD Drive

In the ProxmoxVE web interface, manually click on the corresponding CD in the Hardware section, select Remove, and then restart the virtual machine. This way, you can use it directly:

wk

+ \ No newline at end of file diff --git a/en/incomplete/bashvm.html b/en/incomplete/bashvm.html index 2dc34d124e..d791e77d01 100644 --- a/en/incomplete/bashvm.html +++ b/en/incomplete/bashvm.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/babywhale321/bashvm

https://bashvm.com/

Description

If you want to go deeper into how to open a VM and how to forward ports, then this program will start completely from the bottom and teach you step by step how to open a VM!

Disadvantages

Very tedious and time consuming, not as fast as other programs to set up a network and open a VM

- +
Skip to content

Repo

https://github.com/babywhale321/bashvm

https://bashvm.com/

Description

If you want to go deeper into how to open a VM and how to forward ports, then this program will start completely from the bottom and teach you step by step how to open a VM!

Disadvantages

Very tedious and time consuming, not as fast as other programs to set up a network and open a VM

+ \ No newline at end of file diff --git a/en/incomplete/cockpit.html b/en/incomplete/cockpit.html index 781d0765d2..db9adf1e6f 100644 --- a/en/incomplete/cockpit.html +++ b/en/incomplete/cockpit.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

hits

https://github.com/oneclickvirt/cockpit

Installation

Supported Systems: Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

Install only with Podman containers

shell
bash install.sh --ct

Install only with virtual machines

shell
bash install.sh --vm

Panel Mount Only

shell
bash install.sh

Both container and VM dependencies are installed

shell
bash install.sh --all

Disadvantages

The network is self-configuring, the mirrors are self-importing, the ports are self-mapped, and there is just one more GUI interface than the command line.

Thanks

https://cockpit-project.org/running.html

- +
Skip to content

Repo

hits

https://github.com/oneclickvirt/cockpit

Installation

Supported Systems: Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

Install only with Podman containers

shell
bash install.sh --ct

Install only with virtual machines

shell
bash install.sh --vm

Panel Mount Only

shell
bash install.sh

Both container and VM dependencies are installed

shell
bash install.sh --all

Disadvantages

The network is self-configuring, the mirrors are self-importing, the ports are self-mapped, and there is just one more GUI interface than the command line.

Thanks

https://cockpit-project.org/running.html

+ \ No newline at end of file diff --git a/en/incomplete/convoy.html b/en/incomplete/convoy.html index ea5060c349..b9ac5c4279 100644 --- a/en/incomplete/convoy.html +++ b/en/incomplete/convoy.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

One-click installation of convoy panel

Prerequisites for installation:

  • PVE is installed, but not the same node(not the same machine)
  • System is debian 11
  • CPU at least 2 cores, hard disk at least 20G, memory at least 4G (memory covers swap)

I don't guarantee that this script is error-free, it's just for my own amusement.

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

- +
Skip to content

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

One-click installation of convoy panel

Prerequisites for installation:

  • PVE is installed, but not the same node(not the same machine)
  • System is debian 11
  • CPU at least 2 cores, hard disk at least 20G, memory at least 4G (memory covers swap)

I don't guarantee that this script is error-free, it's just for my own amusement.

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

+ \ No newline at end of file diff --git a/en/incomplete/index.html b/en/incomplete/index.html index 8b2d664f49..8ffc8b6960 100644 --- a/en/incomplete/index.html +++ b/en/incomplete/index.html @@ -5,22 +5,25 @@ Other Virtualization Projects | Other Incomplete Virtualization Projects - + + + - - - - - + + + + + - + + -
Skip to content

Other Virtualization Projects

Some incomplete virtualization projects

- +
Skip to content

Other Virtualization ProjectsSome incomplete virtualization projects

+ \ No newline at end of file diff --git a/en/incomplete/pterodactyl.html b/en/incomplete/pterodactyl.html index 5c19daf3c3..721259686e 100644 --- a/en/incomplete/pterodactyl.html +++ b/en/incomplete/pterodactyl.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

After further research, it was found that creating servers and binding users is too cumbersome compared to using native Docker directly, so further development is currently suspended.

Description

Currently supported systems:

OS TypeVersion RangeNotes
Ubuntu20.04 (recommended), 22.04, 24.04Supported
Debian11 (Bullseye), 12 (Bookworm)Supported

Panel

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

On the wings side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

This will generate a command to be executed on the wings side.

After executing the generated command, wait for more than 20 seconds to avoid issues caused by unfinished initialization processes. Then on the wings side, run:

shell
bash install_wings.sh

Then go to http://<your_ip>/admin/nodes and you should see your node has been automatically added and managed, with a green heartbeat.

Thanks

https://pterodactyl.io/

- +
Skip to content

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

After further research, it was found that creating servers and binding users is too cumbersome compared to using native Docker directly, so further development is currently suspended.

Description

Currently supported systems:

OS TypeVersion RangeNotes
Ubuntu20.04 (recommended), 22.04, 24.04Supported
Debian11 (Bullseye), 12 (Bookworm)Supported

Panel

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

On the wings side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

On the panel side, run:

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

This will generate a command to be executed on the wings side.

After executing the generated command, wait for more than 20 seconds to avoid issues caused by unfinished initialization processes. Then on the wings side, run:

shell
bash install_wings.sh

Then go to http://<your_ip>/admin/nodes and you should see your node has been automatically added and managed, with a green heartbeat.

Thanks

https://pterodactyl.io/

+ \ No newline at end of file diff --git a/en/incomplete/virtfusion.html b/en/incomplete/virtfusion.html index 3cf267f59d..2c039d7a3c 100644 --- a/en/incomplete/virtfusion.html +++ b/en/incomplete/virtfusion.html @@ -3,30 +3,33 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Official Documents

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

One-click Installation

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

Disadvantages

Only one 30-day trial certificate per server per mailbox, no permanent free certificates

- +
Skip to content

Official Documents

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

One-click Installation

debian11

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

Disadvantages

Only one 30-day trial certificate per server per mailbox, no permanent free certificates

+ \ No newline at end of file diff --git a/en/incomplete/virtualizor-docker.html b/en/incomplete/virtualizor-docker.html index 822dd8bd1f..aa7d81dfa4 100644 --- a/en/incomplete/virtualizor-docker.html +++ b/en/incomplete/virtualizor-docker.html @@ -3,24 +3,27 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/ivstiv/virtualizor-docker

Description

The virtualizor opened in the docker

The certificate used is a trial certificate, valid for one day, and only the OpenVZ virtualization method is installed by default

Disadvantages

There is no community, so you have to figure it out on your own.

Ports for admin panel Don't look at the script's prompt messages, go with the repository instructions.

- +
Skip to content

Repo

https://github.com/ivstiv/virtualizor-docker

Description

The virtualizor opened in the docker

The certificate used is a trial certificate, valid for one day, and only the OpenVZ virtualization method is installed by default

Disadvantages

There is no community, so you have to figure it out on your own.

Ports for admin panel Don't look at the script's prompt messages, go with the repository instructions.

+ \ No newline at end of file diff --git a/en/incomplete/webvirtcloud.html b/en/incomplete/webvirtcloud.html index 4a720b648e..438f04b36b 100644 --- a/en/incomplete/webvirtcloud.html +++ b/en/incomplete/webvirtcloud.html @@ -5,66 +5,69 @@ WebVirtCloud Installation Guide | One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Original project repository: https://github.com/webvirtcloud/webvirtcloud

1. Controller Installation

System Requirements

Minimum Requirements:

  • CPU: 1 core
  • Memory: 1 GB RAM
  • Storage: 10 GB free space
  • System: Debian11+, Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

Default Login Information

  • Username: admin@webvirt.cloud
  • Password: admin

Panel Access

  • User Panel: https://192-168-0-114.nip.io
  • Admin Backend: https://192-168-0-114.nip.io/admin

Note: Replace 192.168.0.114 with your public IP to get the actual accessible address.

Installation Command

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
-&& chmod +x install_webvirt_cloud.sh \
-&& bash install_webvirt_cloud.sh

TIP

The execution process may be stuck in the clone repository has not been moving, at this time, press ctrl + c to exit the implementation, re-execution of the installation script on the line, the Department of Docker installation is stuck in the stage of the build project.

2. Compute Node Installation

Important: Hypervisor and Controller cannot be installed on the same virtual machine, otherwise network conflicts will occur.

System Requirements

Recommended Configuration:

  • CPU: 2 cores
  • Memory: 4 GB RAM
  • Storage: 40 GB free space
  • System: AlmaLinux8+, RockyLinux8+

Additional Notes:

  • Higher configurations are recommended for actual use; the test environment is only sufficient for running 4 minimal virtual machines.
  • Servers with KVM nested virtualization support are recommended. If VM-x/AMD-V/Hyper-V is not enabled, it will automatically switch to QEMU using TCG emulation to set up virtual machines, though performance will be reduced.
  • The installation skips environment checks and uses binary files directly, so no dependencies need to be installed.

Environment Check

Check if the server supports KVM nested virtualization:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

Select hardware individual test

Compute Node Installation Steps

  1. Download the installation script:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    -&& chmod +x install_hypervisor.sh
  2. Execute installation (replace with your Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    Replace x.x.x.x with the actual IP address of your Controller.

  3. Node Management in Panel
    After execution, there will be prompts for information needed in the Controller panel.
    In the panel, the Hostname to be entered is the current compute node's IPv4 address, and you need to enter the Token to identify the node.

NetworkManager Version Issue

During installation, you may encounter the following error:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

Solution: Restart the server and re-execute the installation command.

Installation Time Note

  • The entire process takes approximately 10-25 minutes.
  • Most of the time is spent downloading finnix-125.iso to /var/lib/libvirt/isos/finnix-125.iso.
  • This part cannot be accelerated, so it's recommended to use tmux or screen to prevent interruption.

Adding Compute Node to Control Panel

After installation, a Token will be generated for adding the compute node in the control panel (Admin panel):

Path: Admin Panel > Computers > Add Computer

  • HostName should be filled with the compute node's public IPv4 address
  • Token should be filled with the token key obtained on the compute node

3. Public IPv4 Port Mapping

3.1 Automatic Mapping

Automatic mapping features:

  • Automatic Monitoring: Real-time monitoring of virtual machine status changes, automatically applying or cleaning up port mapping rules
  • Intelligent Port Allocation: Automatically calculating and allocating non-conflicting ports based on VM IP addresses
  • Rule Persistence: Using firewall-cmd to ensure port mapping rules remain effective after host restart
  • Mapping Records: Automatically maintaining mapping information records for easy viewing and management
  • Conflict Prevention: Intelligently detecting and avoiding port conflicts, ensuring each VM has unique port mappings

Installation Method

  1. Download the script to a temporary directory:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. Add execution permission:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. Run the installer:

    bash
    /tmp/vm_port_mapping_setup.sh

The script will automatically complete the following operations:

  • Copy itself to the system directory /usr/local/sbin/vm_port_mapping_daemon.sh
  • Create a systemd service unit file
  • Enable and start the service

Port Mapping Rules

The daemon will assign the following ports for each virtual machine:

  1. SSH Port:

    • Calculation formula: (Last segment of IP) × 100 + 22 + 10000
    • Example: For IP address 192.168.33.114, the mapped SSH port is 114×100+22+10000 = 21422
  2. Extra Ports:

    • 10 additional ports are allocated for each VM
    • Starting port: 20000 + (Last segment of IP) × 100
    • Ending port: Starting port + 9
    • Example: For IP address 192.168.33.114, extra port range is 20000+(114×100) to 20000+(114×100)+9

If the calculated port is already occupied, the program will automatically find the next available port to ensure no conflicts occur.

Mapping File

All port mapping information is saved in the /etc/vm_port_mapping/mapping.txt file, in the format:

VM name IP address MAC address SSH mapped port Extra ports start Extra ports end

For example:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

Service Management

  • Check service status:

    bash
    systemctl status vm-port-mapping
  • Start service:

    bash
    systemctl start vm-port-mapping
  • Stop service:

    bash
    systemctl stop vm-port-mapping
  • Disable auto-start:

    bash
    systemctl disable vm-port-mapping
  • View logs:

    bash
    journalctl -u vm-port-mapping
    -# or
    -cat /var/log/vm_port_mapping.log
  • Manually trigger rule update:

    bash
    systemctl restart vm-port-mapping

Common Issues

Port mapping not working

Check the following:

  • Confirm the service is running: systemctl status vm-port-mapping
  • Check the log file: cat /var/log/vm_port_mapping.log
  • Ensure the firewall service is normal: systemctl status firewalld
  • Verify VM network interface configuration: virsh domiflist VM-name
Manually adding mapping rules

Usually, manual addition of rules is not needed, but if necessary:

  1. Stop the service:

    bash
    systemctl stop vm-port-mapping
  2. Edit the mapping file:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. Start the service:

    bash
    systemctl start vm-port-mapping
Cleaning all rules
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
Security Recommendations
  • Regularly check mapping files and logs to ensure there are no unauthorized mappings
  • Do not manually modify files in the /etc/vm_port_mapping/ directory unless you fully understand the impact
  • Make sure the firewalld service is running properly so that rules can be correctly persisted

Uninstallation Method

To uninstall this service:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 Manual Mapping

Assume your virtual machine is shown in the user control panel as

wv1

and the host machine command ip a | head -n 15 result is

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet your_public_IPv4_address/corresponding_subnet_mask scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

It's evident that the public IPv4 address is bound to the ens3 interface, so we'll use ens3 in the following commands.

To map the current VM's port 22 to the public IPv4's port 3322, use:

shell
# Add DNAT rule: Forward public 3322 traffic to host local 192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# Add POSTROUTING: Local NAT masquerading for normal return connections
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# Need to allow INPUT port 3322 through (firewalld is enabled by default)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

This way, the internal virtual machine is mapped out and can be remotely logged in directly.

4. Troubleshooting

Compute Node Addition Error Troubleshooting

Execute on the Controller:

shell
telnet <node ip> 8884

Execute on the compute node:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

If none of the above reveals the problem, then you need to execute on the Controller:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

Change DEBUG=False to DEBUG=True, save the file, then execute in the container:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

Then exit the container and execute:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

Then trigger the error in the frontend, and you'll see the corresponding error in the real-time loaded logs.

Docker Containers Not Auto-Restarting After Controller Reboot

If Docker containers don't automatically restart after system reboot, execute:

bash
docker start $(docker ps -a -q)

5. Drawbacks

System images are hard-coded; you can't use your own custom images, nor export them for use.

This is not the same project as https://github.com/retspen/webvirtcloud, don't confuse them.

Acknowledgements

https://webvirt.cloud/

- +
Skip to content

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Original project repository: https://github.com/webvirtcloud/webvirtcloud

1. Controller Installation

System Requirements

Minimum Requirements:

  • CPU: 1 core
  • Memory: 1 GB RAM
  • Storage: 10 GB free space
  • System: Debian11+, Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

Default Login Information

  • Username: admin@webvirt.cloud
  • Password: admin

Panel Access

  • User Panel: https://192-168-0-114.nip.io
  • Admin Backend: https://192-168-0-114.nip.io/admin

Note: Replace 192.168.0.114 with your public IP to get the actual accessible address.

Installation Command

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
+&& chmod +x install_webvirt_cloud.sh \
+&& bash install_webvirt_cloud.sh

TIP

The execution process may be stuck in the clone repository has not been moving, at this time, press ctrl + c to exit the implementation, re-execution of the installation script on the line, the Department of Docker installation is stuck in the stage of the build project.

2. Compute Node Installation

Important: Hypervisor and Controller cannot be installed on the same virtual machine, otherwise network conflicts will occur.

System Requirements

Recommended Configuration:

  • CPU: 2 cores
  • Memory: 4 GB RAM
  • Storage: 40 GB free space
  • System: AlmaLinux8+, RockyLinux8+

Additional Notes:

  • Higher configurations are recommended for actual use; the test environment is only sufficient for running 4 minimal virtual machines.
  • Servers with KVM nested virtualization support are recommended. If VM-x/AMD-V/Hyper-V is not enabled, it will automatically switch to QEMU using TCG emulation to set up virtual machines, though performance will be reduced.
  • The installation skips environment checks and uses binary files directly, so no dependencies need to be installed.

Environment Check

Check if the server supports KVM nested virtualization:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

Select hardware individual test

Compute Node Installation Steps

  1. Download the installation script:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    +&& chmod +x install_hypervisor.sh
  2. Execute installation (replace with your Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    Replace x.x.x.x with the actual IP address of your Controller.

  3. Node Management in Panel
    After execution, there will be prompts for information needed in the Controller panel.
    In the panel, the Hostname to be entered is the current compute node's IPv4 address, and you need to enter the Token to identify the node.

NetworkManager Version Issue

During installation, you may encounter the following error:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
+Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
+Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

Solution: Restart the server and re-execute the installation command.

Installation Time Note

  • The entire process takes approximately 10-25 minutes.
  • Most of the time is spent downloading finnix-125.iso to /var/lib/libvirt/isos/finnix-125.iso.
  • This part cannot be accelerated, so it's recommended to use tmux or screen to prevent interruption.

Adding Compute Node to Control Panel

After installation, a Token will be generated for adding the compute node in the control panel (Admin panel):

Path: Admin Panel > Computers > Add Computer

  • HostName should be filled with the compute node's public IPv4 address
  • Token should be filled with the token key obtained on the compute node

3. Public IPv4 Port Mapping

3.1 Automatic Mapping

Automatic mapping features:

  • Automatic Monitoring: Real-time monitoring of virtual machine status changes, automatically applying or cleaning up port mapping rules
  • Intelligent Port Allocation: Automatically calculating and allocating non-conflicting ports based on VM IP addresses
  • Rule Persistence: Using firewall-cmd to ensure port mapping rules remain effective after host restart
  • Mapping Records: Automatically maintaining mapping information records for easy viewing and management
  • Conflict Prevention: Intelligently detecting and avoiding port conflicts, ensuring each VM has unique port mappings

Installation Method

  1. Download the script to a temporary directory:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. Add execution permission:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. Run the installer:

    bash
    /tmp/vm_port_mapping_setup.sh

The script will automatically complete the following operations:

  • Copy itself to the system directory /usr/local/sbin/vm_port_mapping_daemon.sh
  • Create a systemd service unit file
  • Enable and start the service

Port Mapping Rules

The daemon will assign the following ports for each virtual machine:

  1. SSH Port:

    • Calculation formula: (Last segment of IP) × 100 + 22 + 10000
    • Example: For IP address 192.168.33.114, the mapped SSH port is 114×100+22+10000 = 21422
  2. Extra Ports:

    • 10 additional ports are allocated for each VM
    • Starting port: 20000 + (Last segment of IP) × 100
    • Ending port: Starting port + 9
    • Example: For IP address 192.168.33.114, extra port range is 20000+(114×100) to 20000+(114×100)+9

If the calculated port is already occupied, the program will automatically find the next available port to ensure no conflicts occur.

Mapping File

All port mapping information is saved in the /etc/vm_port_mapping/mapping.txt file, in the format:

VM name IP address MAC address SSH mapped port Extra ports start Extra ports end

For example:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

Service Management

  • Check service status:

    bash
    systemctl status vm-port-mapping
  • Start service:

    bash
    systemctl start vm-port-mapping
  • Stop service:

    bash
    systemctl stop vm-port-mapping
  • Disable auto-start:

    bash
    systemctl disable vm-port-mapping
  • View logs:

    bash
    journalctl -u vm-port-mapping
    +# or
    +cat /var/log/vm_port_mapping.log
  • Manually trigger rule update:

    bash
    systemctl restart vm-port-mapping

Common Issues

Port mapping not working

Check the following:

  • Confirm the service is running: systemctl status vm-port-mapping
  • Check the log file: cat /var/log/vm_port_mapping.log
  • Ensure the firewall service is normal: systemctl status firewalld
  • Verify VM network interface configuration: virsh domiflist VM-name
Manually adding mapping rules

Usually, manual addition of rules is not needed, but if necessary:

  1. Stop the service:

    bash
    systemctl stop vm-port-mapping
  2. Edit the mapping file:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. Start the service:

    bash
    systemctl start vm-port-mapping
Cleaning all rules
bash
systemctl stop vm-port-mapping
+grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
+  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
+  for ((port=port_start; port<=port_end; port++)); do
+    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
+  done
+done
+firewall-cmd --reload
Security Recommendations
  • Regularly check mapping files and logs to ensure there are no unauthorized mappings
  • Do not manually modify files in the /etc/vm_port_mapping/ directory unless you fully understand the impact
  • Make sure the firewalld service is running properly so that rules can be correctly persisted

Uninstallation Method

To uninstall this service:

bash
systemctl stop vm-port-mapping
+systemctl disable vm-port-mapping
+rm -f /etc/systemd/system/vm-port-mapping.service
+rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
+rm -rf /etc/vm_port_mapping
+systemctl daemon-reload

3.2 Manual Mapping

Assume your virtual machine is shown in the user control panel as

wv1

and the host machine command ip a | head -n 15 result is

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    inet 127.0.0.1/8 scope host lo
+       valid_lft forever preferred_lft forever
+    inet6 ::1/128 scope host
+       valid_lft forever preferred_lft forever
+2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
+    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
+    altname enp0s3
+    inet your_public_IPv4_address/corresponding_subnet_mask scope global noprefixroute ens3
+       valid_lft forever preferred_lft forever
+    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
+       valid_lft forever preferred_lft forever
+    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
+       valid_lft forever preferred_lft forever

It's evident that the public IPv4 address is bound to the ens3 interface, so we'll use ens3 in the following commands.

To map the current VM's port 22 to the public IPv4's port 3322, use:

shell
# Add DNAT rule: Forward public 3322 traffic to host local 192.168.33.130:22
+iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
+# Add POSTROUTING: Local NAT masquerading for normal return connections
+iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
+# Need to allow INPUT port 3322 through (firewalld is enabled by default)
+iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

This way, the internal virtual machine is mapped out and can be remotely logged in directly.

4. Troubleshooting

Compute Node Addition Error Troubleshooting

Execute on the Controller:

shell
telnet <node ip> 8884

Execute on the compute node:

shell
systemctl status webvirtcompute
+systemctl status libvirtd
+systemctl status prometheus
+systemctl status prometheus-libvirt-exporter

If none of the above reveals the problem, then you need to execute on the Controller:

shell
docker exec -it webvirtcloud-backend /bin/sh
+vi webvirtcloud/settings/production.py

Change DEBUG=False to DEBUG=True, save the file, then execute in the container:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

Then exit the container and execute:

shell
docker restart webvirtcloud-backend
+sleep 3
+docker logs webvirtcloud-backend -f

Then trigger the error in the frontend, and you'll see the corresponding error in the real-time loaded logs.

Docker Containers Not Auto-Restarting After Controller Reboot

If Docker containers don't automatically restart after system reboot, execute:

bash
docker start $(docker ps -a -q)

5. Drawbacks

System images are hard-coded; you can't use your own custom images, nor export them for use.

This is not the same project as https://github.com/retspen/webvirtcloud, don't confuse them.

Acknowledgements

https://webvirt.cloud/

+ \ No newline at end of file diff --git a/en/incomplete/webvirtcloud_retspen.html b/en/incomplete/webvirtcloud_retspen.html index 1a8948c714..d9cd41ba1d 100644 --- a/en/incomplete/webvirtcloud_retspen.html +++ b/en/incomplete/webvirtcloud_retspen.html @@ -3,28 +3,31 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository::https://github.com/retspen/webvirtcloud

Controller Node and Computer Node Installation

  • Supported Systems: Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • Recommended system: Debian12+, Ubuntu22.04+.
  • Lower versions of the system will automatically compile the new version of python installation package before deployment, so it is recommended to use a new system without compiling directly installed!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
-&& chmod +x install_webvirt_cloud_retspen.sh \
-&& bash install_webvirt_cloud_retspen.sh

After installation is complete, open the public IP address to access the login page.

The default login username and password are both admin. Make sure to change them after logging in.

Creating a Linux Virtual Machine

After entering the control panel and changing the admin password, you need to manually configure a compute node.

vcr1

Select the type as Local, and name it local.

vcr2

After creation, click the eye icon to enter the view.

vcr3

Under the Storage section, add a storage entry. Choose the type Dir and name it local. If you need to use an ISO for system boot, you’ll need to create a storage of type ISO. If not, just follow this guide and create only the Dir type.

vcr4

vcr5

After creation, download the appropriate qcow2 image for the system using the repository below:

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

In the example, a Debian 12 qcow2 image is used:

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

Return to the instance page to create a new instance.

vcr6

Select local as the compute node.

vcr7

The default chipset is fine; changing it is optional.

vcr8

You can use predefined sizes for the virtual machine or customize it, depending on your preference.

vcr9

Note: the instance name must not duplicate the system name. For example, you cannot use debian12 as the instance name in this case.

vcr10

After successful creation, do not power it on immediately.

vcr11

You need to modify the disk settings first.

vcr12

Change the disk file to debian12.qcow2, which matches the qcow2 image you previously downloaded.

vcr13

Once confirmed and configured correctly, return to the power page and turn on the VM.

vcr14

The default login for the image is:

  • Username: root
  • Password: password or oneclickvirt

Disadvantages

Networking is not auto-configured — not as smart as the previous project — you still need to configure it manually.

- +
Skip to content

WebVirtCloud Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository::https://github.com/retspen/webvirtcloud

Controller Node and Computer Node Installation

  • Supported Systems: Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • Recommended system: Debian12+, Ubuntu22.04+.
  • Lower versions of the system will automatically compile the new version of python installation package before deployment, so it is recommended to use a new system without compiling directly installed!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
+&& chmod +x install_webvirt_cloud_retspen.sh \
+&& bash install_webvirt_cloud_retspen.sh

After installation is complete, open the public IP address to access the login page.

The default login username and password are both admin. Make sure to change them after logging in.

Creating a Linux Virtual Machine

After entering the control panel and changing the admin password, you need to manually configure a compute node.

vcr1

Select the type as Local, and name it local.

vcr2

After creation, click the eye icon to enter the view.

vcr3

Under the Storage section, add a storage entry. Choose the type Dir and name it local. If you need to use an ISO for system boot, you’ll need to create a storage of type ISO. If not, just follow this guide and create only the Dir type.

vcr4

vcr5

After creation, download the appropriate qcow2 image for the system using the repository below:

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

In the example, a Debian 12 qcow2 image is used:

shell
cd /var/lib/libvirt/images
+wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
+chmod 777 debian12.qcow2

Return to the instance page to create a new instance.

vcr6

Select local as the compute node.

vcr7

The default chipset is fine; changing it is optional.

vcr8

You can use predefined sizes for the virtual machine or customize it, depending on your preference.

vcr9

Note: the instance name must not duplicate the system name. For example, you cannot use debian12 as the instance name in this case.

vcr10

After successful creation, do not power it on immediately.

vcr11

You need to modify the disk settings first.

vcr12

Change the disk file to debian12.qcow2, which matches the qcow2 image you previously downloaded.

vcr13

Once confirmed and configured correctly, return to the power page and turn on the VM.

vcr14

The default login for the image is:

  • Username: root
  • Password: password or oneclickvirt

Disadvantages

Networking is not auto-configured — not as smart as the previous project — you still need to configure it manually.

+ \ No newline at end of file diff --git a/en/incomplete/webvirtmgr.html b/en/incomplete/webvirtmgr.html index 40f897c344..b7d606d835 100644 --- a/en/incomplete/webvirtmgr.html +++ b/en/incomplete/webvirtmgr.html @@ -3,26 +3,29 @@ - One Click Virtualization | One Click Virtualization + One Click Virtualization - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtMgr Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository: https://github.com/retspen/webvirtmgr

Control nodes and compute nodes installed at the same time

  • Supported systems: Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • The system will automatically compile python 2.7 installer and then deployed, there will be an error in the compilation process but do not pay attention to it, as long as the scripts are still running, it means that everything is fine!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
-&& chmod +x install_webvirtmgr.sh \
-&& bash install_webvirtmgr.sh

Disadvantages

The origin project is no longer maintained and is not recommended at all.

- +
Skip to content

WebVirtMgr Installation Guide

hits

Repository: https://github.com/oneclickvirt/webvirtcloud

Origin Repository: https://github.com/retspen/webvirtmgr

Control nodes and compute nodes installed at the same time

  • Supported systems: Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • The system will automatically compile python 2.7 installer and then deployed, there will be an error in the compilation process but do not pay attention to it, as long as the scripts are still running, it means that everything is fine!
bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
+&& chmod +x install_webvirtmgr.sh \
+&& bash install_webvirtmgr.sh

Disadvantages

The origin project is no longer maintained and is not recommended at all.

+ \ No newline at end of file diff --git a/en/index.html b/en/index.html index 3c5ce37846..4d16774ae2 100644 --- a/en/index.html +++ b/en/index.html @@ -5,22 +5,25 @@ K'thun - + + + - - - - - + + + + + - + + -
Skip to content

One Click Virtualization

Open source, easy to use server virtualization project

- +
Skip to content

One Click VirtualizationOpen source, easy to use server virtualization project

+ \ No newline at end of file diff --git a/guide/block/block_docker.html b/guide/block/block_docker.html index 2837120b09..6f719bf974 100644 --- a/guide/block/block_docker.html +++ b/guide/block/block_docker.html @@ -5,22 +5,25 @@ 待开发,敬请期待 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/guide/block/block_incus.html b/guide/block/block_incus.html index 11d8d31fa5..e3a89a831c 100644 --- a/guide/block/block_incus.html +++ b/guide/block/block_incus.html @@ -5,22 +5,25 @@ 通过shell脚本屏蔽滥用行为 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
- +
Skip to content

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
+ \ No newline at end of file diff --git a/guide/block/block_iptables.html b/guide/block/block_iptables.html index 345d47fe44..99c7fc6d94 100644 --- a/guide/block/block_iptables.html +++ b/guide/block/block_iptables.html @@ -5,75 +5,78 @@ 通过iptables屏蔽滥用 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

通过iptables屏蔽滥用

iptables的基础使用说明

1. 启动 iptables

在大多数 Linux 发行版中,iptables 服务可以通过以下命令启动:

bash
sudo systemctl start iptables

2. 设置规则

在启动 iptables 后,可以设置相应的规则来屏蔽滥用流量。例如,以下命令将阻止来自特定IPV4地址的流量:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. 查询规则

设置完规则后,可以使用以下命令查看当前的 iptables 规则:

bash
sudo iptables -L

这将列出所有输入、输出和转发的规则。

4. 停止 iptables

如果需要停止 iptables 服务,可以使用以下命令:

bash
sudo systemctl stop iptables

5. 保存规则

为了确保在重启后规则依然生效,可以保存当前的规则:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. 恢复规则

在需要恢复规则时,可以使用以下命令:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. 其他常用命令

  • 列出规则(详细信息)

    bash
    sudo iptables -L -v
  • 删除特定规则

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • 清空所有规则

    bash
    sudo iptables -F

在宿主机上屏蔽滥用行为

屏蔽挖矿行为

strings=(
-    "ethermine.com"
-    "antpool.one"
-    "antpool.com"
-    "pool.bar"
-    "get_peers"
-    "announce_peer"
-    "find_node"
-    "seed_hash"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽BT行为

strings=(
-    "torrent"
-    ".torrent"
-    "peer_id="
-    "announce"
-    "info_hash"
-    "get_peers"
-    "find_node"
-    "BitTorrent"
-    "announce_peer"
-    "BitTorrent protocol"
-    "announce.php?passkey="
-    "magnet:"
-    "xunlei"
-    "sandai"
-    "Thunder"
-    "XLLiveUD"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done

屏蔽测速行为

strings=(
-    ".speed"
-    "speed."
-    ".speed."
-    "fast.com"
-    "speedtest.net"
-    "speedtest.com"
-    "speedtest.cn"
-    "test.ustc.edu.cn"
-    "10000.gd.cn"
-    "db.laomoe.com"
-    "jiyou.cloud"
-    "ovo.speedtestcustom.com"
-    "speed.cloudflare.com"
-    "speedtest"
-)
-
-for str in "${strings[@]}"; do
-    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
-done
- +
Skip to content

通过iptables屏蔽滥用

iptables的基础使用说明

1. 启动 iptables

在大多数 Linux 发行版中,iptables 服务可以通过以下命令启动:

bash
sudo systemctl start iptables

2. 设置规则

在启动 iptables 后,可以设置相应的规则来屏蔽滥用流量。例如,以下命令将阻止来自特定IPV4地址的流量:

bash
sudo iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

3. 查询规则

设置完规则后,可以使用以下命令查看当前的 iptables 规则:

bash
sudo iptables -L

这将列出所有输入、输出和转发的规则。

4. 停止 iptables

如果需要停止 iptables 服务,可以使用以下命令:

bash
sudo systemctl stop iptables

5. 保存规则

为了确保在重启后规则依然生效,可以保存当前的规则:

bash
sudo iptables-save | sudo tee /etc/iptables/rules.v4

6. 恢复规则

在需要恢复规则时,可以使用以下命令:

bash
sudo iptables-restore < /etc/iptables/rules.v4

7. 其他常用命令

  • 列出规则(详细信息)

    bash
    sudo iptables -L -v
  • 删除特定规则

    bash
    sudo iptables -D INPUT -s 192.168.1.100 -j DROP
  • 清空所有规则

    bash
    sudo iptables -F

在宿主机上屏蔽滥用行为

屏蔽挖矿行为

strings=(
+    "ethermine.com"
+    "antpool.one"
+    "antpool.com"
+    "pool.bar"
+    "get_peers"
+    "announce_peer"
+    "find_node"
+    "seed_hash"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

屏蔽BT行为

strings=(
+    "torrent"
+    ".torrent"
+    "peer_id="
+    "announce"
+    "info_hash"
+    "get_peers"
+    "find_node"
+    "BitTorrent"
+    "announce_peer"
+    "BitTorrent protocol"
+    "announce.php?passkey="
+    "magnet:"
+    "xunlei"
+    "sandai"
+    "Thunder"
+    "XLLiveUD"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done

屏蔽测速行为

strings=(
+    ".speed"
+    "speed."
+    ".speed."
+    "fast.com"
+    "speedtest.net"
+    "speedtest.com"
+    "speedtest.cn"
+    "test.ustc.edu.cn"
+    "10000.gd.cn"
+    "db.laomoe.com"
+    "jiyou.cloud"
+    "ovo.speedtestcustom.com"
+    "speed.cloudflare.com"
+    "speedtest"
+)
+
+for str in "${strings[@]}"; do
+    iptables -A OUTPUT -m string --string "$str" --algo bm -j DROP
+done
+ \ No newline at end of file diff --git a/guide/block/block_lxd.html b/guide/block/block_lxd.html index 6302634fdd..2e04e6bb51 100644 --- a/guide/block/block_lxd.html +++ b/guide/block/block_lxd.html @@ -5,22 +5,25 @@ 通过shell脚本屏蔽滥用行为 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
- +
Skip to content

通过shell脚本屏蔽滥用行为

屏蔽容易被滥用的端口的出入流量以屏蔽端口和屏蔽滥用工具包

  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事前预防

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/rules.sh -o rules.sh && chmod +x rules.sh && bash rules.sh

使用screen配置监控屏蔽某些进程的执行遇到某些进程的出现直接关闭容器

  • 如需停止监控可使用screen命令停止lxc_moniter这个名字的窗口并删除
  • (非必须,该脚本仅仅是为了防止容器滥用方便,不装的也没问题)
  • 事后停机

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_monitor.sh -o build_monitor.sh && chmod +x build_monitor.sh && bash build_monitor.sh
+ \ No newline at end of file diff --git a/guide/block/block_pve.html b/guide/block/block_pve.html index 7d5387a99c..d9d34ed331 100644 --- a/guide/block/block_pve.html +++ b/guide/block/block_pve.html @@ -5,25 +5,28 @@ 通过设置防火墙限制虚拟机使用的IP避免盗用 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

通过设置防火墙限制虚拟机使用的IP避免盗用

在PVE的宿主机下创建以下文件

shell
/etc/pve/firewall/<VMID>.fw
+    
Skip to content

通过设置防火墙限制虚拟机使用的IP避免盗用

在PVE的宿主机下创建以下文件

shell
/etc/pve/firewall/<VMID>.fw
 
-[IPSET ipfilter-<net0>]
-xxx.xxx.xxx.xxx

<VMID>替换为虚拟机的VMID数字,<net0>替换为网络设备中对应的别名(一般不用修改,除非你限制的IPV6),xxx.xxx.xxx.xxx替换为公网IP地址,注意此IP对应前面的网络设备。

这里的意思是net0只能使用xxx.xxx.xxx.xxx这个IP,如果使用其他的IP数据将会被丢弃,从而达到限制虚拟机只能使用此IP的目的。

这里可以有多个IP,一旦启用此规则该VM就无法使用除此之外的任何IP,如果你没有写IPv6地址则代表该VM无法使用IPv6地址。

TIP

本设置仅推荐在开设非NAT全端口映射的独立IP的虚拟机时使用,否则可能导致奇奇怪怪的问题造成服务器没网。

该方法不适合开设任何NAT虚拟机/容器的PVE上使用。

- +[IPSET ipfilter-<net0>] +xxx.xxx.xxx.xxx

<VMID>替换为虚拟机的VMID数字,<net0>替换为网络设备中对应的别名(一般不用修改,除非你限制的IPV6),xxx.xxx.xxx.xxx替换为公网IP地址,注意此IP对应前面的网络设备。

这里的意思是net0只能使用xxx.xxx.xxx.xxx这个IP,如果使用其他的IP数据将会被丢弃,从而达到限制虚拟机只能使用此IP的目的。

这里可以有多个IP,一旦启用此规则该VM就无法使用除此之外的任何IP,如果你没有写IPv6地址则代表该VM无法使用IPv6地址。

TIP

本设置仅推荐在开设非NAT全端口映射的独立IP的虚拟机时使用,否则可能导致奇奇怪怪的问题造成服务器没网。

该方法不适合开设任何NAT虚拟机/容器的PVE上使用。

+ \ No newline at end of file diff --git a/guide/dashboard.html b/guide/dashboard.html index 002a29149d..8700162479 100644 --- a/guide/dashboard.html +++ b/guide/dashboard.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

准备工作

需要虚拟化出服务器,你需要:

  1. 一台可以连接公网的服务器( VPS 或 Dedicated Server),最好能完美访问 Github 的 RAW 页面,部分项目部分组件可能未使用 CDN 加速

TIP

如果您位于中国大陆,访问 Github 有困难,请注意配套脚本和项目是否有说明已使用 CDN 加速

  1. 本地可以稳定连接SSH,如果不能稳定连接,请使用screen命令创建窗口后,在窗口内执行命令

TIP

不会用screen命令的,自行查找相关教程学习,或者用tmux替代也行

  1. 确保服务器的系统和硬件满足对应项目的要求,详见对应项目说明

本文档将以VPS作为范例,且该VPS纯净,无原生环境问题,如有必要请重装系统保证初始环境的纯净

WARNING

PVE项目可能造成宿主机出现问题,如果你不会看Bug和修复系统,那么不建议你在生产环境中使用,使用PVE相关脚本请确保宿主机随时可重装系统

项目仓库

欢迎Star和Fork,所有资源均开源,无非开源部分,转载以及使用请写上来源于本站,谢谢

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

- +
Skip to content

准备工作

需要虚拟化出服务器,你需要:

  1. 一台可以连接公网的服务器( VPS 或 Dedicated Server),最好能完美访问 Github 的 RAW 页面,部分项目部分组件可能未使用 CDN 加速

TIP

如果您位于中国大陆,访问 Github 有困难,请注意配套脚本和项目是否有说明已使用 CDN 加速

  1. 本地可以稳定连接SSH,如果不能稳定连接,请使用screen命令创建窗口后,在窗口内执行命令

TIP

不会用screen命令的,自行查找相关教程学习,或者用tmux替代也行

  1. 确保服务器的系统和硬件满足对应项目的要求,详见对应项目说明

本文档将以VPS作为范例,且该VPS纯净,无原生环境问题,如有必要请重装系统保证初始环境的纯净

WARNING

PVE项目可能造成宿主机出现问题,如果你不会看Bug和修复系统,那么不建议你在生产环境中使用,使用PVE相关脚本请确保宿主机随时可重装系统

项目仓库

欢迎Star和Fork,所有资源均开源,无非开源部分,转载以及使用请写上来源于本站,谢谢

PVE

https://github.com/oneclickvirt/pve

Hits

incus

https://github.com/oneclickvirt/incus

Hits

Docker

https://github.com/oneclickvirt/docker

Hits

LXD

https://github.com/oneclickvirt/lxd

Hits

+ \ No newline at end of file diff --git a/guide/dashboardq.html b/guide/dashboardq.html index 5c927e9148..df28f8f7d5 100644 --- a/guide/dashboardq.html +++ b/guide/dashboardq.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/guide/docker/docker_android.html b/guide/docker/docker_android.html index 58ea7b46f9..e5a5170109 100644 --- a/guide/docker/docker_android.html +++ b/guide/docker/docker_android.html @@ -5,27 +5,30 @@ 在Docker中开设Android虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

在Docker中开设Android虚拟机

一键开设

  • 自定义安卓版本
  • 自动创建带校验的web网站
  • 自动进行nginx安装和反向代理的配置,可选择是否绑定域名,默认回车不绑定使用80端口
  • 无需考虑宿主机是否支持嵌套虚拟化
  • 支持x86_64和ARM架构

宿主机的配置至少要有1核2G内存15G硬盘,否则开设可能会导致宿主机卡死

宿主机推荐 Ubuntu 系统,Debian 系统可能导致安卓屏幕白屏

安卓版本越新占用越大,以上的配置要求是最低版本安卓的配置要求 (个人测试到 12.0.0-latest 的tag可用,更高版本映射白屏了,自己测试哪个能用吧)

如果开设后,过了5分钟浏览器网页的登录验证还是一直失败,那么请查询安卓容器的日志,大概率安卓容器崩溃了,建议更换更低的安卓系统版本的容器进行安装

开设

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

命令执行后按照提示输入即可,注意选择版本输入的是序号,对应选项的数字序号,安装完毕后打开本机IPV4+80端口可登录

如果需要查询生成的安卓信息和web登录信息,执行cat /root/android_info可查询信息

默认的用户名 onea

默认密码 oneclick

远程的桌面点击H264 Converter跳转就是了

暂时只支持生成一个安卓容器,勿要重复生成,如需替换版本请执行后续命令删除后再次开设

暂时只支持开设后一直使用,不可重启服务器,重启后可能无法自重启映射成功,自测

删除

  • 删除容器
  • 删除容器对应镜像
  • 删除配置文件
docker rm -f android
-docker rmi $(docker images | grep "redroid" | awk '{print $3}')
-rm -rf /etc/nginx/sites-enabled/reverse-proxy
-rm -rf /etc/nginx/sites-available/reverse-proxy
-rm -rf /etc/nginx/passwd_scrcpy_web
-rm -rf /root/android_info
- +
Skip to content

在Docker中开设Android虚拟机

一键开设

  • 自定义安卓版本
  • 自动创建带校验的web网站
  • 自动进行nginx安装和反向代理的配置,可选择是否绑定域名,默认回车不绑定使用80端口
  • 无需考虑宿主机是否支持嵌套虚拟化
  • 支持x86_64和ARM架构

宿主机的配置至少要有1核2G内存15G硬盘,否则开设可能会导致宿主机卡死

宿主机推荐 Ubuntu 系统,Debian 系统可能导致安卓屏幕白屏

安卓版本越新占用越大,以上的配置要求是最低版本安卓的配置要求 (个人测试到 12.0.0-latest 的tag可用,更高版本映射白屏了,自己测试哪个能用吧)

如果开设后,过了5分钟浏览器网页的登录验证还是一直失败,那么请查询安卓容器的日志,大概率安卓容器崩溃了,建议更换更低的安卓系统版本的容器进行安装

开设

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_android.sh -o create_android.sh && chmod +x create_android.sh && bash create_android.sh

命令执行后按照提示输入即可,注意选择版本输入的是序号,对应选项的数字序号,安装完毕后打开本机IPV4+80端口可登录

如果需要查询生成的安卓信息和web登录信息,执行cat /root/android_info可查询信息

默认的用户名 onea

默认密码 oneclick

远程的桌面点击H264 Converter跳转就是了

暂时只支持生成一个安卓容器,勿要重复生成,如需替换版本请执行后续命令删除后再次开设

暂时只支持开设后一直使用,不可重启服务器,重启后可能无法自重启映射成功,自测

删除

  • 删除容器
  • 删除容器对应镜像
  • 删除配置文件
docker rm -f android
+docker rmi $(docker images | grep "redroid" | awk '{print $3}')
+rm -rf /etc/nginx/sites-enabled/reverse-proxy
+rm -rf /etc/nginx/sites-available/reverse-proxy
+rm -rf /etc/nginx/passwd_scrcpy_web
+rm -rf /root/android_info
+ \ No newline at end of file diff --git a/guide/docker/docker_build.html b/guide/docker/docker_build.html index 3b64861f35..f6b74b7e4f 100644 --- a/guide/docker/docker_build.html +++ b/guide/docker/docker_build.html @@ -5,45 +5,48 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

两种开设方式

单独开设

  • 只生成一个docker,这里有判断为国际服务器还是国内服务器,如果在国内服务器上开设,容器内的包管理源自动替换为清华源
  • 可配置绑定独立的IPV6地址,但需要先前使用本套脚本的环境安装命令安装的docker,且需要宿主机至少绑定了/112的IPV6子网
  • 支持x86_64和ARM架构的服务器

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

示例

运行支持的变量

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

目前system仅支持选择

  • alpine
  • debian
  • ubuntu
  • almalinux

默认不填则是debian

shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

以下为开设的示例容器的信息:

属性
容器名字test
SSH登录的用户名root
SSH登录的密码123456
CPU核数1
内存大小512MB
SSH端口25000
内外网映射端口一致的区间34975到35000
系统debian
是否绑定独立的IPV6地址N

相关操作

删除示例

shell
docker rm -f test
-rm -rf test
-ls

进入示例

shell
docker exec -it test /bin/bash

要退出容器就执行exit退出。

查询已开设的信息

shell
cat 容器名字

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

批量开设

  • 批量多次运行继承配置生成
  • 生成多个时为避免SSH连接中断建议在screen中执行
  • 支持x86_64和ARM架构的服务器

运行

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

查询批量开设的信息

shell
cat dclog

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

一行一个容器对应的信息,docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

卸载所有docker容器和镜像

以下命令卸载会忽略ndpresponder,以防止IPV6的配置失效

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
-docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
-rm -rf dclog
-ls

更新上述所有脚本

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/onedocker.sh
-rm -rf /root/create_docker.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
-wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

宿主机重启后重启所有容器

默认容器没有设置停止后自重启,需要执行以下命令启动所有停止的容器

docker start $(docker ps -aq)

宿主机重启后启动所有容器的SSH服务

由于容器本身没有守护进程,所以SSH服务无法自启动,需要执行以下命令启动所有容器的SSH进程

container_ids=$(docker ps -q)
-for container_id in $container_ids
-do
-    docker exec -it $container_id bash -c "service ssh start"
-    docker exec -it $container_id bash -c "service sshd restart"
-    docker exec -it $container_id sh -c "service ssh start"
-    docker exec -it $container_id sh -c "/usr/sbin/sshd"
-done
- +
Skip to content

前言

两种开设方式

单独开设

  • 只生成一个docker,这里有判断为国际服务器还是国内服务器,如果在国内服务器上开设,容器内的包管理源自动替换为清华源
  • 可配置绑定独立的IPV6地址,但需要先前使用本套脚本的环境安装命令安装的docker,且需要宿主机至少绑定了/112的IPV6子网
  • 支持x86_64和ARM架构的服务器

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

示例

运行支持的变量

./onedocker.sh name cpu memory password sshport startport endport <independent_ipv6> <system>

目前system仅支持选择

  • alpine
  • debian
  • ubuntu
  • almalinux

默认不填则是debian

shell
./onedocker.sh test 1 512 123456 25000 34975 35000 N debian

以下为开设的示例容器的信息:

属性
容器名字test
SSH登录的用户名root
SSH登录的密码123456
CPU核数1
内存大小512MB
SSH端口25000
内外网映射端口一致的区间34975到35000
系统debian
是否绑定独立的IPV6地址N

相关操作

删除示例

shell
docker rm -f test
+rm -rf test
+ls

进入示例

shell
docker exec -it test /bin/bash

要退出容器就执行exit退出。

查询已开设的信息

shell
cat 容器名字

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

批量开设

  • 批量多次运行继承配置生成
  • 生成多个时为避免SSH连接中断建议在screen中执行
  • 支持x86_64和ARM架构的服务器

运行

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -o create_docker.sh && chmod +x create_docker.sh && bash create_docker.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -o onedocker.sh && chmod +x onedocker.sh

查询批量开设的信息

shell
cat dclog

输出格式

容器名字 SSH端口 登陆的root密码 核数 内存 外网端口起 外网端口止

一行一个容器对应的信息,docker的ipv6地址只能在容器内自己查询,在docker的配置中是不存在的

卸载所有docker容器和镜像

以下命令卸载会忽略ndpresponder,以防止IPV6的配置失效

shell
docker ps -a --format '{{.Names}}' | grep -vE '^ndpresponder' | xargs -r docker rm -f
+docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep -v 'ndpresponder' | awk '{print $2}' | xargs -r docker rmi
+rm -rf dclog
+ls

更新上述所有脚本

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/onedocker.sh
+rm -rf /root/create_docker.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onedocker.sh -O /root/onedocker.sh && chmod +x /root/onedocker.sh
+wget https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/create_docker.sh -O /root/create_docker.sh && chmod +x /root/create_docker.sh

宿主机重启后重启所有容器

默认容器没有设置停止后自重启,需要执行以下命令启动所有停止的容器

docker start $(docker ps -aq)

宿主机重启后启动所有容器的SSH服务

由于容器本身没有守护进程,所以SSH服务无法自启动,需要执行以下命令启动所有容器的SSH进程

container_ids=$(docker ps -q)
+for container_id in $container_ids
+do
+    docker exec -it $container_id bash -c "service ssh start"
+    docker exec -it $container_id bash -c "service sshd restart"
+    docker exec -it $container_id sh -c "service ssh start"
+    docker exec -it $container_id sh -c "/usr/sbin/sshd"
+done
+ \ No newline at end of file diff --git a/guide/docker/docker_custom.html b/guide/docker/docker_custom.html index c6932dcd86..b81032b045 100644 --- a/guide/docker/docker_custom.html +++ b/guide/docker/docker_custom.html @@ -5,32 +5,35 @@ 使用Docker一键安装某些容器的脚本 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

使用Docker一键安装某些容器的脚本

每个容器都有对应的配置要求,自行查看,内存不够的用https://github.com/spiritLHLS/addswap

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

开设虚拟内存补足也行

注意,以下脚本使用前务必使用本套教程中的环境安装脚本进行前期环境安装

一键开设Firefox浏览器的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 可选是否开启VNC端口,默认不开启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 不支持声音映射,无论是WEB端还是VNC端都无法传输声音

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码1G硬盘

开设

如果未设置自定义密码,开设后默认的密码是oneclick

默认的web端口是3003,开设后打开本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

删除

修改以下端口号3003为你实际的端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3003"
-docker stop firefox_${PORT}
-docker rm -f firefox_${PORT}
-rm -rf /usr/local/bin/firefox_${PORT}
-docker rmi jlesage/firefox

一键开设Chrome浏览器的容器

  • 已设置崩溃自启
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射

宿主机需要至少1核2G内存10G硬盘,开设的容器大小将占用起码1G硬盘

首次安装过程中最好在screen中挂起执行,避免长时间运行SSH连接断开

开设

如果未设置自定义用户名,开设后默认的用户名是oneclick

如果未设置自定义密码,开设后默认的密码是oneclick

默认的http端口是3004,开设后打开http://本机IPV4:端口即可

默认的https端口是3005,开设后打开https://本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

删除

修改以下端口号3004为你实际的http端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3004"
-docker stop chromium_${PORT}
-docker rm -f chromium_${PORT}
-rm -rf /usr/local/bin/config_${PORT}
-rm -rf /usr/local/bin/password_${PORT}
-docker rmi lscr.io/linuxserver/chromium

注意事项

  • nginx,caddy等https映射的时候要映射3004的端口,不要映射3005端口
  • 部署以后安静的等待15分钟,不然中文库没安装全,会出现不可预料的错误
  • 进入远程桌面浏览器以后点击左侧的设置->点开输入法进行设置,不然没法输入中文

图片

一键开设Desktop的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置用户名和密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射,WEB端可传输声音

完整的Linux桌面,可以在上面使用浏览器

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码3.2G硬盘

开设

开设后默认的用户名是onew,密码是oneclick,默认的内存最大占用是2GB

默认的http协议的web端口是3004,默认的https协议的web端口是3005,开设后打开对应协议的本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

删除

执行

shell
docker ps -a

查询name的前缀是webtop的容器,记录容器的ID用

shell
docker rm -f 容器的ID

删除所有关联的容器后可用

shell
docker rmi lscr.io/linuxserver/webtop

删除对应镜像

一键安装guacamole

一个网页端连接SSH或RDP等协议控制服务器的玩意

网址:http://你的IPV4地址:80/guacamole

默认用户: guacadmin

默认密码: guacadmin

安装完毕登录后自行修改

宿主机的配置至少要有1核2G内存10G硬盘,否则开设可能会导致宿主机卡死!

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

一键开设RustDesk的容器

  • 已设置崩溃自启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 传输质量看你的服务器和各端之间的连通性和延迟

一个跨端的远控中继端(非客户端),支持双向控制

宿主机需要至少1核1G内存10G硬盘,对带宽的需求极低

开设

安装后客户端在这里找 https://github.com/rustdesk/rustdesk/releases/latest

在设置中设置中继服务器的IP即可,支持 Android、Windows、Linux、浏览器 端,支持电脑远控手机

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onerustdesk.sh -o onerustdesk.sh && chmod +x onerustdesk.sh && bash onerustdesk.sh

删除

删除容器

shell
docker rm -f hbbs
-docker rm -f hbbr

删除对应镜像

shell
docker rmi rustdesk/rustdesk-server
- +
Skip to content

使用Docker一键安装某些容器的脚本

每个容器都有对应的配置要求,自行查看,内存不够的用https://github.com/spiritLHLS/addswap

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

开设虚拟内存补足也行

注意,以下脚本使用前务必使用本套教程中的环境安装脚本进行前期环境安装

一键开设Firefox浏览器的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 可选是否开启VNC端口,默认不开启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 不支持声音映射,无论是WEB端还是VNC端都无法传输声音

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码1G硬盘

开设

如果未设置自定义密码,开设后默认的密码是oneclick

默认的web端口是3003,开设后打开本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onefirefox.sh -o onefirefox.sh && chmod +x onefirefox.sh && bash onefirefox.sh

删除

修改以下端口号3003为你实际的端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3003"
+docker stop firefox_${PORT}
+docker rm -f firefox_${PORT}
+rm -rf /usr/local/bin/firefox_${PORT}
+docker rmi jlesage/firefox

一键开设Chrome浏览器的容器

  • 已设置崩溃自启
  • 自带web的校验,可自设置密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射

宿主机需要至少1核2G内存10G硬盘,开设的容器大小将占用起码1G硬盘

首次安装过程中最好在screen中挂起执行,避免长时间运行SSH连接断开

开设

如果未设置自定义用户名,开设后默认的用户名是oneclick

如果未设置自定义密码,开设后默认的密码是oneclick

默认的http端口是3004,开设后打开http://本机IPV4:端口即可

默认的https端口是3005,开设后打开https://本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onechromium.sh -o onechromium.sh && chmod +x onechromium.sh && bash onechromium.sh

删除

修改以下端口号3004为你实际的http端口号,然后执行命令回车两次即可删除容器、配置文件、对应镜像

shell
PORT="3004"
+docker stop chromium_${PORT}
+docker rm -f chromium_${PORT}
+rm -rf /usr/local/bin/config_${PORT}
+rm -rf /usr/local/bin/password_${PORT}
+docker rmi lscr.io/linuxserver/chromium

注意事项

  • nginx,caddy等https映射的时候要映射3004的端口,不要映射3005端口
  • 部署以后安静的等待15分钟,不然中文库没安装全,会出现不可预料的错误
  • 进入远程桌面浏览器以后点击左侧的设置->点开输入法进行设置,不然没法输入中文

图片

一键开设Desktop的容器

  • 已设置崩溃自启
  • 已设置带中文字体
  • 自带web的校验,可自设置用户名和密码
  • 可自定义容器最大的内存占用
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 支持声音映射,WEB端可传输声音

完整的Linux桌面,可以在上面使用浏览器

宿主机需要至少1核2G内存5G硬盘,开设的容器大小将占用起码3.2G硬盘

开设

开设后默认的用户名是onew,密码是oneclick,默认的内存最大占用是2GB

默认的http协议的web端口是3004,默认的https协议的web端口是3005,开设后打开对应协议的本机IPV4:端口即可

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewebtop.sh -o onewebtop.sh && chmod +x onewebtop.sh && bash onewebtop.sh

删除

执行

shell
docker ps -a

查询name的前缀是webtop的容器,记录容器的ID用

shell
docker rm -f 容器的ID

删除所有关联的容器后可用

shell
docker rmi lscr.io/linuxserver/webtop

删除对应镜像

一键安装guacamole

一个网页端连接SSH或RDP等协议控制服务器的玩意

网址:http://你的IPV4地址:80/guacamole

默认用户: guacadmin

默认密码: guacadmin

安装完毕登录后自行修改

宿主机的配置至少要有1核2G内存10G硬盘,否则开设可能会导致宿主机卡死!

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/extra_scripts/guacamole.sh -o guacamole.sh && chmod +x guacamole.sh && bash guacamole.sh

一键开设RustDesk的容器

  • 已设置崩溃自启
  • 无需考虑是否支持嵌套虚拟化和服务器的架构
  • 传输质量看你的服务器和各端之间的连通性和延迟

一个跨端的远控中继端(非客户端),支持双向控制

宿主机需要至少1核1G内存10G硬盘,对带宽的需求极低

开设

安装后客户端在这里找 https://github.com/rustdesk/rustdesk/releases/latest

在设置中设置中继服务器的IP即可,支持 Android、Windows、Linux、浏览器 端,支持电脑远控手机

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onerustdesk.sh -o onerustdesk.sh && chmod +x onerustdesk.sh && bash onerustdesk.sh

删除

删除容器

shell
docker rm -f hbbs
+docker rm -f hbbr

删除对应镜像

shell
docker rmi rustdesk/rustdesk-server
+ \ No newline at end of file diff --git a/guide/docker/docker_install.html b/guide/docker/docker_install.html index 618f141b32..cbd33e307b 100644 --- a/guide/docker/docker_install.html +++ b/guide/docker/docker_install.html @@ -5,22 +5,25 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

支持开设 Docker 虚拟化的各系统,含 Linux、Android、Windows 系统

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

开设虚拟内存

TIP

内存开点swap免得机器炸了

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

环境安装

  • 检测系统环境,安装对应组件
  • 安装docker和docker-compose,这里有判断为国际服务器还是国内服务器,自动安装对应源的docker
  • 下载默认需要的一些配置脚本,设置默认的网络配置
  • 检测如果存在IPV6地址,检测其是否大于或等于/112,如果符合条件,则配置docker的ipv6的网络
  • 如果上述条件都符合,创建ndpresponder的docker和radvd,使得IPV6的分配支持ndp广播和自动分配
  • 支持x86_64和ARM架构的服务器

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

bash dockerinstall.sh

TIP

环境安装过程中可能要求你重启服务器后再次执行脚本,详见脚本运行后的说明

- +
Skip to content

前言

支持开设 Docker 虚拟化的各系统,含 Linux、Android、Windows 系统

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

开设虚拟内存

TIP

内存开点swap免得机器炸了

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

环境安装

  • 检测系统环境,安装对应组件
  • 安装docker和docker-compose,这里有判断为国际服务器还是国内服务器,自动安装对应源的docker
  • 下载默认需要的一些配置脚本,设置默认的网络配置
  • 检测如果存在IPV6地址,检测其是否大于或等于/112,如果符合条件,则配置docker的ipv6的网络
  • 如果上述条件都符合,创建ndpresponder的docker和radvd,使得IPV6的分配支持ndp广播和自动分配
  • 支持x86_64和ARM架构的服务器

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/dockerinstall.sh -o dockerinstall.sh && chmod +x dockerinstall.sh && bash dockerinstall.sh

bash dockerinstall.sh

TIP

环境安装过程中可能要求你重启服务器后再次执行脚本,详见脚本运行后的说明

+ \ No newline at end of file diff --git a/guide/docker/docker_macos.html b/guide/docker/docker_macos.html index 5656f78891..da97421fa2 100644 --- a/guide/docker/docker_macos.html +++ b/guide/docker/docker_macos.html @@ -5,22 +5,25 @@ 在Docker中开设Macos虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/guide/docker/docker_precheck.html b/guide/docker/docker_precheck.html index be50ff3665..70256e6760 100644 --- a/guide/docker/docker_precheck.html +++ b/guide/docker/docker_precheck.html @@ -5,22 +5,25 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

WARNING

如果宿主机带IPV6网络的话,安装会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/docker

项目特点

通过docker批量或单独开设NAT服务器(Bulk or individual NAT server provisioning via docker)

默认使用debian系统可选alpine系统,每个容器自带1个外网ssh端口,25个内外网一致端口,可选择是否绑定IPV6地址

默认创建的是非特权容器,且不挂载与宿主机的docker的守护进程之间的通信,所以宿主机创建的docker虚拟化的NAT服务器内无法再嵌套虚拟化docker

默认安装并启用lxcfs,使得在容器内的查询资源时CPU和内存使用的是配置的视图而不是宿主机的视图

由于大部分云服务器是ext4文件系统,docker默认的存储引擎是overlayfs2,即便宿主机的文件系统是xfs,默认也不会启用pquota选项,所以默认共享宿主机硬盘,无法限制每个容器的磁盘大小

配置要求

系统可安装docker即可用,网络能连接Github的raw界面就能用,硬件配置只要不拉跨就行,空闲硬盘有3G就行

(如果需要绑定IPV6地址,那么请保证使用本套脚本的环境预设脚本进行环境安装,需要它自动预设部分设置)

如果硬件资源只是好了一点,需要限制更多东西并需要限制硬盘大小,可使用incus分区的脚本批量开LXC虚拟化的容器

如果硬件非常好资源很多,可使用PVE分区的脚本批量开KVM虚拟化的虚拟机

推荐在开设NAT服务器前先增加部分SWAP虚拟内存,避免突发的内存占用导致宿主机卡死

- +
Skip to content

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

WARNING

如果宿主机带IPV6网络的话,安装会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/docker

项目特点

通过docker批量或单独开设NAT服务器(Bulk or individual NAT server provisioning via docker)

默认使用debian系统可选alpine系统,每个容器自带1个外网ssh端口,25个内外网一致端口,可选择是否绑定IPV6地址

默认创建的是非特权容器,且不挂载与宿主机的docker的守护进程之间的通信,所以宿主机创建的docker虚拟化的NAT服务器内无法再嵌套虚拟化docker

默认安装并启用lxcfs,使得在容器内的查询资源时CPU和内存使用的是配置的视图而不是宿主机的视图

由于大部分云服务器是ext4文件系统,docker默认的存储引擎是overlayfs2,即便宿主机的文件系统是xfs,默认也不会启用pquota选项,所以默认共享宿主机硬盘,无法限制每个容器的磁盘大小

配置要求

系统可安装docker即可用,网络能连接Github的raw界面就能用,硬件配置只要不拉跨就行,空闲硬盘有3G就行

(如果需要绑定IPV6地址,那么请保证使用本套脚本的环境预设脚本进行环境安装,需要它自动预设部分设置)

如果硬件资源只是好了一点,需要限制更多东西并需要限制硬盘大小,可使用incus分区的脚本批量开LXC虚拟化的容器

如果硬件非常好资源很多,可使用PVE分区的脚本批量开KVM虚拟化的虚拟机

推荐在开设NAT服务器前先增加部分SWAP虚拟内存,避免突发的内存占用导致宿主机卡死

+ \ No newline at end of file diff --git a/guide/docker/docker_qa.html b/guide/docker/docker_qa.html index 24ff549517..f99003d3ba 100644 --- a/guide/docker/docker_qa.html +++ b/guide/docker/docker_qa.html @@ -5,22 +5,25 @@ 解惑 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

解惑

常见的一些docker命令

查询某个容器的实时占用

docker stats 容器名字

进入某个容器

docker exec -it 容器名字 /bin/bash

清理 Docker 缓存,清理未使用的资源,包括镜像、容器、网络等

docker system prune -a

卸载所有docker的镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

查看对应容器日志

docker logs 容器名字或ID

查看docker整体的disk占用

docker system df

查看所有容器

docker ps -a

查看所有镜像

docker images

删除某个特定容器

docker rm -f 容器名字或ID

删除某个特定镜像

docker rmi 镜像名字或ID
- +
Skip to content

解惑

常见的一些docker命令

查询某个容器的实时占用

docker stats 容器名字

进入某个容器

docker exec -it 容器名字 /bin/bash

清理 Docker 缓存,清理未使用的资源,包括镜像、容器、网络等

docker system prune -a

卸载所有docker的镜像和容器

docker rm -f $(docker ps -aq); docker rmi $(docker images -aq)

查看对应容器日志

docker logs 容器名字或ID

查看docker整体的disk占用

docker system df

查看所有容器

docker ps -a

查看所有镜像

docker images

删除某个特定容器

docker rm -f 容器名字或ID

删除某个特定镜像

docker rmi 镜像名字或ID
+ \ No newline at end of file diff --git a/guide/docker/docker_thanks.html b/guide/docker/docker_thanks.html index 6786613287..5e668cbf46 100644 --- a/guide/docker/docker_thanks.html +++ b/guide/docker/docker_thanks.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/guide/docker/docker_windows.html b/guide/docker/docker_windows.html index 2b28b53076..8d244eb7da 100644 --- a/guide/docker/docker_windows.html +++ b/guide/docker/docker_windows.html @@ -5,47 +5,50 @@ 在Docker中开设Windows系统虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

在Docker中开设Windows系统虚拟机

一键开设(通过vagrant)

  • 共享宿主机所有资源(CPU、内存、硬盘),基于docker所以只占用系统的大小,适合多开
  • 共享IP,做了docker的NAT映射,可选择是否映射到外网或仅内网
  • 设置的win系统默认最多占用为1核2G内存50G硬盘,实际占用看使用情况
  • 无需iptables进行NAT映射,删除容器时自动删除了端口的映射,方便维护
  • 需要考虑宿主机是否支持嵌套虚拟化,暂时只支持X86_64架构的系统

宿主机需要支持嵌套虚拟化,且暂时只支持X86_64架构的系统,否则不可开设

执行

egrep -c '(vmx|svm)' /proc/cpuinfo

结果需要大于或等于1,不能为0

然后需要先设置docker切换使用v1版cgroup启动

sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
-update-grub
-ls

如果执行都无报错,执行reboot重启系统以使得设置生效

支持的镜像

使用的自建的镜像:https://hub.docker.com/r/spiritlhl/wds

镜像名字镜像大小
1020G
202217.5G
201917G

创建出的容器大小会比镜像大小大一丢丢,但不多

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

使用方法

开设前务必在screen窗口中执行,避免SSH长期链接造成掉线卡死

./onewindows.sh 容器名字 系统版本 RDP的端口 是否为外网映射(留空则默认是N,可选Y)

开设前需要确认宿主机至少有镜像大小的两倍大小加10G硬盘的大小,因为docker在创建容器时得先将镜像拉到本地再创建

创建过程中,硬盘占用峰值为宿主机系统+镜像大小+容器大小

比如开设容器名字为test,占用最低的Windows 2019系统的容器,映射外网RDP端口为13389,设置为外网映射(映射到你的服务器外网IPV4地址)

./onewindows.sh test 2019 13389 Y

开设后默认的用户名是Administratorvagrant

默认的密码是vagrant

如果你选择开设映射的外网端口,务必登录后修改对应账户的密码(两个账户都可能有,自行尝试),否则可能被人爆破滥用

删除

需要删除对应镜像和容器,先执行docker ps -adocker images查询镜像是spiritlhl/wds的ID,然后对应使用

docker rm -f 容器的ID
-docker rmi 镜像的ID

删除后可开设别的版本的windows容器

(在宿主机上使用Docker安装Windows系统,好像绕过了某些商家不允许DD成Win系统的TOS限制)

手动开设(通过 Dockur 项目)

本项目支持在宿主机不支持嵌套虚拟化的情况下,使用 QEMU 进行虚拟机创建。

原始项目地址

注意事项:

  • 原始项目仅为启动器,不包含 Windows 镜像;

  • 使用时需下载镜像文件,在境内网络环境下首次启动容器需约 4 小时(含镜像下载和安装);

  • 默认要求宿主机具备以下最低硬件资源(可通过修改脚本进行调整):

    • CPU:至少 4 核
    • 内存:至少 4G
    • 硬盘:至少 64G

如需魔改启动脚本以减少资源占用或调整其他参数,可参考以下文章:

对于 x86_64 架构用户

提供一个已魔改的启动器(单文件版本),方便自行构建 Windows 镜像。该版本将系统文件和镜像直接写入 Docker 写入层中,无需额外挂载镜像文件

下载链接: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

导入 Docker 镜像:

bash
docker load -i builder.tar

使用自定义 Windows ISO 镜像启动容器

首先从以下地址下载 Windows ISO 镜像: https://down.idc.wiki/ISOS/Windows/

启动容器示例命令:

bash
docker run -it -d \
-  -e RAM_SIZE="8G" \
-  -e CPU_CORES="4" \
-  --name win2022 \
-  -p 8006:8006 \
-  --device=/dev/kvm \
-  --device=/dev/net/tun \
-  --cap-add NET_ADMIN \
-  -v "$(pwd)/Windows镜像文件.iso:/boot.iso" \
-  --stop-timeout 120 \
-  windows:builder

使用内置镜像(推荐快速部署)

我们也提供一个已集成系统镜像和配置的成品镜像,特点如下:

  • 镜像大小约 26G(包含系统镜像与默认配置);
  • 已集成自动磁盘扩容与开机任务;
  • 下载后导入 Docker 即可使用;
  • 注意:合并下载路径需要约 60G 空间。

下载与合并切片

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
-chmod +x mergew.sh
-bash mergew.sh

启动容器

bash
docker load -i win2022.tar
-docker run -it -d \
-  -e RAM_SIZE="4G" \
-  -e CPU_CORES="2" \
-  --name win2022 \
-  -p 8006:8006 \
-  --device=/dev/kvm \
-  --device=/dev/net/tun \
-  --cap-add NET_ADMIN \
-  --stop-timeout 120 \
-  windows:2022

注意事项

不建议在当前镜像基础上使用 docker commit 保存修改,因为写入层会不断叠加,导致二次生成的镜像体积可能超过 40G。

如需进行个性化配置或集成应用,请builder 镜像开始自行构建新镜像,以保持镜像整洁与可维护性。

- +
Skip to content

在Docker中开设Windows系统虚拟机

一键开设(通过vagrant)

  • 共享宿主机所有资源(CPU、内存、硬盘),基于docker所以只占用系统的大小,适合多开
  • 共享IP,做了docker的NAT映射,可选择是否映射到外网或仅内网
  • 设置的win系统默认最多占用为1核2G内存50G硬盘,实际占用看使用情况
  • 无需iptables进行NAT映射,删除容器时自动删除了端口的映射,方便维护
  • 需要考虑宿主机是否支持嵌套虚拟化,暂时只支持X86_64架构的系统

宿主机需要支持嵌套虚拟化,且暂时只支持X86_64架构的系统,否则不可开设

执行

egrep -c '(vmx|svm)' /proc/cpuinfo

结果需要大于或等于1,不能为0

然后需要先设置docker切换使用v1版cgroup启动

sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
+update-grub
+ls

如果执行都无报错,执行reboot重启系统以使得设置生效

支持的镜像

使用的自建的镜像:https://hub.docker.com/r/spiritlhl/wds

镜像名字镜像大小
1020G
202217.5G
201917G

创建出的容器大小会比镜像大小大一丢丢,但不多

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/docker/main/scripts/onewindows.sh -o onewindows.sh && chmod +x onewindows.sh

使用方法

开设前务必在screen窗口中执行,避免SSH长期链接造成掉线卡死

./onewindows.sh 容器名字 系统版本 RDP的端口 是否为外网映射(留空则默认是N,可选Y)

开设前需要确认宿主机至少有镜像大小的两倍大小加10G硬盘的大小,因为docker在创建容器时得先将镜像拉到本地再创建

创建过程中,硬盘占用峰值为宿主机系统+镜像大小+容器大小

比如开设容器名字为test,占用最低的Windows 2019系统的容器,映射外网RDP端口为13389,设置为外网映射(映射到你的服务器外网IPV4地址)

./onewindows.sh test 2019 13389 Y

开设后默认的用户名是Administratorvagrant

默认的密码是vagrant

如果你选择开设映射的外网端口,务必登录后修改对应账户的密码(两个账户都可能有,自行尝试),否则可能被人爆破滥用

删除

需要删除对应镜像和容器,先执行docker ps -adocker images查询镜像是spiritlhl/wds的ID,然后对应使用

docker rm -f 容器的ID
+docker rmi 镜像的ID

删除后可开设别的版本的windows容器

(在宿主机上使用Docker安装Windows系统,好像绕过了某些商家不允许DD成Win系统的TOS限制)

手动开设(通过 Dockur 项目)

本项目支持在宿主机不支持嵌套虚拟化的情况下,使用 QEMU 进行虚拟机创建。

原始项目地址

注意事项:

  • 原始项目仅为启动器,不包含 Windows 镜像;

  • 使用时需下载镜像文件,在境内网络环境下首次启动容器需约 4 小时(含镜像下载和安装);

  • 默认要求宿主机具备以下最低硬件资源(可通过修改脚本进行调整):

    • CPU:至少 4 核
    • 内存:至少 4G
    • 硬盘:至少 64G

如需魔改启动脚本以减少资源占用或调整其他参数,可参考以下文章:

对于 x86_64 架构用户

提供一个已魔改的启动器(单文件版本),方便自行构建 Windows 镜像。该版本将系统文件和镜像直接写入 Docker 写入层中,无需额外挂载镜像文件

下载链接: https://github.com/oneclickvirt/docker/releases/download/amd64_builder/builder.tar

导入 Docker 镜像:

bash
docker load -i builder.tar

使用自定义 Windows ISO 镜像启动容器

首先从以下地址下载 Windows ISO 镜像: https://down.idc.wiki/ISOS/Windows/

启动容器示例命令:

bash
docker run -it -d \
+  -e RAM_SIZE="8G" \
+  -e CPU_CORES="4" \
+  --name win2022 \
+  -p 8006:8006 \
+  --device=/dev/kvm \
+  --device=/dev/net/tun \
+  --cap-add NET_ADMIN \
+  -v "$(pwd)/Windows镜像文件.iso:/boot.iso" \
+  --stop-timeout 120 \
+  windows:builder

使用内置镜像(推荐快速部署)

我们也提供一个已集成系统镜像和配置的成品镜像,特点如下:

  • 镜像大小约 26G(包含系统镜像与默认配置);
  • 已集成自动磁盘扩容与开机任务;
  • 下载后导入 Docker 即可使用;
  • 注意:合并下载路径需要约 60G 空间。

下载与合并切片

bash
curl https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/docker/refs/heads/main/extra_scripts/mergew.sh -o mergew.sh
+chmod +x mergew.sh
+bash mergew.sh

启动容器

bash
docker load -i win2022.tar
+docker run -it -d \
+  -e RAM_SIZE="4G" \
+  -e CPU_CORES="2" \
+  --name win2022 \
+  -p 8006:8006 \
+  --device=/dev/kvm \
+  --device=/dev/net/tun \
+  --cap-add NET_ADMIN \
+  --stop-timeout 120 \
+  windows:2022

注意事项

不建议在当前镜像基础上使用 docker commit 保存修改,因为写入层会不断叠加,导致二次生成的镜像体积可能超过 40G。

如需进行个性化配置或集成应用,请builder 镜像开始自行构建新镜像,以保持镜像整洁与可维护性。

+ \ No newline at end of file diff --git a/guide/incus/incus_custom.html b/guide/incus/incus_custom.html index 35a4b307f2..2478b1ad46 100644 --- a/guide/incus/incus_custom.html +++ b/guide/incus/incus_custom.html @@ -5,101 +5,104 @@ 自定义 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

自定义

给incus启用官方的web面板进行控制

先查看 incus论坛活跃用户分享的第三方教程

不懂的部分见 给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如incus的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

- +
Skip to content

自定义

给incus启用官方的web面板进行控制

先查看 incus论坛活跃用户分享的第三方教程

不懂的部分见 给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
+systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如incus的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
+EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
+ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
+Client IPv4
+Server IPv6
+Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
+ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
+ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
+apt update -y
+
+# 安装 WireGuard 运行依赖
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# 安装 WireGuard 协议兼容的工具集合
+apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
+yum update -y
+
+# 安装额外包组件
+yum install -y epel-release 
+
+# 安装 WireGuard 运行依赖
+yum install -y net-tools
+
+# 安装 WireGuard 协议兼容的工具集合
+yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
+sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
+wg-quick up warp
+
+# 查看 IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# 查看 IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# 测试成功后断开 Warp 连接
+wg-quick down warp
+
+# 重新连接并设置进程守护,以便重启后自动生效
+systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

+ \ No newline at end of file diff --git a/guide/incus/incus_extra_config.html b/guide/incus/incus_extra_config.html index 250366c94c..9d7bfc1da8 100644 --- a/guide/incus/incus_extra_config.html +++ b/guide/incus/incus_extra_config.html @@ -5,32 +5,35 @@ 其他自定义配置 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为incus创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开incus宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

安装incus的官方可视化控制面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
apt-get install -y incus-ui-canonical
-incus config set core.https_address [::]

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

- +
Skip to content

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为incus创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

一键安装开incus宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

安装incus的官方可视化控制面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
apt-get install -y incus-ui-canonical
+incus config set core.https_address [::]

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

+ \ No newline at end of file diff --git a/guide/incus/incus_install.html b/guide/incus/incus_install.html index 1bf54bb587..38b6a7b79a 100644 --- a/guide/incus/incus_install.html +++ b/guide/incus/incus_install.html @@ -5,38 +5,41 @@ incus主体安装 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

incus主体安装

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

一键安装

WARNING

如果是全新的服务器,务必保证curl命令可用且update无问题再执行本脚本。

  • 环境要求:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

shell
bash incus_install.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

TIP

执行过程中可能会要求手动重启加载存储类型到内核中,安装完毕执行到最后会自动进行服务器重启,首次完整安装完毕后的重启大概耗时400~500秒,请耐心等待

WARNING

如果你需要在一台服务器上开启超过200个INCUS容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装incus

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

sudo -i
-mkdir -p /etc/apt/keyrings/
-curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
-sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
-Enabled: yes
-Types: deb
-URIs: https://pkgs.zabbly.com/incus/stable
-Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
-Components: main
-Architectures: $(dpkg --print-architecture)
-Signed-By: /etc/apt/keyrings/zabbly.gpg
-EOF'
-apt-get update
-apt-get install incus -y
-incus -h

如果无异常,继续执行

incus admin init

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

incus -h
- +
Skip to content

incus主体安装

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

一键安装

WARNING

如果是全新的服务器,务必保证curl命令可用且update无问题再执行本脚本。

  • 环境要求:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/incus_install.sh -o incus_install.sh && chmod +x incus_install.sh && bash incus_install.sh

shell
bash incus_install.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

TIP

执行过程中可能会要求手动重启加载存储类型到内核中,安装完毕执行到最后会自动进行服务器重启,首次完整安装完毕后的重启大概耗时400~500秒,请耐心等待

WARNING

如果你需要在一台服务器上开启超过200个INCUS容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装incus

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

sudo -i
+mkdir -p /etc/apt/keyrings/
+curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --dearmor -o /etc/apt/keyrings/zabbly.gpg
+sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-stable.sources
+Enabled: yes
+Types: deb
+URIs: https://pkgs.zabbly.com/incus/stable
+Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
+Components: main
+Architectures: $(dpkg --print-architecture)
+Signed-By: /etc/apt/keyrings/zabbly.gpg
+EOF'
+apt-get update
+apt-get install incus -y
+incus -h

如果无异常,继续执行

incus admin init

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

incus -h
+ \ No newline at end of file diff --git a/guide/incus/incus_lxc.html b/guide/incus/incus_lxc.html index 8c445a15b6..3977c0228e 100644 --- a/guide/incus/incus_lxc.html +++ b/guide/incus/incus_lxc.html @@ -5,46 +5,49 @@ 在 Incus 中运行 LXC 容器 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

在 Incus 中运行 LXC 容器

开设LXC容器可使用的镜像

这里展示一部分可使用的系统参数供你参考:

  • debian10,debian11,debian12
  • ubuntu18,ubuntu20,ubuntu22
  • centos8,centos9 (实际开设出来都是Stream版本)
  • alpine3.15,alpine3.16,alpine3.17,alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (都需要在GRUB中启用CGroupV1否则无法启动,详细介绍见常见问题答疑)
  • kali,archlinux
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载脚本

下载开机脚本是非必须的,如果你使用过一键安装incus的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian11,注意传入参数为系统名字+版本号

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

需要进入容器内部则执行

incus exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
incus stop test
-incus delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用incus命令

查看所有

bash
incus list

查看个例

bash
incus info 服务器名字

启动个例

bash
incus start 服务器名字

停止个例

bash
incus stop 服务器名字

删除个例

bash
incus delete -f 服务器名字

进入内部

bash
incus exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

- +
Skip to content

在 Incus 中运行 LXC 容器

开设LXC容器可使用的镜像

这里展示一部分可使用的系统参数供你参考:

  • debian10,debian11,debian12
  • ubuntu18,ubuntu20,ubuntu22
  • centos8,centos9 (实际开设出来都是Stream版本)
  • alpine3.15,alpine3.16,alpine3.17,alpine3.18
  • openwrt21,openwrt22,fedora37,fedora38,fedora39
  • rockylinux8,rockylinux9,oralce8,oracle9
  • oralce7,centos7 (都需要在GRUB中启用CGroupV1否则无法启动,详细介绍见常见问题答疑)
  • kali,archlinux
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载脚本

下载开机脚本是非必须的,如果你使用过一键安装incus的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian11,注意传入参数为系统名字+版本号

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian11
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian11

需要进入容器内部则执行

incus exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
incus stop test
+incus delete test
+rm -rf test
+rm -rf test_v6
+ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/incus/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
+2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用incus命令

查看所有

bash
incus list

查看个例

bash
incus info 服务器名字

启动个例

bash
incus start 服务器名字

停止个例

bash
incus stop 服务器名字

删除个例

bash
incus delete -f 服务器名字

进入内部

bash
incus exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
incus list -c n --format csv | xargs -I {} incus delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

+ \ No newline at end of file diff --git a/guide/incus/incus_precheck.html b/guide/incus/incus_precheck.html index b16c35f28d..972aae399c 100644 --- a/guide/incus/incus_precheck.html +++ b/guide/incus/incus_precheck.html @@ -5,22 +5,25 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/incus

要求

硬件要求:

  • 系统:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu24Debian12,别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换(优先级: btrfs > lvm > zfs > ceph > dir )

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加各种第三方镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像(含自修复镜像)

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
- +
Skip to content

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看incus模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/incus

要求

硬件要求:

  • 系统:Ubuntu 20+, Debian 11+, RockyLinux 9+, AlmaLinux 9+, Centos 9+
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu24Debian12,别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换(优先级: btrfs > lvm > zfs > ceph > dir )

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加各种第三方镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像(含自修复镜像)

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/incus/main/scripts/pre_check.sh)
+ \ No newline at end of file diff --git a/guide/incus/incus_qa.html b/guide/incus/incus_qa.html index 6a3205812e..6df55a5c4f 100644 --- a/guide/incus/incus_qa.html +++ b/guide/incus/incus_qa.html @@ -5,22 +5,25 @@ 解惑 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

解惑

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销款

- +
Skip to content

解惑

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销款

+ \ No newline at end of file diff --git a/guide/incus/incus_thanks.html b/guide/incus/incus_thanks.html index fcf3648603..a410120d95 100644 --- a/guide/incus/incus_thanks.html +++ b/guide/incus/incus_thanks.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/guide/incus/incus_windows.html b/guide/incus/incus_windows.html index bb1e6b745b..1cd274344c 100644 --- a/guide/incus/incus_windows.html +++ b/guide/incus/incus_windows.html @@ -5,49 +5,52 @@ 在 Incus 中运行 Windows 虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

在 Incus 中运行 Windows 虚拟机

检查 Incus 驱动

确保 incus info 输出中含有 qemu,否则无法创建 VM:

shell
incus info | grep -i driver:

若显示只有 lxc,则incus的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root 目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install distrobuilder --classic
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

支持修补的Windows镜像版本:https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-distrobuilder repack-windows \
-  --windows-arch=amd64 \
-  win.iso \
-  win.incus.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screentmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
# 初始化空 VM
-incus init winvm --empty --vm
+    
Skip to content

在 Incus 中运行 Windows 虚拟机

检查 Incus 驱动

确保 incus info 输出中含有 qemu,否则无法创建 VM:

shell
incus info | grep -i driver:

若显示只有 lxc,则incus的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root 目录下按顺序执行以下命令:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install distrobuilder --classic
+# 重启加载一些配置
+reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

支持修补的Windows镜像版本:https://linuxcontainers.org/distrobuilder/docs/latest/tutorials/use/#repack-windows-iso

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+distrobuilder repack-windows \
+  --windows-arch=amd64 \
+  win.iso \
+  win.incus.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screentmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
# 初始化空 VM
+incus init winvm --empty --vm
 
-# 调整根盘大小、CPU、内存
-incus config device override winvm root size=30GiB
-incus config set winvm limits.cpu=3
-incus config set winvm limits.memory=5GiB
+# 调整根盘大小、CPU、内存
+incus config device override winvm root size=30GiB
+incus config set winvm limits.cpu=3
+incus config set winvm limits.memory=5GiB
 
-# 添加 TPM 设备(Secure Boot/BitLocker 支持)
-incus config device add winvm vtpm tpm path=/dev/tpm0
+# 添加 TPM 设备(Secure Boot/BitLocker 支持)
+incus config device add winvm vtpm tpm path=/dev/tpm0
 
-# 挂载安装 ISO,设为第一启动项
-incus config device add winvm install disk \
-  source=/root/win.incus.iso \
-  boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
incus start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示Zabbly的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用incus list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
incus stop winvm
-incus config device remove winvm install
-incus start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,incus将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后incus delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
incus config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

- +# 挂载安装 ISO,设为第一启动项 +incus config device add winvm install disk \ + source=/root/win.incus.iso \ + boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
+apt install -y spice-html5 websockify lsof

启动虚拟机

shell
incus start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/run/incus/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示Zabbly的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用incus list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
incus stop winvm
+incus config device remove winvm install
+incus start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,incus将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后incus delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
incus config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

+ \ No newline at end of file diff --git a/guide/lxd/lxd_custom.html b/guide/lxd/lxd_custom.html index 4629249678..e9459107c2 100644 --- a/guide/lxd/lxd_custom.html +++ b/guide/lxd/lxd_custom.html @@ -5,101 +5,104 @@ 自定义 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

自定义

给lxd启用官方的web面板

给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
-# systemctl stop systemd-networkd
-# systemctl disable systemd-networkd
-# systemctl stop systemd-networkd.socket
-# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
-systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如LXD的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
-EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
-systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
-ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
-Client IPv4
-Server IPv6
-Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
-# 这里修改一下
-EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
-systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
-ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
-ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
-apt update -y
-
-# 安装 WireGuard 运行依赖
-apt install -y --no-install-recommends net-tools openresolv dnsutils
-
-# 安装 WireGuard 协议兼容的工具集合
-apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
-yum update -y
-
-# 安装额外包组件
-yum install -y epel-release 
-
-# 安装 WireGuard 运行依赖
-yum install -y net-tools
-
-# 安装 WireGuard 协议兼容的工具集合
-yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = ::/0
-Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
-PrivateKey = <替换 PrivateKey>
-Address = 172.16.0.2/32
-Address = <替换 Address v6 地址>/128
-DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
-MTU = 1280
-
-[Peer]
-PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
-AllowedIPs = 0.0.0.0/0
-Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
-grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
-sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
-wg-quick up warp
-
-# 查看 IPv4
-curl -A a https://api-ipv4.ip.sb/geoip
-
-# 查看 IPv6
-curl -A a https://api-ipv6.ip.sb/geoip
-
-# 测试成功后断开 Warp 连接
-wg-quick down warp
-
-# 重新连接并设置进程守护,以便重启后自动生效
-systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
-wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

- +
Skip to content

自定义

给lxd启用官方的web面板

给机房的Ubuntu22.04安装LXD共享GPU资源-配置web 部分的内容

给宿主机附加免费的IPV6地址段

有的机器本身没有IPV6的/64子网,这里给出一个方法免费附加IPV6的子网。

这里是使用6in4方法解决宿主机本身没有IPV6地址的问题。

TIP

本页面的操作务必在原始系统上操作,保证未使用本项目的其他脚本安装环境(除了PVE,PVE需要先安装好),否则可能导致环境冲突

以下是2023年目前还在运行的免费提供IPV6子网的平台

支持的平台对应需要的安装包协议通道/子网数量
tunnelbroker.netifupdown 或 ifupdown2v4tunnel 或 sit3✖/64 或 5✖/64
tunnelbroker.chifupdown 或 ifupdown2v4tunnel 或 sit3✖/64
ip4market.ruifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
netassist.uaifupdown 或 ifupdown2v4tunnel 或 sit1✖/64
https://github.com/oneclickvirt/6in4ifupdown2sit、gre、ipip自定义

免费的平台只解决IPV6有没有的问题,不提供优质的IPV6带宽。

如需优质的带宽,请自建隧道,当ifupdown和ifupdown2都可时,先尝试ifupdown是否可安装成功,否则就安装ifupdown2.

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

初始环境修改

执行

touch /etc/cloud/cloud-init.disabled

关闭cloud-init的自动化覆写先,然后查看本机使用什么管理网络,执行

systemctl is-active systemd-networkd

systemctl is-active networking

看看属于哪种情况,如果是前者active,后者inactive,你需要重装/DD一个不是这样配置的系统,或者切换本机使用ifupdown/ifupdown2管理网络

# 是否需要禁用原网络管理自行评判
+# systemctl stop systemd-networkd
+# systemctl disable systemd-networkd
+# systemctl stop systemd-networkd.socket
+# systemctl disable systemd-networkd.socket

如果需要安装的是ifupdown控制网络,这个工具一般的主流linux系统都有

apt-get install ifupdown -y

如果需要安装的是ifupdown2进行网络管理,而这个工具一般只在debian系上可安装使用

apt-get install ifupdown2 -y

安装完毕后,安装了哪个包后面就选择哪个包进行格式转换。

systemctl start networking
+systemctl enable networking

然后重启服务器,检验机器的网络是否会因为修改出现重启失联的情况,且执行uptime观察启动已超过1分钟后,再进行后续步骤

如果是是前者inactive,后者active,则不需要切换网络管理程序,直接进行后续操作即可。

由于部分服务器存在默认的内网IPV6路由会与隧道冲突,此时可使用以下命令删除默认的IPV6路由

default_route=$(ip -6 route show | awk '/default via/{print $3}') && [ -n "$default_route" ] && ip -6 route del default via $default_route dev eth0

这里假设了你的客户端的服务器的默认网卡是eth0,你可以使用ip -6 route查看默认的路由并替换它,默认路由以default via开头,使用dev指定默认网卡,你只需要按照这个规则找到它即可

目前收集且支持的平台

tunnelbroker_net

结合一键开设带IPV6地址的容器的脚本,就能给每个容器附加来自he的IPV6地址了

缺点是地址比较黑/脏,cloudflare的cdn极有可能套不上,自行测试

  1. https://tunnelbroker.net/ 注册账户,并点击左边的 Create Regular Tunnel

1

  1. 红框处填写你的服务器的IPV4地址,选择物理距离近的连接点,比如机器在美国洛杉矶,就选美国西海岸的连接点,然后显示绿框提示,点Create Tunnel创建即可

2

3

4

  1. 等待出以下界面,点击Example Configurations然后选择对应的系统,比如LXD的宿主机那肯定就是Debian/Ubuntu了

5

6

  1. 框住的部分就是要修改的文件和需要复制的内容了

7

复制的时候不要带空行

  1. 转换格式后给你的网络配置文件附加IPV6的设置

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerNet,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改复制粘贴一下转换格式后的配置文件内容,然后执行此命令
+EOF

然后你可以使用cat /etc/network/interfaces查看配置文件是否正常写入了

  1. 如果上面都没问题,就需要启用网络接口即可
apt-get install net-tools iproute2 -y
+systemctl restart networking
  1. 然后你就可以测试IPV6网络是否已附加

执行ifconfig命令,这时应该有一个 he-ipv6 接口,类似下面这样:

8

或者执行:

curl ipv6.ip.sb

回传你绑定IPV6地址

  1. NAT VPS 的额外设置

IPv4 NAT VPS 除了前面提到的替换 IP 操作以外,可能还需要一些额外的设置,否则可能还是无法访问 IPv6 网络。

apt-get install ufw -y
+ufw allow 41

添加相关的路由规则

route -A inet6 add ::/0 dev he-ipv6
  1. 如果不需要该IPV6网络了,想要删除

删除 he-ipv6 网络接口配置(若没有删除重启后会自动启用),记得修改/etc/network/interfaces文件,删除之前红框添加的内容

然后重启服务器,就删除了

tunnelbroker_ch

类似上述的操作,先在 https://www.tunnelbroker.ch/ 注册一个账户先,注册后点击激活的邮件

然后就是填写你的服务器IPV4地址

创建后需要进入Config页面而不是详情页面

见到以下页面千万别使用,先刷新一下本页面,不要弹那个浅蓝色框后再停止刷新

记录以下页面的最后一个红框的内容,准备修改宿主机配置文件

页面的最后一个红框框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionTunnelBrokerCh,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式,等待页面刷新显示转换格式后的配置文件内容

然后用vim或者vi命令修改/etc/network/interfaces文件增加内容,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

ip4market_ru

类似上述的操作,先在 https://tb.ip4market.ru 注册一个账户先,注册邮箱得是非常见邮箱,电话可随便写不验证的,IP填上你要附加的宿主机的IPV4地址

然后就是过Recaptcha的人机验证,点击注册

邮箱会收到激活邮件,里面附带有你的密码,记住它

然后在首页进行登录

然后就会进入这个页面

按住右键,然后复制红框框住的四行内容,也就是

Server IPv4:
+Client IPv4
+Server IPv6
+Client IPv6

这四行内容,按ctrl+c复制或者右键复制

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择Optionip4market,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

netassist_ua

这个平台你在切换网络管理时务必使用ifupdown2而不是ifupdown2安装包,该平台使用sit协议,而sit协议需要在ifupdown2控制的环境中使用

类似上述的操作,先在 https://tb.netassist.ua/ 注册一个账户先,注册后点击激活的邮件,激活页面会有密码显示,记得记录

然后就是填写你的服务器IPV4地址,这个后面可以自己修改,先随便填一个都没问题

然后就到了这个页面了

a

第一个红框是你宿主机的IPV4地址需要填写的位置,要修改就修改那里,然后点change保存

第二个下拉红框选择Linux,然后点击show

b

会出现上面的内容,全选框住的部分复制下来,不要带空行

然后打开 https://ipv6tunnel.spiritlhl.top/ 选择OptionNetAssist,另一个下拉选择框选择你之前安装成功的包名,然后在输入框内粘贴你复制的内容

然后点击Covert转换格式

c

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

转移不同服务器之间的IPV6子网

相关仓库:https://github.com/oneclickvirt/6in4

该方法将提供一种方式,将A上的IPV6网段拆分一个子ipv6网段的出来,附加到B上使用

你需要在B所在的服务器上使用本套脚本给容器一键配置IPV6地址

功能

  • 自建sit/gre/ipip协议的IPv6隧道
  • 支持自定义要切分出来的IPV6子网大小,将自动计算出合适的CIDR格式的IPV6子网信息
  • 自动识别服务端的IPV6子网大小
  • 将自动设置隧道服务端并打印客户端需要执行的命令
  • 设置IPV6隧道的方法简单易懂,易于删除

环境准备

VPS(A)VPS(B)
一个IPV4地址(server_ipv4)一个IPV4地址(clinet_ipv4)
一个IPV6子网无IPV6地址
以下称之为服务端以下称之为客户端

使用方法

下载脚本

curl -L https://raw.githubusercontent.com/oneclickvirt/6in4/main/6in4.sh -o 6in4.sh && chmod +x 6in4.sh

执行命令

./6in4.sh client_ipv4 <mode_type> <subnet_size>
选项可选的选项1可选的选项2可选的选项3
<mode_type>gresitipip
<subnet_size>6480112

<mode_type>暂时只支持那三种协议,越靠前的越推荐,不填则默认为sit协议

<subnet_size>只要比原系统子网掩码大就行,且是8的倍数,不填则默认为80

记得client_ipv4替换为需要附加IPV6的机器的IPV4地址,执行完毕后会回传你需要在客户端执行的命令,详见执行后的说明即可

为防止忘记复制命令,命令本身也将写入到当前路径下的6in4.log文件中,可使用cat 6in4.log查询客户端需要执行的命令

复制下来的命令,务必在 https://ipv6tunnel.spiritlhl.top/ 中选择选项6in4后进行转换

然后就会自动刷新页面出现需要自己用vim或者vi命令修改/etc/network/interfaces文件增加的内容了,或者修改以下命令新增

tee -a /etc/network/interfaces <<EOF
+# 这里修改一下
+EOF

然后你就需要重启一下系统,或者执行

apt-get install net-tools iproute2 -y
+systemctl restart networking

保证环境无问题再进行别的操作了

检测服务端

systemctl status ndpresponder
ip addr show

检测客户端

ip addr show
curl ipv6.ip.sb

删除隧道

服务端

ip link set server-ipv6 down
+ip tunnel del server-ipv6

客户端

ip link set user-ipv6 down
+ip tunnel del user-ipv6

以上删除的方式只是临时删除,永久删除务必修改删除/etc/network/interfaces文件中你之前增加的内容

后言

实际上 https://tunnelbroker.net/ 支持申请/48大小的IPV6子网,只需要在

图片

这里进行申请,然后转换格式的时候将原先/64的IPV6地址改成/48的IPV6地址,你就能获得一个更大的IPV6子网了

使用WARP给宿主机添加IP出口(IPv4/IPv6)

好处

  • 宿主机安装,能使所有开启的机器都能够享受 Warp 的优势,而无需为每台机器单独进行设置,从而节省资源和简化管理。
  • 宿主机使用内核态 WireGuard,相比于用户态的 WireGuard-Go,实现能够提供更高效的 WireGuard 运行。

手动安装

1.安装WireGuard依赖

  • Debian 和 Ubuntu 系统
# 更新依赖库
+apt update -y
+
+# 安装 WireGuard 运行依赖
+apt install -y --no-install-recommends net-tools openresolv dnsutils
+
+# 安装 WireGuard 协议兼容的工具集合
+apt install -y --no-install-recommends wireguard-tools
  • CentOS 系
# 更新依赖库
+yum update -y
+
+# 安装额外包组件
+yum install -y epel-release 
+
+# 安装 WireGuard 运行依赖
+yum install -y net-tools
+
+# 安装 WireGuard 协议兼容的工具集合
+yum install -y wireguard-tools

2.获取warp账户信息

访问 https://warp.cloudflare.now.cc/?run=register&format=yaml,记录下 private_key, v6 2个值

image.png

3.修改配置文件

  • 创建并编辑 /etc/wireguard/warp.conf 文件,包含<>(尖括号)的部分一起替换掉,这只是为了看起来明显。

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口

[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 1.1.1.1, 1.0.0.1, 2606:4700:4700::1111, 2606:4700:4700::1001
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = ::/0
+Endpoint = 162.159.193.10:2408
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口
[Interface]
+PrivateKey = <替换 PrivateKey>
+Address = 172.16.0.2/32
+Address = <替换 Address v6 地址>/128
+DNS = 2606:4700:4700::1111, 2606:4700:4700::1001, 1.1.1.1, 1.0.0.1
+MTU = 1280
+
+[Peer]
+PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
+AllowedIPs = 0.0.0.0/0
+Endpoint = [2606:4700:d0::a29f:c101]:2408
  • 针对双栈没有必要,毕竟原生的网络出口都会比通过 Warp 中转要好

4.设置地址解析优先级

  • 针对 IPv4 only 的宿主机,Warp 只接管 IPv6 出口,设置优先使用原生网络的 IPv4 出口
# IPv4 优先
+grep -qE '^[ ]*precedence[ ]*::ffff:0:0/96[ ]*100' /etc/gai.conf || echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  • 针对 IPv6 only 的宿主机,Warp 只接管 IPv4 出口,设置优先使用原生网络的 IPv6 出口
# IPv6 优先,默认即为 IPv6 优先
+sed -i '/^precedence \:\:ffff\:0\:0/d;/^label 2002\:\:\/16/d' /etc/gai.conf

5.连接 Warp,并设置 systemd 进程守护

# 运行 wireguard 连接 Warp。如果这步卡死导致失联,后台重启宿主机即可解决
+wg-quick up warp
+
+# 查看 IPv4
+curl -A a https://api-ipv4.ip.sb/geoip
+
+# 查看 IPv6
+curl -A a https://api-ipv6.ip.sb/geoip
+
+# 测试成功后断开 Warp 连接
+wg-quick down warp
+
+# 重新连接并设置进程守护,以便重启后自动生效
+systemctl enable --now wg-quick@warp

自动安装和运行(fscarmen的一键脚本)

最后,介绍 fscarmen 的一键脚本。提到该脚本是一个方便的工具,可以简化配置过程。并自动处理最优 MTU, 最优 Endpoint 等进阶参数。

项目介绍: https://github.com/fscarmen/warp-sh

# 运动脚本
+wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh

image.png

+ \ No newline at end of file diff --git a/guide/lxd/lxd_extra_config.html b/guide/lxd/lxd_extra_config.html index b82a99125d..f20161cabe 100644 --- a/guide/lxd/lxd_extra_config.html +++ b/guide/lxd/lxd_extra_config.html @@ -5,37 +5,40 @@ 其他自定义配置 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为LXD创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
-ip6tables-legacy -t nat -F PREROUTING
-ip6tables-save > /etc/iptables/rules.v6
-netfilter-persistent save
-netfilter-persistent reload
-service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
-systemctl disable add-ipv6.service
-rm /etc/systemd/system/add-ipv6.service
-systemctl daemon-reload
-rm /usr/local/bin/add-ipv6.sh

一键安装开lxd宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

一键启用官方可视化操作的面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
sudo snap refresh lxd --channel=latest/stable
-snap set lxd ui.enable=true
-lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
-systemctl reload snap.lxd.daemon
-snap restart --reload lxd

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

一键安装宿主机第三方可视化操作的面板

  • (非必须,该面板只是为了方便可视化操作,没有也没问题)
  • 原作者仓库:跳转
shell
lxc config set core.https_address [::]
-lxc config set core.trust_password your_password
-snap install lxdmosaic

安装完毕后打开宿主机IP地址,按照提示设置admin的密码,其他一路默认就能使用面板了

- +
Skip to content

其他自定义配置

TIP

以下的配置安装会加重宿主机的负担,非必要不要安装

自动配置IPV6地址

  • (非必须,不使用的也没问题)
  • 该脚本仅适用于宿主机有给IPV6子网且是至少/112的,且宿主机绑定了子网的第一个IP宿主机的IPV6地址或IPV6的gateway
  • 自动为LXD创建的LXC容器配置IPV6地址
  • 已集成到buildone.sh中可使用变量控制且无需事先下载,该脚本可不手动使用,在使用buildone.sh时配置Y开启即可

下载脚本

国际

bash
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -o build_ipv6_network.sh && chmod +x build_ipv6_network.sh

自动为容器配置IPV6映射地址(默认不使用iptables进行映射)

bash
bash build_ipv6_network.sh 容器名称

映射完毕会打印信息

示例(给test容器自动配置IPV6地址,配置完成会写入一个test_v6的文件信息)

bash
bash build_ipv6_network.sh test

PS:增加ipv6处理过程中可选择是否使用ip6tables进行映射,默认不使用ip6tables方式进行映射而使用新增网络设备的方式进行映射

使用ip6tables进行映射

bash
bash build_ipv6_network.sh 容器名称 Y

若使用了ip6tables进行映射,则删除所有IPV6已映射的规则可用:

bash
ip6tables -t nat -F PREROUTING
+ip6tables-legacy -t nat -F PREROUTING
+ip6tables-save > /etc/iptables/rules.v6
+netfilter-persistent save
+netfilter-persistent reload
+service netfilter-persistent restart

卸载IPV6地址绑定的守护进程和对应的文件可用:

shell
systemctl stop add-ipv6.service
+systemctl disable add-ipv6.service
+rm /etc/systemd/system/add-ipv6.service
+systemctl daemon-reload
+rm /usr/local/bin/add-ipv6.sh

一键安装开lxd宿主机所需要的带vnstat环境的常用预配置环境

  • (非必须,该脚本仅仅是为了站点对接监控方便,不装的也没问题)

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/backend.sh -o backend.sh && chmod +x backend.sh && bash backend.sh

一键启用官方可视化操作的面板

  • (非必须,只是为了方便可视化操作,没有也没问题)
shell
sudo snap refresh lxd --channel=latest/stable
+snap set lxd ui.enable=true
+lxc config set core.https_address $(curl -sKL ipv4.ip.sb):8443
+systemctl reload snap.lxd.daemon
+snap restart --reload lxd

然后你可以在浏览器中输入

https://你的公网IPV4地址:8443

即可进入官方可视化操作面板,后续的操作配置按照UI提示操作即可

一键安装宿主机第三方可视化操作的面板

  • (非必须,该面板只是为了方便可视化操作,没有也没问题)
  • 原作者仓库:跳转
shell
lxc config set core.https_address [::]
+lxc config set core.trust_password your_password
+snap install lxdmosaic

安装完毕后打开宿主机IP地址,按照提示设置admin的密码,其他一路默认就能使用面板了

+ \ No newline at end of file diff --git a/guide/lxd/lxd_install.html b/guide/lxd/lxd_install.html index 61b5b4f1e0..e3b5fd7a38 100644 --- a/guide/lxd/lxd_install.html +++ b/guide/lxd/lxd_install.html @@ -3,29 +3,32 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXD

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

LXD主体安装

WARNING

如果是全新的服务器,务必保证apt updateapt install curl都无问题再执行本脚本。

  • 环境要求:Ubuntu 18+(推荐20.04以上),Debian 8+(推荐11以上)
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

shell
bash lxdinstall.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

WARNING

如果你需要在一台服务器上开启超过200个LXD容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

安装WEB控制面板

自定义 教程中有关于官方面板怎么启用的教程,但这里不选择使用官方的面板,因为官方面板为了安全性,牺牲了很多用户体验,这块使用

https://github.com/turtle0x1/LxdMosaic

的第三方面板

shell
sudo snap install lxdmosaic

直接进行一键安装,然后打开当前宿主机的https://<公网IP地址>/,强制访问,就能进入设置页面

lxd

lxd

lxd

这块如果你需要设置网站名字可以改改

lxd

聊胜于无只能说,没有RBAC权限控制进行分用户隔离

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
-apt install curl wget sudo dos2unix ufw jq -y
-ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装LXD

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

apt install snapd -y
-snap install lxd
-/snap/bin/lxd init

如果上面的命令中出现下面的错误

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

使用命令修补后再进行lxd的安装

snap install core

如果无异常,上面三行命令执行结果如下

图片

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

测试lxc有没有软连接上

lxc -h

如果报错则执行以下命令软连接lxc命令

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

连接后再测试lxc命令是否有报错找不到

- +
Skip to content

LXD

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

LXD主体安装

WARNING

如果是全新的服务器,务必保证apt updateapt install curl都无问题再执行本脚本。

  • 环境要求:Ubuntu 18+(推荐20.04以上),Debian 8+(推荐11以上)
  • 这里的虚拟内存是说要开的SWAP大小,存储池则是你所有要开的服务器占的盘的大小的总和
  • 环境安装过程后需要重启服务器以加载一些默认配置
  • 默认启用lxd的lxcfs相关配置,使得容器内查询容器信息变更为容器本身的信息而不是宿主机信息

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/lxdinstall.sh -o lxdinstall.sh && chmod +x lxdinstall.sh && bash lxdinstall.sh

shell
bash lxdinstall.sh

初始化配置的例子:

如果系统盘除去已占用空间还有18G硬盘空余,想开2G虚拟内存(2048MB的SWAP),15G的存储池,按照命令行的提示则依次输入204815

WARNING

如果你需要在一台服务器上开启超过200个LXD容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

安装WEB控制面板

自定义 教程中有关于官方面板怎么启用的教程,但这里不选择使用官方的面板,因为官方面板为了安全性,牺牲了很多用户体验,这块使用

https://github.com/turtle0x1/LxdMosaic

的第三方面板

shell
sudo snap install lxdmosaic

直接进行一键安装,然后打开当前宿主机的https://<公网IP地址>/,强制访问,就能进入设置页面

lxd

lxd

lxd

这块如果你需要设置网站名字可以改改

lxd

聊胜于无只能说,没有RBAC权限控制进行分用户隔离

手动安装(备选)

不推荐,只是为了一些奇葩环境一键脚本跑不动的时候进行安装

关闭防火墙

bash
apt update
+apt install curl wget sudo dos2unix ufw jq -y
+ufw disable

开设虚拟内存SWAP

内存看你开多少服务器,这里如果要开8个,换算需要2G内存,实际内存如果是512MB内存,还需要开1.5G,保守点开2G虚拟内存即可

执行下面命令,输入1,再输入2048,代表开2G虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/swap.sh -o swap.sh && chmod +x swap.sh && bash swap.sh

安装LXD

实际swap开的虚拟内存应该是实际内存的2倍,也就是开1G是合理的,上面我描述的情况属于超开了

apt install snapd -y
+snap install lxd
+/snap/bin/lxd init

如果上面的命令中出现下面的错误

(snap "lxd" assumes unsupported features: snapd2.39 (try to update snapd and refresh the core snap))

使用命令修补后再进行lxd的安装

snap install core

如果无异常,上面三行命令执行结果如下

图片

一般的选项回车默认即可

选择配置物理盘大小(提示默认最小1GB那个选项),一般我填空闲磁盘大小减去内存大小后乘以0.95并向下取整,这里我填了10GB

提示带auto的更新image的选项记得选no,避免更新占用系统

测试lxc有没有软连接上

lxc -h

如果报错则执行以下命令软连接lxc命令

bash
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

连接后再测试lxc命令是否有报错找不到

+ \ No newline at end of file diff --git a/guide/lxd/lxd_lxc.html b/guide/lxd/lxd_lxc.html index 29ea480f82..8e42bed747 100644 --- a/guide/lxd/lxd_lxc.html +++ b/guide/lxd/lxd_lxc.html @@ -5,46 +5,49 @@ LXC虚拟化 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXC虚拟化

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载开机脚本是非必须的,如果你使用过一键安装LXD的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian12,注意传入参数为系统名字+版本号,如:

  • debian12,debian13
  • ubuntu22,ubuntu24
  • centos8,centos9 (实际都是Stream版本)
  • alpine3.16,alpine3.17,alpine3.18,alpine3.19
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

需要进入容器内部则执行

lxc exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
lxc stop test
-lxc delete test
-rm -rf test
-rm -rf test_v6
-ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
-2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用LXD命令

查看所有

bash
lxc list

查看个例

bash
lxc info 服务器名字

启动个例

bash
lxc start 服务器名字

停止个例

bash
lxc stop 服务器名字

删除个例

bash
lxc delete -f 服务器名字

进入内部

bash
lxc exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
-sudo apt-get clean
-sudo find /var/log -type f -delete
-sudo find /var/tmp -type f -delete
-sudo find /tmp -type f -delete
-sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
-rm -rf /usr/local/bin/config.sh
-rm -rf /usr/local/bin/ssh_bash.sh
-rm -rf /usr/local/bin/check-dns.sh
-rm -rf /root/ssh_sh.sh
-rm -rf /root/config.sh
-rm -rf /root/ssh_bash.sh
-rm -rf /root/buildone.sh
-rm -rf /root/add_more.sh
-rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
-wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

- +
Skip to content

LXC虚拟化

单独生成一个NAT服务器

  • 只生成一个NAT服务器,可自定义限制所有内容

下载开机脚本是非必须的,如果你使用过一键安装LXD的命令,自动已下载对应的开机脚本,不需要重复下载该脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -o buildone.sh && chmod +x buildone.sh && dos2unix buildone.sh

使用方法

./buildone.sh 服务器名称 CPU核数 内存大小 硬盘大小 SSH端口 外网起端口 外网止端口 下载速度 上传速度 是否启用IPV6(Y or N) 系统(留空则为debian11)

CPU核数需要小于或等于宿主机的核数,内存大小以MB计算,硬盘大小以GB计算,下载速度上传速度以Mbit计算,是否启用IPV6不一定要填Y或者N,没有这个参数也行,留空默认不开启IPV6

如果外网起端口外网止端口都设置为0则不做区间外网端口映射了,只映射基础的SSH端口,注意不能为空,不进行映射需要设置为0

支持自定义服务器的系统,不填写留空时默认使用debian12,注意传入参数为系统名字+版本号,如:

  • debian12,debian13
  • ubuntu22,ubuntu24
  • centos8,centos9 (实际都是Stream版本)
  • alpine3.16,alpine3.17,alpine3.18,alpine3.19
  • 注意都是小写字母+数字的组合或仅小写字母,自行尝试,如果搜索无该系统则会自动退出脚本
  • 版本号可以带英文小数点,为了适配alpine的版本号已支持
  • 开不起来的可能是硬盘或内存不够大或者本身就不适配宿主机,自行尝试查看开不起来的报错
  • 目前使用的容器系统有三重筛选,优先级:自编译官方opsmaru
  • 自编译镜像完整的支持系统的列表:x86_64_fixed_images.txtarm64_fixed_images.txt

示例

以下为开设的示例服务器的信息:

属性
服务器名字test
SSH登录的用户名root
SSH登录的密码随机生成
CPU核数1
内存大小256MB
磁盘大小2G
内外网映射端口一致的区间20002到20025
上传带宽500Mbit
下载带宽500Mbit
自动设置外网IPV6地址N
系统debian12
./buildone.sh test 1 256 2 20001 20002 20025 500 500 N debian12

需要进入容器内部则执行

lxc exec test /bin/bash

退出则输入exit回车即可

需要查看信息则执行

shell
cat 服务器名字

比如查询示例的信息就是

shell
cat test

如果已通过以上方法生成过服务器,还需要批量生成服务器,可使用自定义批量生成版本的脚本,但注意先删除测试服务器再进行批量生成服务器

删除测试服务器

shell
lxc stop test
+lxc delete test
+rm -rf test
+rm -rf test_v6
+ls

普通版本批量生成

开出的服务器配置:

  • 1核256MB内存1GB硬盘限速300Mbit带宽
  • 带1个SSH端口,24个外网端口
  • 默认内存和硬盘大小

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

执行下面命令加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/init.sh -o init.sh && chmod +x init.sh && dos2unix init.sh

下面命令为开服务器名字前缀为tj10个服务器

shell
./init.sh tj 10

有时候init.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

纯SSH端口版本批量生成

开出的服务器配置:

  • 1核128MB内存300MB硬盘限速300Mbit带宽
  • 只有一个SSH端口
  • 无法挂载warp

TIP

lxc若命令无问题,执行初始化开服务器,这一步最好放screen中后台挂起执行,开服务器时长与你开几个和宿主机配置相关

加载开机脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/least.sh -o least.sh && chmod +x least.sh && dos2unix least.sh

下列命令最后一行为开服务器名字前缀为tj10个服务器

shell
./least.sh tj 10

有时候least.sh的运行路径有问题,此时建议前面加上sudo强制根目录执行

自定义批量生成版本

  • 可自定义内存和硬盘大小
  • 有执行过上面的手动批量生成过也没问题,配置是继承的不覆盖

如果需要多次批量生成服务器,可使用

国际

curl -L https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/lxd/raw/main/scripts/add_more.sh -o add_more.sh && chmod +x add_more.sh && bash add_more.sh

可多次运行批量生成服务器,且继承前面已生成的部分在后面添加,可自定义内存和硬盘大小

查看已批量开设的信息

开完服务器后,具体信息会生成在当前目录下的log文件中,格式如下

shell
1号服务器名称 密码 ssh端口 外网端口起始 外网端口终止
+2号服务器名称 密码 ssh端口 外网端口起始 外网端口终止

如果想要查看,只需在当前目录执行以下命令打印log文件即可

shell
cat log

WARNING

不要拿该脚本开出的服务器当生产环境,LXC虚拟化不支持换内核,dd,开启bbr等操作

部分常用LXD命令

查看所有

bash
lxc list

查看个例

bash
lxc info 服务器名字

启动个例

bash
lxc start 服务器名字

停止个例

bash
lxc stop 服务器名字

删除个例

bash
lxc delete -f 服务器名字

进入内部

bash
lxc exec 服务器名字 /bin/bash

TIP

在alpine中不用/bin/bash而是用/bin/sh,常规的系统都是/bin/bash

退出则输入exit回车即可

删除所有LXC容器

bash
lxc list -c n --format csv | xargs -I {} lxc delete -f {}

在容器内执行删除无用日志

bash
sudo apt-get autoremove
+sudo apt-get clean
+sudo find /var/log -type f -delete
+sudo find /var/tmp -type f -delete
+sudo find /tmp -type f -delete
+sudo find /var/cache/apt/archives -type f -delete

更新上述所有一键脚本的相关命令

删除原始配置脚本

bash
rm -rf /usr/local/bin/ssh_sh.sh
+rm -rf /usr/local/bin/config.sh
+rm -rf /usr/local/bin/ssh_bash.sh
+rm -rf /usr/local/bin/check-dns.sh
+rm -rf /root/ssh_sh.sh
+rm -rf /root/config.sh
+rm -rf /root/ssh_bash.sh
+rm -rf /root/buildone.sh
+rm -rf /root/add_more.sh
+rm -rf /root/build_ipv6_network.sh

下载回新版本的相关配置脚本

bash
wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/check-dns.sh -O /usr/local/bin/check-dns.sh && chmod +x /usr/local/bin/check-dns.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/config.sh -O /usr/local/bin/config.sh && chmod +x /usr/local/bin/config.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_bash.sh -O /usr/local/bin/ssh_bash.sh && chmod +x /usr/local/bin/ssh_bash.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/ssh_sh.sh -O /usr/local/bin/ssh_sh.sh && chmod +x /usr/local/bin/ssh_sh.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/build_ipv6_network.sh -O /root/build_ipv6_network.sh && chmod +x /root/build_ipv6_network.sh
+wget https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/buildone.sh -O /root/buildone.sh && chmod +x /root/buildone.sh

其他一键脚本自己对应下载回来就行了

+ \ No newline at end of file diff --git a/guide/lxd/lxd_precheck.html b/guide/lxd/lxd_precheck.html index af34b0d75d..f32338195d 100644 --- a/guide/lxd/lxd_precheck.html +++ b/guide/lxd/lxd_precheck.html @@ -5,22 +5,25 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/lxd

要求

硬件要求:

  • 系统:Debian 8+, Ubuntu 18+(推荐20.04)
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu20,Ubuntu别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加清华镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
- +
Skip to content

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果你的宿主机本身没有IPV6的子网又想给容器分配IPV6地址,那么请先查看LXD模块中的自定义分区中的给宿主机附加免费的IPV6地址段的内容,给宿主机附加上IPV6子网后再进行环境安装

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/lxd

要求

硬件要求:

  • 系统:Debian 8+, Ubuntu 18+(推荐20.04)
  • 虚拟化:推荐KVM、VMWARE虚拟化
  • 内存:内存至少512MB
  • 硬盘:硬盘(系统盘)至少10G
  • 网络:独立的IPV4地址,IPV6可有可无,带宽能下载脚本就行,网络能连接Github的raw页面就行

PS: 如果硬件非常好资源很多,可使用PVE批量开KVM虚拟化的虚拟机 跳转

PS: 如果硬件资源更烂,虚拟化不支持,可使用docker版本的,适配面更广 跳转

项目特点

  • 本套脚本开发使用的Ubuntu20,Ubuntu别的长期维护版本应该也没问题,某个存储类型无法使用时自动切换

  • 已设置同时进行TCP和UDP转发,除了SSH端口其他的映射内网外网端口一致

  • 已设置支持开出的LXC容器进行docker嵌套虚拟,默认普通版本和纯探针版本使用debian11系统

  • 已设置默认启用lxcfs,使得在容器内的查询资源时使用的是配置的视图而不是宿主机的视图

  • 已屏蔽容器内可能用于滥用的工具包和IPV4网络的TCP/UDP协议的端口( 3389 8888 54321 65432 ),以防止容器被用于扫描和爆破,且可外置进程检查有问题自动停机

  • 已支持一键为LXC容器配置IPV6地址(前提是宿主机有IPV6子网,无IPV6地址则不配置),自动适配子网大小

  • 已增加清华镜像源,如果官方镜像丢失时,将使用镜像源下载容器镜像

  • 保证你要开的盘为默认的系统盘(sda或者sda1)而不是挂载的盘(sdb之类的),不确定的使用fdisk -ldf查看

  • 挂载其他盘的详看 其他说明

  • 一键脚本支持自定义限制所有内容,普通版本支持多次运行批量生成不覆盖先前生成的配置

检测环境

使用后续脚本的务必执行本命令检测宿主机是否符合要求

国际

bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)

国内

bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/lxd/main/scripts/pre_check.sh)
+ \ No newline at end of file diff --git a/guide/lxd/lxd_qa.html b/guide/lxd/lxd_qa.html index 1434e24feb..38af3c7b56 100644 --- a/guide/lxd/lxd_qa.html +++ b/guide/lxd/lxd_qa.html @@ -5,23 +5,26 @@ 解惑 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

解惑

如果LXD安装后lxc命令显示找不到怎么办

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
-export PATH=$PATH:/snap/bin

执行这个命令后尝试

lxc -h

看看lxc命令是否已修复

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销

- +
Skip to content

解惑

如果LXD安装后lxc命令显示找不到怎么办

! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >> /root/.bashrc && source /root/.bashrc
+export PATH=$PATH:/snap/bin

执行这个命令后尝试

lxc -h

看看lxc命令是否已修复

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

目前已验证可开带独立IPV6地址容器的VPS商家

kuroit 中的 美国凤凰城 regular

datalix 中的 德国AMD 促销

+ \ No newline at end of file diff --git a/guide/lxd/lxd_thanks.html b/guide/lxd/lxd_thanks.html index b33135d6a2..73a932a7b5 100644 --- a/guide/lxd/lxd_thanks.html +++ b/guide/lxd/lxd_thanks.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/guide/lxd/lxd_windows.html b/guide/lxd/lxd_windows.html index 25365d3598..83f8d27771 100644 --- a/guide/lxd/lxd_windows.html +++ b/guide/lxd/lxd_windows.html @@ -5,39 +5,42 @@ 在 LXD 中运行 Windows 虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

在 LXD 中运行 Windows 虚拟机

检查 lxd 驱动

确保lxc info输出中含有qemu,否则无法创建VM:

shell
lxc info | grep -i driver:

若显示只有lxc,则lxd的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root目录下按顺序执行以下命令:

shell
apt update
-apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
-snap install lxd-imagebuilder --classic --edge
-# 重启加载一些配置
-reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
-lxd-imagebuilder repack-windows \
-  --windows-arch=amd64 \
-  win.iso \
-  win.lxd.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screen或tmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
lxc init winvm --vm --empty
-lxc config device override winvm root size=30GiB
-lxc config set winvm limits.cpu=3 limits.memory=5GiB
-lxc config device add winvm vtpm tpm path=/dev/tpm0
-lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
-apt install -y spice-html5 websockify lsof

启动虚拟机

shell
lxc start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
-nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
-echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示三个立方体的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用lxc list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
lxc stop winvm
-lxc config device remove winvm install
-lxc start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,lxd将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后lxc delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
lxc config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

- +
Skip to content

在 LXD 中运行 Windows 虚拟机

检查 lxd 驱动

确保lxc info输出中含有qemu,否则无法创建VM:

shell
lxc info | grep -i driver:

若显示只有lxc,则lxd的驱动不支持开设虚拟机,不需要看后续的教程了。

准备环境和修补镜像

/root目录下按顺序执行以下命令:

shell
apt update
+apt install -y snapd libguestfs-tools wimtools rsync libhivex-bin libwin-hivex-perl genisoimage || apt install -y mkisofs
+snap install lxd-imagebuilder --classic --edge
+# 重启加载一些配置
+reboot

下载镜像并进行修补,如果你使用的是别的镜像,自行替换下载链接(不需要下载自带virtio的镜像,原始的镜像就够了)

自行下载Windows镜像的地址:https://down.idc.wiki/ISOS/Windows/

下面的指南将以windows2019作为示例进行

shell
wget https://down.idc.wiki/ISOS/Windows/Server%202019/cn_windows_server_2019_updated_july_2020_x64_dvd_2c9b67da.iso -O win.iso
+lxd-imagebuilder repack-windows \
+  --windows-arch=amd64 \
+  win.iso \
+  win.lxd.iso

修补时长取决于程序何时添加完毕启动所需的驱动(未完毕时会一个个添加)。

有的耗时短有的耗时长,最长可能超过10~30分钟,建议在screen或tmux中挂起执行

修补完毕后可删除原始的镜像:

shell
rm -f win.iso

创建虚拟机并挂载安装ISO

这里我使用的配置是3核5G内存30G硬盘,如果使用的是windows10等更新版本的镜像,至少需要4核6G内存40G硬盘。

建议使用比我现在设置的资源更多的CPU和内存(主要是内存),避免系统卡到崩溃。

如果内存不够用,建议查看本指南的其他实用项目中的添加SWAP项目,自行添加更多虚拟内存。

shell
lxc init winvm --vm --empty
+lxc config device override winvm root size=30GiB
+lxc config set winvm limits.cpu=3 limits.memory=5GiB
+lxc config device add winvm vtpm tpm path=/dev/tpm0
+lxc config device add winvm install disk source=/root/win.lxd.iso boot.priority=10

启动虚拟机并通过浏览器远程访问桌面

安装浏览器访问所需组件

shell
apt update
+apt install -y spice-html5 websockify lsof

启动虚拟机

shell
lxc start winvm

无问题后启动远程访问的组件

shell
SERVER_IP=$(hostname -I | awk '{print $1}')
+nohup websockify --web /usr/share/spice-html5 6080 --unix-target=/var/snap/lxd/common/lxd/logs/winvm/qemu.spice > /var/log/websockify-winvm.log 2>&1 &
+echo "SPICE HTML5 console on http://${SERVER_IP}:6080/spice_auto.html"

浏览器打开输出提示的地址

首次启动需要按浏览器页面左上角的Ctrl+Alt+Delete按钮,重启后在默认的界面按照提示,按回车等待5~10分钟才会正式装载ISO进行实际的安装

最终会显示三个立方体的图标,这个图标在这里转圈圈需要至少2分钟,请耐心等待。

转圈圈完毕就会进入正常的Win虚拟机安装流程,类比PVE的操作即可。

这里硬盘不可选中,选择在左下角查看黄色的提示,然后按照提示将脱机的硬盘联机点确认按钮,就可以选中硬盘了。

安装完成后,虚拟机会自动重新启动几次更新网络,spice的网页端显示进入用户设置界面,同时后台可使用lxc list查看到网络被自动附加。

设置完用户进入系统登录页面后,执行下述命令关闭/退出Windows,然后移除 ISO 设备,保证下次从硬盘启动,然后再次启动虚拟机

shell
lxc stop winvm
+lxc config device remove winvm install
+lxc start winvm

启动后可见如下图(测试访问一个网站)

无需自行进行网络配置,lxd将自动分配IPV4地址和连接网络

删除远程组件重新启动浏览器映射

如果发现资源没给够等原因需要删虚拟机重新开设,那么需要使用pkill -f websockify终止所有的spice信号转发,然后lxc delete -f winvm强行删除虚拟机。

shell
lsof -i :6080

查询对应端口的PID号是否还存在,确保已完全停止(如果你有多个虚拟机的信号转发,那么最好不要用pkill删除所有,用kill -9删除对应端口的PID即可)。

如果首次启动没过几分钟就崩溃停机了

需要添加CPU直通

shell
lxc config set winvm raw.qemu -- "-cpu host"

再次启动虚拟机即可

缺点

前端无权限校验,没法设置用户密码

如果需要前端鉴权,那么得使用Guacamole添加一些设置来实现,这里就不赘述了

虚拟机这块没有成型的一些交互面板和适配,spice古老了(虽然有网页端的spice客户端),官方的面板又不支持rbac使用用户名密码,只能通过证书使用

+ \ No newline at end of file diff --git a/guide/pve/images/readme.html b/guide/pve/images/readme.html index cf5bffb401..efe8a7ba7b 100644 --- a/guide/pve/images/readme.html +++ b/guide/pve/images/readme.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + - - + + \ No newline at end of file diff --git a/guide/pve/pve_android.html b/guide/pve/pve_android.html index 9c95ff8897..00a8b649f0 100644 --- a/guide/pve/pve_android.html +++ b/guide/pve/pve_android.html @@ -5,22 +5,25 @@ Android 虚拟机 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Android 虚拟机

安卓系统镜像下载

Android系统版本9及以前的镜像下载地址:

国际

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

国内

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Android系统版本10及以后的新镜像下载地址:

https://blissos.org/index.html#download

虚拟机开设

以安卓版本9及以前的镜像开设Android虚拟机

本指南以

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

作为示例进行演示

1

模板设置

开设VMID为100的虚拟机选择对应的存储盘

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

Graphic card选择Vmware compatible,其他选项选择默认如图所示

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面

9

系统安装

进入引导后,选择Installation开头的选项

10

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了

11

选择不使用GPT格式

12

显示空白盘后,选择New

13

选择分区类型Primary

14

然后会提示划分多大的空间,默认回车就行,使用全部的空间

15

然后是选择Flags,移动到Bootable后,按回车,直到Flags下方显示Boot

16

然后移动到Write,回车,进行写入

17

这时候会让你确认是否继续,输入yes后回车继续

18

一段进度条跑过后,回到了最初的菜单,选择Quit退出菜单,一切准备就绪了

19

然后这时候回到了UI界面,使用前面初始化好的盘,选择OK按钮回车

20

文件系统按方向键选择ext4类型,选择OK按钮回车

21

确认进行格式化,选择Yes按钮回车

22

确认GRUB引导安装,选择OK按钮回车

23

确认文件系统可读写,选择OK按钮回车

24

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车

25

然后一段时间后进入安卓LOGO界面

26

镜像移除

然后会进入一段黑屏,大概3~5分钟后仍然黑屏的话,宿主机执行qm stop 100,然后开始移除镜像文件

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

ar

然后宿主机再执行qm start 100,然后应该就会进入安卓系统的初始化界面了

系统初始化

初始化界面选择语言,然后点击确定按钮

27

此时回尝试连接WIFI,由于本项目安装的PVE是完全的静态网络配置,直接跳过,稍后再进行设置

31

点击下一步按钮确认设置时间

32

点击取消屏幕保护,确认仍然跳过

33

然后一段时间黑屏后,会出现主屏幕应用的选择,如果等待3~5分钟这个界面仍然没有出现,那么像之前那样重启虚拟机,再进入VNC应该就会显示了

选择Quickstep

34

网络设置

进入桌面,此时需要开始设置网络,左上角点击设置图标

35

出现下拉框,点击按住下拉

36

点击齿轮按钮

37

进入网络和互联网设置

38

左键双击WIFI

39

修改目前识别到的VirtWIFI,右键点击出现选择框后,点击修改网络

40

出现高级选项,点击打开隐藏的选项

41

如图进行对应的网络设置

IP地址 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码 24

默认网关 172.16.1.1

DNS 8.8.8.8144.144.144.144

然后点击保存按钮

42

此时出来后可能仍然未应用设置,点击关闭WIFI后,再启用WIFI,应该就会显示已连接

43

然后退出到主界面,点击谷歌浏览器,尝试打开一个网页

44

可以看到打开本指南的网址无问题,证明网络已联通

45

以安卓版本10及以后的新镜像开设Android虚拟机

本指南以

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

作为示例进行演示

1

模板设置

宿主机需要先执行以下命令安装图形环境依赖

shell
apt install libgl1 libegl1 -y

然后开始创建虚拟机,点击右上角的Create VM按钮,填写VMIDNameResource Pool

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

如果宿主机本身携带有GPU,那么Graphic card选择VirGL GPU

如果宿主机本身不携带GPU,那么Graphic card选择VirtIOVmware compatible

Machine选择q35BIOS选择OVMF (UEFI)启动,EFI Storage选择local

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面。

系统安装

进入引导后,选择Installation结尾的选项

9

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了。

10

选择不使用GPT格式,依然使用cfdisk格式。

11

显示格式选择框,选择gpt

12

显示空白盘后,选择New

13

因为要划分EFI分区,这个盘需要修改大小,不能使用默认大小,数字改成1就行,分配1G硬盘,然后按回车。

14

然后回到了菜单栏,按方向键选择Type,然后回车,给分区选择格式类型

15

按方向键选择第一个选项EFI System,然后回车

16

此时回到菜单栏,页面上半部分就能看到具体的分区大小和格式

17

然后按下方向键,选择下一行空白的分区

18

菜单栏选择New,然后回车

19

这块需要填写分区大小,此时对照右上角选中的空白分区大小一致即可,然后回车。

20

回到菜单栏,选择Write,回车,写入分区。

21

会提示你输入yes进行确认,输入后回车。

22

然后一段进度条跑过,应该会回到菜单栏,选择Quit退出菜单,一切准备就绪了

23

然后这时候回到了UI界面,使用前面初始化好的1GB大小的盘,选择OK按钮回车。

24

文件系统按方向键选择fat32类型,选择OK按钮回车

25

确认不修改名字,选择OK按钮回车

26

确认进行格式化,选择Yes按钮回车

27

然后回到最初的UI栏,选择第二块不是1GB大小的分区,选择OK按钮回车

28

文件系统按方向键选择ext4类型,选择OK按钮回车

29

确认不修改名字,选择OK按钮回车

30

确认进行格式化,选择Yes按钮回车

31

默认不使用额外空间更新,选择No按钮回车

32

确认GRUB2 EFI BootLoader,选择OK按钮回车

33

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车。

34

系统初始化

然后一段时间后进入LOGO界面。

35

再过一段时间,应该就会进入初始的安卓界面了,能看到弹窗和时间,按住左键上划

36

会出现主屏幕应用的选择,选择Quickstep

如果等待3~5分钟这个界面仍然没有出现,那么就重启虚拟机,再进入VNC应该就会显示了

37

镜像移除

出现了安卓的界面后,宿主机执行qm stop 100,然后开始移除镜像文件。

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

br

然后宿主机再执行qm start 100,然后应该就会进入系统的初始界面了。

网络设置

进入桌面,此时需要开始设置网络,图示位置按住左键,上划

38

弹出一堆应用,在里面找到那个叫做Bliss Ethernet Manager的应用,点击并打开

39

IP Assignment点击打开,选择Static类型,点击OK按钮确认

40

IP Address点击打开,填入172.16.1.xxx/24(xxx我写的100,因为这里我的虚拟机VMID是100方便区分),点击OK按钮确认

41

Gateway Address点击打开,填入172.16.1.1,点击OK按钮确认

42

DNS Address点击打开,填入8.8.8.8,点击OK按钮确认

43

然后在应用界面中,点击Interface UpRefresh,然后键盘按exit键退出程序

44

主界面中打开浏览器,验证网络是否畅通

45

可以看到打开本指南无问题,网络畅通

46

- +
Skip to content

Android 虚拟机

安卓系统镜像下载

Android系统版本9及以前的镜像下载地址:

国际

https://www.fosshub.com/Android-x86.html

https://sourceforge.net/projects/android-x86/files/

国内

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/

Android系统版本10及以后的新镜像下载地址:

https://blissos.org/index.html#download

虚拟机开设

以安卓版本9及以前的镜像开设Android虚拟机

本指南以

https://mirrors.tuna.tsinghua.edu.cn/osdn/android-x86/71931/android-x86_64-9.0-rc2.iso

作为示例进行演示

1

模板设置

开设VMID为100的虚拟机选择对应的存储盘

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

Graphic card选择Vmware compatible,其他选项选择默认如图所示

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面

9

系统安装

进入引导后,选择Installation开头的选项

10

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了

11

选择不使用GPT格式

12

显示空白盘后,选择New

13

选择分区类型Primary

14

然后会提示划分多大的空间,默认回车就行,使用全部的空间

15

然后是选择Flags,移动到Bootable后,按回车,直到Flags下方显示Boot

16

然后移动到Write,回车,进行写入

17

这时候会让你确认是否继续,输入yes后回车继续

18

一段进度条跑过后,回到了最初的菜单,选择Quit退出菜单,一切准备就绪了

19

然后这时候回到了UI界面,使用前面初始化好的盘,选择OK按钮回车

20

文件系统按方向键选择ext4类型,选择OK按钮回车

21

确认进行格式化,选择Yes按钮回车

22

确认GRUB引导安装,选择OK按钮回车

23

确认文件系统可读写,选择OK按钮回车

24

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车

25

然后一段时间后进入安卓LOGO界面

26

镜像移除

然后会进入一段黑屏,大概3~5分钟后仍然黑屏的话,宿主机执行qm stop 100,然后开始移除镜像文件

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

ar

然后宿主机再执行qm start 100,然后应该就会进入安卓系统的初始化界面了

系统初始化

初始化界面选择语言,然后点击确定按钮

27

此时回尝试连接WIFI,由于本项目安装的PVE是完全的静态网络配置,直接跳过,稍后再进行设置

31

点击下一步按钮确认设置时间

32

点击取消屏幕保护,确认仍然跳过

33

然后一段时间黑屏后,会出现主屏幕应用的选择,如果等待3~5分钟这个界面仍然没有出现,那么像之前那样重启虚拟机,再进入VNC应该就会显示了

选择Quickstep

34

网络设置

进入桌面,此时需要开始设置网络,左上角点击设置图标

35

出现下拉框,点击按住下拉

36

点击齿轮按钮

37

进入网络和互联网设置

38

左键双击WIFI

39

修改目前识别到的VirtWIFI,右键点击出现选择框后,点击修改网络

40

出现高级选项,点击打开隐藏的选项

41

如图进行对应的网络设置

IP地址 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码 24

默认网关 172.16.1.1

DNS 8.8.8.8144.144.144.144

然后点击保存按钮

42

此时出来后可能仍然未应用设置,点击关闭WIFI后,再启用WIFI,应该就会显示已连接

43

然后退出到主界面,点击谷歌浏览器,尝试打开一个网页

44

可以看到打开本指南的网址无问题,证明网络已联通

45

以安卓版本10及以后的新镜像开设Android虚拟机

本指南以

https://psychz.dl.sourceforge.net/project/blissos-x86/Official/BlissOS15/Gapps/Generic/Bliss-v15.9.2-x86_64-OFFICIAL-gapps-20241012.iso?viasf=1

作为示例进行演示

1

模板设置

宿主机需要先执行以下命令安装图形环境依赖

shell
apt install libgl1 libegl1 -y

然后开始创建虚拟机,点击右上角的Create VM按钮,填写VMIDNameResource Pool

2

选择安卓镜像,然后Type选择LinuxVersion选择含2.6版本的选项

3

如果宿主机本身携带有GPU,那么Graphic card选择VirGL GPU

如果宿主机本身不携带GPU,那么Graphic card选择VirtIOVmware compatible

Machine选择q35BIOS选择OVMF (UEFI)启动,EFI Storage选择local

4

磁盘格式选择SATA,具体需要分配多大的磁盘自选,推荐至少30G

5

CPU数量至少2核

如果你的宿主机支持嵌套虚拟化,CPU的类型请选择host(经验证无问题)

如果你的宿主机不支持嵌套虚拟化,CPU的类型请选择qemu64,同时在模板设置成功后,需要在Options中点击KVM hardware virtualization取消勾选后再启动虚拟机(不保证后面系统初始化无问题)

6

内存至少4G内存,填写至少4096

7

绑定的网桥选择vmbr1Model选择VirtIO (paravirtualized),取消Firewall的勾选

8

后续点击continue按钮后,模板成功创建出来,需要手动点击启动并进入VNC界面。

系统安装

进入引导后,选择Installation结尾的选项

9

然后需要创建分区写入,这块如果选择不了的话按键盘按钮c,就能选中了。

10

选择不使用GPT格式,依然使用cfdisk格式。

11

显示格式选择框,选择gpt

12

显示空白盘后,选择New

13

因为要划分EFI分区,这个盘需要修改大小,不能使用默认大小,数字改成1就行,分配1G硬盘,然后按回车。

14

然后回到了菜单栏,按方向键选择Type,然后回车,给分区选择格式类型

15

按方向键选择第一个选项EFI System,然后回车

16

此时回到菜单栏,页面上半部分就能看到具体的分区大小和格式

17

然后按下方向键,选择下一行空白的分区

18

菜单栏选择New,然后回车

19

这块需要填写分区大小,此时对照右上角选中的空白分区大小一致即可,然后回车。

20

回到菜单栏,选择Write,回车,写入分区。

21

会提示你输入yes进行确认,输入后回车。

22

然后一段进度条跑过,应该会回到菜单栏,选择Quit退出菜单,一切准备就绪了

23

然后这时候回到了UI界面,使用前面初始化好的1GB大小的盘,选择OK按钮回车。

24

文件系统按方向键选择fat32类型,选择OK按钮回车

25

确认不修改名字,选择OK按钮回车

26

确认进行格式化,选择Yes按钮回车

27

然后回到最初的UI栏,选择第二块不是1GB大小的分区,选择OK按钮回车

28

文件系统按方向键选择ext4类型,选择OK按钮回车

29

确认不修改名字,选择OK按钮回车

30

确认进行格式化,选择Yes按钮回车

31

默认不使用额外空间更新,选择No按钮回车

32

确认GRUB2 EFI BootLoader,选择OK按钮回车

33

跑了一段时间进度条后,显示安装成功,此时选择Reboot,选择OK按钮回车。

34

系统初始化

然后一段时间后进入LOGO界面。

35

再过一段时间,应该就会进入初始的安卓界面了,能看到弹窗和时间,按住左键上划

36

会出现主屏幕应用的选择,选择Quickstep

如果等待3~5分钟这个界面仍然没有出现,那么就重启虚拟机,再进入VNC应该就会显示了

37

镜像移除

出现了安卓的界面后,宿主机执行qm stop 100,然后开始移除镜像文件。

移除已经按照完毕的ISO文件,在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]

br

然后宿主机再执行qm start 100,然后应该就会进入系统的初始界面了。

网络设置

进入桌面,此时需要开始设置网络,图示位置按住左键,上划

38

弹出一堆应用,在里面找到那个叫做Bliss Ethernet Manager的应用,点击并打开

39

IP Assignment点击打开,选择Static类型,点击OK按钮确认

40

IP Address点击打开,填入172.16.1.xxx/24(xxx我写的100,因为这里我的虚拟机VMID是100方便区分),点击OK按钮确认

41

Gateway Address点击打开,填入172.16.1.1,点击OK按钮确认

42

DNS Address点击打开,填入8.8.8.8,点击OK按钮确认

43

然后在应用界面中,点击Interface UpRefresh,然后键盘按exit键退出程序

44

主界面中打开浏览器,验证网络是否畅通

45

可以看到打开本指南无问题,网络畅通

46

+ \ No newline at end of file diff --git a/guide/pve/pve_custom.html b/guide/pve/pve_custom.html index ad009b2afb..3efc15c00f 100644 --- a/guide/pve/pve_custom.html +++ b/guide/pve/pve_custom.html @@ -5,51 +5,54 @@ 自定义分区 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

自定义分区

在非Debian系统上安装 Proxmox VE 7

本机硬件配置的最低要求同先前正常安装的要求一致

需要先安装docker

curl -sSL https://get.docker.com/ | sh
-curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
-chmod +x /usr/local/bin/docker-compose
-docker-compose --version

然后使用uname -m查询架构,使用对应架构的命令

开设出的PVE面板信息为:

登录用户名和密码都是root,登录后务必使用web的SSH更改密码以免被爆破

用宿主机SSH时务必登录对应https://IPV4地址:8006在web面板上使用SSH,不要使用宿主机的22端口操控PVE

因为web面板上的SSH是在Docker内的,所以不支持后续的一键配置,请自行配置网关等进行使用

X86架构

bash
docker run -idt --network host \
---privileged \
---name pve \
---add-host pve:10.13.14.101 \
---hostname pve \
-spiritlhl/pve:7_x86_64

ARM架构

bash
docker run -idt --network host \
---privileged \
---name pve \
---add-host pve:10.13.14.101 \
---hostname pve \
-spiritlhl/pve:7_aarch64

开设出的面板实际是开设在容器内的,但网络已使用host模式,PVE的端口约等于就使用的宿主机的端口

但这里登录的用户名和密码就变成了rootroot,如需修改请docker exec -it pve /bin/bash进入后修改root的密码,然后按ctrl键和A+D退出。

有许多错误需要修复,欢迎PR解决问题,实测在Ubuntu系统的宿主机上安装Proxmox VE的面板成功,解决了通过网络安装Proxmox VE只能使用Debian系统做宿主机的问题

在低配置系统中优化Proxmox-VE的内存占用

以下优化可以减少至少400M内存左右的占用,部分机器能减少6GB以上,实际减少多少内存占用自行测试

减少max_workers数量

执行下述命令查询

cd /usr/share/perl5/PVE/Service
-grep 'max_workers => 3' *

可见

pvedaemon.pm:    max_workers => 3,
-pveproxy.pm:    max_workers => 3,
-spiceproxy.pm:    max_workers => 3, # todo: do we need more?

默认的max_workers是3,可以修改对应的文件,最低max_workers可为1,可使用如下命令进行修改

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

停用HA服务

集群(多节点)可以使用HA服务,如果是单节点,或者没有HA使用的需求,可以执行下述命令禁用

systemctl stop pve-ha-lrm.service 
-systemctl stop pve-ha-crm.service 
-systemctl disable pve-ha-lrm.service 
-systemctl disable pve-ha-crm.service

停用防火墙服务

可执行下述命令停用服务

systemctl stop pve-firewall.service 
-systemctl disable pve-firewall.service

停用调度服务

如果不需要计划任务,如备份、同步之类的任务,可执行下述命令停用服务

systemctl stop pvescheduler.service
-systemctl disable pvescheduler.service

停用Spiceproxy服务

如果不需要使用Spice进行虚拟机/容器链接(arm下暂不支持Spice),可执行下述命令停用服务

systemctl stop spiceproxy.service 
-systemctl disable spiceproxy.service

使用定时任务删除内存缓存

清理不同类型的缓存以及对文件系统进行TRIM操作

shell
TEMP_CRON=$(mktemp)
-sudo crontab -l > $TEMP_CRON
-echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
-echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
-sudo crontab $TEMP_CRON
-rm $TEMP_CRON

上面的命令需要宿主机本身有sudocrontab命令才可使用。

在开设出的NAT的KVM虚拟机上自行映射公网端口

使用nanovim命令修改文件增加端口映射:

/etc/iptables/rules.v4

例如我有一台内网IP为172.16.1.152的KVM虚拟机,虚拟机内已经开设MYSQL监听了3306,我需要使用tcp协议映射出来到宿主机IP上的33306端口上进行使用,那么需要在上面的那个文件中的COMMIT行以上增加如下行

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

保存文件退出文件编辑后执行

service netfilter-persistent restart

重载端口映射

此时在宿主机上执行

lsof -i:33306

可见端口映射规则是否生效

开设Linux虚拟机的时候自定义CPU的TYPE

在宿主机上使用类似

shell
echo "kvm64" > /usr/local/bin/cpu_type

这样的方式指定默认的CPU的TYPE,可将kvm64替换为你需要的类型

- +
Skip to content

自定义分区

在非Debian系统上安装 Proxmox VE 7

本机硬件配置的最低要求同先前正常安装的要求一致

需要先安装docker

curl -sSL https://get.docker.com/ | sh
+curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" -o /usr/local/bin/docker-compose
+chmod +x /usr/local/bin/docker-compose
+docker-compose --version

然后使用uname -m查询架构,使用对应架构的命令

开设出的PVE面板信息为:

登录用户名和密码都是root,登录后务必使用web的SSH更改密码以免被爆破

用宿主机SSH时务必登录对应https://IPV4地址:8006在web面板上使用SSH,不要使用宿主机的22端口操控PVE

因为web面板上的SSH是在Docker内的,所以不支持后续的一键配置,请自行配置网关等进行使用

X86架构

bash
docker run -idt --network host \
+--privileged \
+--name pve \
+--add-host pve:10.13.14.101 \
+--hostname pve \
+spiritlhl/pve:7_x86_64

ARM架构

bash
docker run -idt --network host \
+--privileged \
+--name pve \
+--add-host pve:10.13.14.101 \
+--hostname pve \
+spiritlhl/pve:7_aarch64

开设出的面板实际是开设在容器内的,但网络已使用host模式,PVE的端口约等于就使用的宿主机的端口

但这里登录的用户名和密码就变成了rootroot,如需修改请docker exec -it pve /bin/bash进入后修改root的密码,然后按ctrl键和A+D退出。

有许多错误需要修复,欢迎PR解决问题,实测在Ubuntu系统的宿主机上安装Proxmox VE的面板成功,解决了通过网络安装Proxmox VE只能使用Debian系统做宿主机的问题

在低配置系统中优化Proxmox-VE的内存占用

以下优化可以减少至少400M内存左右的占用,部分机器能减少6GB以上,实际减少多少内存占用自行测试

减少max_workers数量

执行下述命令查询

cd /usr/share/perl5/PVE/Service
+grep 'max_workers => 3' *

可见

pvedaemon.pm:    max_workers => 3,
+pveproxy.pm:    max_workers => 3,
+spiceproxy.pm:    max_workers => 3, # todo: do we need more?

默认的max_workers是3,可以修改对应的文件,最低max_workers可为1,可使用如下命令进行修改

sed -i "s/max_workers => 3/max_workers => 1/g" /usr/share/perl5/PVE/Service/*

停用HA服务

集群(多节点)可以使用HA服务,如果是单节点,或者没有HA使用的需求,可以执行下述命令禁用

systemctl stop pve-ha-lrm.service 
+systemctl stop pve-ha-crm.service 
+systemctl disable pve-ha-lrm.service 
+systemctl disable pve-ha-crm.service

停用防火墙服务

可执行下述命令停用服务

systemctl stop pve-firewall.service 
+systemctl disable pve-firewall.service

停用调度服务

如果不需要计划任务,如备份、同步之类的任务,可执行下述命令停用服务

systemctl stop pvescheduler.service
+systemctl disable pvescheduler.service

停用Spiceproxy服务

如果不需要使用Spice进行虚拟机/容器链接(arm下暂不支持Spice),可执行下述命令停用服务

systemctl stop spiceproxy.service 
+systemctl disable spiceproxy.service

使用定时任务删除内存缓存

清理不同类型的缓存以及对文件系统进行TRIM操作

shell
TEMP_CRON=$(mktemp)
+sudo crontab -l > $TEMP_CRON
+echo "*/5 * * * * echo 1 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 60; echo 2 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 120; echo 3 > /proc/sys/vm/drop_caches" >> $TEMP_CRON
+echo "*/5 * * * * sleep 180; fstrim -av" >> $TEMP_CRON
+sudo crontab $TEMP_CRON
+rm $TEMP_CRON

上面的命令需要宿主机本身有sudocrontab命令才可使用。

在开设出的NAT的KVM虚拟机上自行映射公网端口

使用nanovim命令修改文件增加端口映射:

/etc/iptables/rules.v4

例如我有一台内网IP为172.16.1.152的KVM虚拟机,虚拟机内已经开设MYSQL监听了3306,我需要使用tcp协议映射出来到宿主机IP上的33306端口上进行使用,那么需要在上面的那个文件中的COMMIT行以上增加如下行

-A PREROUTING -i vmbr0 -p tcp -m tcp -dport 33306 -j DNAT --to-destination 172.16.1.152:3306

保存文件退出文件编辑后执行

service netfilter-persistent restart

重载端口映射

此时在宿主机上执行

lsof -i:33306

可见端口映射规则是否生效

开设Linux虚拟机的时候自定义CPU的TYPE

在宿主机上使用类似

shell
echo "kvm64" > /usr/local/bin/cpu_type

这样的方式指定默认的CPU的TYPE,可将kvm64替换为你需要的类型

+ \ No newline at end of file diff --git a/guide/pve/pve_install.html b/guide/pve/pve_install.html index dc12526999..88b0003495 100644 --- a/guide/pve/pve_install.html +++ b/guide/pve/pve_install.html @@ -5,22 +5,25 @@ PVE主体安装 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

PVE主体安装

安装过程中遇到选项不会选的可无脑按回车,本项目所有脚本内置国内外IP自动判断,使用的是不同的安装源与配置文件,有使用CDN加速镜像下载

TIP

低配置的宿主机,建议所有内容安装完毕后,查看自定义分区的内容,进行内存调优,减少内存占用。

一键安装PVE

TIP

建议debian12,实测部分独立服务器的debian11系统会出现一重启网络就失联的情况,debian12没有这种问题

  • 安装的是当下apt源最新的PVE
  • 比如debian10则是pve6.4,debian11则是pve7.x,debian12则是pve8.x
  • /etc/hosts文件修改(修正商家hostname设置错误以及新增PVE所需的内容)
  • /etc/cloud/cloud.cfg文件修改(避免覆写已修改的hostname等配置)
  • /etc/network/interfaces文件修改(修复auto、dhcp类型为static、增加vmbr0网关)
  • 检测是否为中国IP,如果为中国IP使用清华镜像源,否则使用官方源,同时处理apt的源和对应的nameserver,避免断网
  • 创建vmbr0(独立IP网关),宿主机允许addr和gateway为内网IP或外网IP,已自动识别
  • vmbr0创建支持开设纯IPV4、纯IPV6、双栈虚拟机,自动识别IPV4地址和IPV6地址,自动识别对应的IP区间
  • 安装PVE开虚拟机需要的必备工具包
  • x86_64的替换apt源中的企业订阅为社区源,arm的使用第三方修复的补丁构建的源
  • 打印查询Linux系统内核和PVE内核是否已安装
  • 设置DNS检测8.8.8.8的开机自启添加DNS的systemd服务
  • 新增PVE的APT源链接后,下载PVE并打印输出登陆信息

所有修改过的文件均已设置为只读模式,避免重启后文件被覆写,如需修改请使用chattr -i 文件路径取消只读锁定,修改完毕请执行chattr +i 文件路径进行只读锁定

执行过程中会提示重启系统一次,重启后务必等待起码20秒确保系统未再次自动重启,因为原始环境可能缺失ifupdownifupdown2环境,有加载安装的守护进程进行安装,安装后会再次自动重启系统,等待20秒未自重启确保这个安装已运行完毕.

如果你需要将新安装的PVE纳管进入已有的集群,那么这块安装的时候,名字就不能回车默认使用pve,需要换一个名字避免和集群内的pve本身的hostname冲突.

若宿主机本身存在SLAAC分配的IPV6地址,将可选择是否使用最大的IPV6子网范围,默认回车不使用最大的IPV6子网范围仅使用本机IPV6,若后续需要给虚拟机/容器附加独立的IPV6地址,该选项务必选择y.

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

shell
bash install_pve.sh

TIP

安装成功后打开网页可能提示不安全,点击高级或更多选项,坚持访问即可

登录的信息是你SSH的账户和密码

预配置环境

  • 创建资源池mypool(local)
  • 移除订阅弹窗
  • 尝试开启硬件直通
  • 对AppArmor模块检测和自动安装
  • 重启系统前推荐挂上nezha探针方便在后台不通过SSH使用命令行,避免SSH可能因为商家奇葩的预设可能导致重启后root密码丢失
  • 执行reboot前需要等待后台任务执行完毕,一些宿主机的系统apt命令执行很慢,得等一会才能执行完毕,当然大部分的机器没这么烂,如果很久都起不来ssh无法连接,那么尝试通过控制面板重启一下服务器

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

自动配置宿主机的网关

WARNING

使用前请保证重启过服务器且此时PVE能正常登录进WEB端再执行,重启机器后不要立即执行此命令,待WEB端启动并可登录成功后至少等1分钟再执行本命令 如果WEB端起不来,执行systemctl status pveproxy查看是否启动,如果卡住未启动,执行systemctl start pveproxy启动WEB端。

TIP

这一步是最容易造成SSH断开的,原因是未等待PVE内核启动就修改网络会造成设置冲突,所以至少等几分钟待内核启动也就是WEB端启动成功后再执行。

TIP

在执行本命令前如果宿主机需要附加IPV6隧道(给没有IPV6地址的宿主机添加IPV6子网),请查看IPV6免费子网附加部分的内容附加到对应的配置文件中,但请忽略<初始环境修改>的操作,直接进行附加,附加后验证有IPV6地址了再执行下面的一键配置网关的命令。

  • 如果vmbr0未创建,则自动创建,逻辑同主体安装一致
  • 创建vmbr1(NAT网关),支持开设NAT的IPV6网络的NAT的IPV4的服务器
  • 创建vmbr2(独立IPV6网关),使用ndppd解决宿主机对IPV6地址进行MAC校验的问题,支持开设带独立IPV6网络的服务器
  • 想查看完整设置可以执行cat /etc/network/interfaces查看,如需修改网关需要修改该文件,web端已经无法修改
  • 加载iptables并设置回源且允许NAT端口转发

简单的说,vmbr0负责v4的独立IP,vmbr1负责复杂v4/v6的NAT,vmbr2负责v6的独立IP

开独立IPV4的虚拟机时使用的vmbr0,gateway同宿主机,IPV4/CIDR使用同一网段的地址和相同的子网掩码,使用宿主机未绑定的IPV4地址做IPV4/CIDR,当然如果后续使用本套脚本无需关注这点细枝末节的东西

开NAT的IPV4的虚拟机时使用vmbr1,gateway使用172.16.1.1,IPV4/CIDR使用172.16.1.x/24,这里的x不能是1,当然如果后续使用本套脚本无需关注这点细枝末节的东西

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

这一步是可能需要你执行成功几分钟后重启系统,详见脚本最后执行完毕的提示,但重启可以保证部分隐藏设置加载成功,有条件务必重启一次服务器

- +
Skip to content

PVE主体安装

安装过程中遇到选项不会选的可无脑按回车,本项目所有脚本内置国内外IP自动判断,使用的是不同的安装源与配置文件,有使用CDN加速镜像下载

TIP

低配置的宿主机,建议所有内容安装完毕后,查看自定义分区的内容,进行内存调优,减少内存占用。

一键安装PVE

TIP

建议debian12,实测部分独立服务器的debian11系统会出现一重启网络就失联的情况,debian12没有这种问题

  • 安装的是当下apt源最新的PVE
  • 比如debian10则是pve6.4,debian11则是pve7.x,debian12则是pve8.x
  • /etc/hosts文件修改(修正商家hostname设置错误以及新增PVE所需的内容)
  • /etc/cloud/cloud.cfg文件修改(避免覆写已修改的hostname等配置)
  • /etc/network/interfaces文件修改(修复auto、dhcp类型为static、增加vmbr0网关)
  • 检测是否为中国IP,如果为中国IP使用清华镜像源,否则使用官方源,同时处理apt的源和对应的nameserver,避免断网
  • 创建vmbr0(独立IP网关),宿主机允许addr和gateway为内网IP或外网IP,已自动识别
  • vmbr0创建支持开设纯IPV4、纯IPV6、双栈虚拟机,自动识别IPV4地址和IPV6地址,自动识别对应的IP区间
  • 安装PVE开虚拟机需要的必备工具包
  • x86_64的替换apt源中的企业订阅为社区源,arm的使用第三方修复的补丁构建的源
  • 打印查询Linux系统内核和PVE内核是否已安装
  • 设置DNS检测8.8.8.8的开机自启添加DNS的systemd服务
  • 新增PVE的APT源链接后,下载PVE并打印输出登陆信息

所有修改过的文件均已设置为只读模式,避免重启后文件被覆写,如需修改请使用chattr -i 文件路径取消只读锁定,修改完毕请执行chattr +i 文件路径进行只读锁定

执行过程中会提示重启系统一次,重启后务必等待起码20秒确保系统未再次自动重启,因为原始环境可能缺失ifupdownifupdown2环境,有加载安装的守护进程进行安装,安装后会再次自动重启系统,等待20秒未自重启确保这个安装已运行完毕.

如果你需要将新安装的PVE纳管进入已有的集群,那么这块安装的时候,名字就不能回车默认使用pve,需要换一个名字避免和集群内的pve本身的hostname冲突.

若宿主机本身存在SLAAC分配的IPV6地址,将可选择是否使用最大的IPV6子网范围,默认回车不使用最大的IPV6子网范围仅使用本机IPV6,若后续需要给虚拟机/容器附加独立的IPV6地址,该选项务必选择y.

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_pve.sh -o install_pve.sh && chmod +x install_pve.sh && bash install_pve.sh

shell
bash install_pve.sh

TIP

安装成功后打开网页可能提示不安全,点击高级或更多选项,坚持访问即可

登录的信息是你SSH的账户和密码

预配置环境

  • 创建资源池mypool(local)
  • 移除订阅弹窗
  • 尝试开启硬件直通
  • 对AppArmor模块检测和自动安装
  • 重启系统前推荐挂上nezha探针方便在后台不通过SSH使用命令行,避免SSH可能因为商家奇葩的预设可能导致重启后root密码丢失
  • 执行reboot前需要等待后台任务执行完毕,一些宿主机的系统apt命令执行很慢,得等一会才能执行完毕,当然大部分的机器没这么烂,如果很久都起不来ssh无法连接,那么尝试通过控制面板重启一下服务器

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_backend.sh)

自动配置宿主机的网关

WARNING

使用前请保证重启过服务器且此时PVE能正常登录进WEB端再执行,重启机器后不要立即执行此命令,待WEB端启动并可登录成功后至少等1分钟再执行本命令 如果WEB端起不来,执行systemctl status pveproxy查看是否启动,如果卡住未启动,执行systemctl start pveproxy启动WEB端。

TIP

这一步是最容易造成SSH断开的,原因是未等待PVE内核启动就修改网络会造成设置冲突,所以至少等几分钟待内核启动也就是WEB端启动成功后再执行。

TIP

在执行本命令前如果宿主机需要附加IPV6隧道(给没有IPV6地址的宿主机添加IPV6子网),请查看IPV6免费子网附加部分的内容附加到对应的配置文件中,但请忽略<初始环境修改>的操作,直接进行附加,附加后验证有IPV6地址了再执行下面的一键配置网关的命令。

  • 如果vmbr0未创建,则自动创建,逻辑同主体安装一致
  • 创建vmbr1(NAT网关),支持开设NAT的IPV6网络的NAT的IPV4的服务器
  • 创建vmbr2(独立IPV6网关),使用ndppd解决宿主机对IPV6地址进行MAC校验的问题,支持开设带独立IPV6网络的服务器
  • 想查看完整设置可以执行cat /etc/network/interfaces查看,如需修改网关需要修改该文件,web端已经无法修改
  • 加载iptables并设置回源且允许NAT端口转发

简单的说,vmbr0负责v4的独立IP,vmbr1负责复杂v4/v6的NAT,vmbr2负责v6的独立IP

开独立IPV4的虚拟机时使用的vmbr0,gateway同宿主机,IPV4/CIDR使用同一网段的地址和相同的子网掩码,使用宿主机未绑定的IPV4地址做IPV4/CIDR,当然如果后续使用本套脚本无需关注这点细枝末节的东西

开NAT的IPV4的虚拟机时使用vmbr1,gateway使用172.16.1.1,IPV4/CIDR使用172.16.1.x/24,这里的x不能是1,当然如果后续使用本套脚本无需关注这点细枝末节的东西

国际

shell
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

国内

shell
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/build_nat_network.sh)

TIP

这一步是可能需要你执行成功几分钟后重启系统,详见脚本最后执行完毕的提示,但重启可以保证部分隐藏设置加载成功,有条件务必重启一次服务器

+ \ No newline at end of file diff --git a/guide/pve/pve_kvm.html b/guide/pve/pve_kvm.html index 4a785f402f..1edf82792f 100644 --- a/guide/pve/pve_kvm.html +++ b/guide/pve/pve_kvm.html @@ -5,36 +5,39 @@ Linux虚拟机(KVM/TCG) | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Linux虚拟机(KVM/TCG)

SSH登录说明

开设出的虚拟机,默认生成的用户名可以不是root,此时你需要执行sudo -i切换为root用户

默认设置的用户名不是root时,未经过设置的默认的root密码是passwordoneclickvirt

登录SSH切换为root权限后,一定要修改root密码,可以使用以下命令修改

国际

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

国内

bash
bash <(curl -sSL https://cdn.spiritlhl.net/https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

开设带IPV6地址的虚拟机的注意事项

由于长期闲置IPV6不使用可能导致NDP广播缓存失效重置,一般闲置50分钟左右就会出现IPV6不可用的情况,俗称“IPV6断流”,此时需要设置一个定时任务

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

在开设出的虚拟机中执行上述命令,可保证IPV6网络一直被使用,不会失效断流

开设虚拟机可使用的镜像

  • 已预安装开启cloudinit
  • 开启SSH登陆
  • 预设置SSH监听V4和V6的22端口
  • 开启允许密码验证登陆
  • 开启允许root登陆
  • 部分预安装Qemu-guest-agent

目前可使用的镜像名字的列表为

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

以及

https://github.com/oneclickvirt/pve_kvm_images

仓库的Release中存储的每日修补镜像

单独开设NAT的虚拟化的虚拟机

  • 自动开设NAT服务器,默认使用Debian10镜像,因为该镜像占用最小
  • 可在命令中自定义需要使用的镜像,这里有给出配置好的镜像,镜像自带空间设置是2~10G硬盘,日常使用至少10G以上即可,除非某些镜像开不起来再增加硬盘大小
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 自定义内存大小推荐512MB内存
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloud-init配置好网络以及登陆信息,大概需要5分钟
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是/64的子网

使用方法

  • 系统支持:
    • x86_64架构的详见 跳转 中列出的系统,使用时只需写文件名字,不需要.qcow2尾缀
    • arm架构的详见 跳转 中列出的系统,使用时只需要写系统名字+系统版本号,如ubuntu20、ubutnu22这种

TIP

注意这里的用户名不能是纯数字,会造成cloudinit出问题,最好是纯英文或英文开头

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

各参数含义

shell
# ./buildvm.sh VMID 用户名 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6地址(留空默认N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

开设完毕可执行cat vm111查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小10G
SSH端口40001
80端口40002
443端口40003
内外网映射端口一致的区间50000到50025
系统debian11
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除指定虚拟机

  • 停止VM
  • 删除VM
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应VMID的虚拟机,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个VMID即可,可一次性删除多个

批量开设NAT的虚拟化的虚拟机

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成VM
  • 自动开设NAT服务器,选项留空默认使用debian11镜像,可自定义使用镜像名字,支持的系统名字详见上文支持的镜像列表
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloudinit配置好网络以及登陆信息,大概需要5分钟,每个虚拟机创建之间有间隔等待60秒避免突发性能不足
  • 默认批量开设的虚拟机网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

开设完毕可执行cat vmlog查看信息,或到WEB端对应VM的NOTES中查看

删除所有虚拟机

  • 删除所有VM
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4
-rm -rf vmlog
-rm -rf vm*

TIP

PVE修改VM配置前都得停机先,再修改配置,修改完再启动,免得出现配置重载错误

开设独立IPV4地址的虚拟机

三个脚本,各取所需,各有优缺点。

前两个脚本不需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将直接绑定额外的IPV4地址。

最后一个脚本需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将做NAT全端口映射内网IPV4地址,不直接绑定额外的IPV4地址。

自动选择宿主机同一子网内的额外IPV4地址开设虚拟机

WARNING

使用前需要保证当前宿主机的IP段带了至少2个IP,且有空余的IP未配置,该空余的IP未绑定宿主机。

TIP

此时附加的IPV4地址是宿主机目前的IPV4地址顺位后面的地址, 比如目前宿主机地址是1.1.1.32然后1.1.1.33已经有虚拟机了,那么本脚本附加IP地址为1.1.1.34

  • 自动检测可用的IP区间,通过ping检测空余可使用的IP,选取其中之一绑定到虚拟机上
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 自动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同)
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

各参数含义

shell
# ./buildvm_extra_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘
IPV6附加默认不附加

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

手动指定额外IPV4地址开设虚拟机

  • 需要手动在命令中指定IPV4地址,且带上子网长度
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 如果商家有给IPV4地址和子网长度,请仔细比对,按照下面示例的命令写参数
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网
  • 手动附加的IPV4地址与宿主机的IPV4地址是在不同子网内的(IP地址前缀不同),将使用宿主机IP地址做网关
  • 手动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同),将使用宿主机的网关做网关
  • 可选择是否指定虚拟机的MAC地址
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

TIP

不同子网内的IP地址,如果附加时不指定MAC地址,那么路由器无法识别源 MAC 地址,流量将被标记为“滥用”,并“可能”导致服务器被阻止。 (如果使用Hetzner的独立服务器务建议提供附加IPV4地址对应的MAC地址防止被报告滥用)

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

各参数含义

shell
# ./buildvm_manual_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N) MAC地址(不提供时将不指定虚拟机的MAC地址)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
子网/24 子网
IPV6
MAC地址

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

宿主机手动附加额外IPV4地址后再指定IPV4地址开设虚拟机

  • 需要自己在/etc/network/interfaces中给vmbr0添加额外的IPV4地址(注意chattr -i解锁文件修改后再chattr +i加锁回去)
  • 其他功能类似开设NAT的虚拟机,只不过这里映射不再是部分端口映射,也不再是映射到宿主机的IPV4地址上,而是全端口一一映射到额外的IPV4地址上
  • 在虚拟机外进入虚拟机的流量走绑定的额外IPV4的地址,在虚拟机内发出的流量走原有的宿主机的IPV4地址

TIP

务必保证开设前你能使用额外的IPV4地址通过SSH登录宿主机,但curl ip.sb却仍显示原来的宿主机IPV4地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

各参数含义

shell
# ./buildvm_fullnat_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
IPV6

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

进出流量都走绑定的IPV4地址

执行

line="-A POSTROUTING -s 172.16.1.0\/24 -o vmbr0 -j MASQUERADE"
-sed -i "\|$line|d" /etc/iptables/rules.v4
-service netfilter-persistent restart

即可,但这会导致宿主机丧失开设非独立IPV4地址的NAT的虚拟机/容器的能力,慎重执行

执行后你只能开设独立IPV4地址的虚拟机了。

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际虚拟机仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应虚拟机编号的V6地址绑定到虚拟机上
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

各参数含义

shell
# ./buildvm_onlyv6.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

创建示例

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的虚拟机

参数
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除vm152示例

shell
qm stop 152
-qm destroy 152
-systemctl restart ndpresponder.service
-rm -rf vm152
- +
Skip to content

Linux虚拟机(KVM/TCG)

SSH登录说明

开设出的虚拟机,默认生成的用户名可以不是root,此时你需要执行sudo -i切换为root用户

默认设置的用户名不是root时,未经过设置的默认的root密码是passwordoneclickvirt

登录SSH切换为root权限后,一定要修改root密码,可以使用以下命令修改

国际

bash
bash <(curl -sSL https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

国内

bash
bash <(curl -sSL https://cdn.spiritlhl.net/https://raw.githubusercontent.com/fscarmen/tools/main/root.sh) [PASSWORD]

开设带IPV6地址的虚拟机的注意事项

由于长期闲置IPV6不使用可能导致NDP广播缓存失效重置,一般闲置50分钟左右就会出现IPV6不可用的情况,俗称“IPV6断流”,此时需要设置一个定时任务

shell
echo '*/1 * * * * curl -m 6 -s ipv6.ip.sb || curl -m 6 -s ipv6.ip.sb' | crontab -

在开设出的虚拟机中执行上述命令,可保证IPV6网络一直被使用,不会失效断流

开设虚拟机可使用的镜像

  • 已预安装开启cloudinit
  • 开启SSH登陆
  • 预设置SSH监听V4和V6的22端口
  • 开启允许密码验证登陆
  • 开启允许root登陆
  • 部分预安装Qemu-guest-agent

目前可使用的镜像名字的列表为

https://github.com/oneclickvirt/kvm_images/blob/main/list.text

以及

https://github.com/oneclickvirt/pve_kvm_images

仓库的Release中存储的每日修补镜像

单独开设NAT的虚拟化的虚拟机

  • 自动开设NAT服务器,默认使用Debian10镜像,因为该镜像占用最小
  • 可在命令中自定义需要使用的镜像,这里有给出配置好的镜像,镜像自带空间设置是2~10G硬盘,日常使用至少10G以上即可,除非某些镜像开不起来再增加硬盘大小
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 自定义内存大小推荐512MB内存
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloud-init配置好网络以及登陆信息,大概需要5分钟
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是/64的子网

使用方法

  • 系统支持:
    • x86_64架构的详见 跳转 中列出的系统,使用时只需写文件名字,不需要.qcow2尾缀
    • arm架构的详见 跳转 中列出的系统,使用时只需要写系统名字+系统版本号,如ubuntu20、ubutnu22这种

TIP

注意这里的用户名不能是纯数字,会造成cloudinit出问题,最好是纯英文或英文开头

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm.sh -o buildvm.sh && chmod +x buildvm.sh

各参数含义

shell
# ./buildvm.sh VMID 用户名 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6地址(留空默认N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm.sh 111 root oneclick123 1 512 10 40001 40002 40003 50000 50025 debian11 local N

开设完毕可执行cat vm111查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小10G
SSH端口40001
80端口40002
443端口40003
内外网映射端口一致的区间50000到50025
系统debian11
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除指定虚拟机

  • 停止VM
  • 删除VM
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应VMID的虚拟机,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个VMID即可,可一次性删除多个

批量开设NAT的虚拟化的虚拟机

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成VM
  • 自动开设NAT服务器,选项留空默认使用debian11镜像,可自定义使用镜像名字,支持的系统名字详见上文支持的镜像列表
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部的cloudinit配置好网络以及登陆信息,大概需要5分钟,每个虚拟机创建之间有间隔等待60秒避免突发性能不足
  • 默认批量开设的虚拟机网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 虚拟机的相关信息将会存储到WEB端对应VM的NOTES中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_vm.sh -o create_vm.sh && chmod +x create_vm.sh && bash create_vm.sh

开设完毕可执行cat vmlog查看信息,或到WEB端对应VM的NOTES中查看

删除所有虚拟机

  • 删除所有VM
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
for vmid in $(qm list | awk '{if(NR>1) print $1}'); do qm stop $vmid; qm destroy $vmid; rm -rf /var/lib/vz/images/$vmid*; done
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4
+rm -rf vmlog
+rm -rf vm*

TIP

PVE修改VM配置前都得停机先,再修改配置,修改完再启动,免得出现配置重载错误

开设独立IPV4地址的虚拟机

三个脚本,各取所需,各有优缺点。

前两个脚本不需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将直接绑定额外的IPV4地址。

最后一个脚本需要额外的IPV4地址事先绑定到vmbr0接口上,开设的虚拟机将做NAT全端口映射内网IPV4地址,不直接绑定额外的IPV4地址。

自动选择宿主机同一子网内的额外IPV4地址开设虚拟机

WARNING

使用前需要保证当前宿主机的IP段带了至少2个IP,且有空余的IP未配置,该空余的IP未绑定宿主机。

TIP

此时附加的IPV4地址是宿主机目前的IPV4地址顺位后面的地址, 比如目前宿主机地址是1.1.1.32然后1.1.1.33已经有虚拟机了,那么本脚本附加IP地址为1.1.1.34

  • 自动检测可用的IP区间,通过ping检测空余可使用的IP,选取其中之一绑定到虚拟机上
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 自动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同)
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_extra_ip.sh -o buildvm_extra_ip.sh && chmod +x buildvm_extra_ip.sh

各参数含义

shell
# ./buildvm_extra_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_extra_ip.sh 152 root oneclick123 1 1024 10 debian12 local N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘
IPV6附加默认不附加

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

手动指定额外IPV4地址开设虚拟机

  • 需要手动在命令中指定IPV4地址,且带上子网长度
  • 如果宿主机自带IPV6子网将可选择是否附加上IPV6地址
  • 如果商家有给IPV4地址和子网长度,请仔细比对,按照下面示例的命令写参数
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网
  • 手动附加的IPV4地址与宿主机的IPV4地址是在不同子网内的(IP地址前缀不同),将使用宿主机IP地址做网关
  • 手动附加的IPV4地址与宿主机的IPV4地址是在同一个子网内的(IP地址前缀相同),将使用宿主机的网关做网关
  • 可选择是否指定虚拟机的MAC地址
  • 在虚拟机内外进出流量都走绑定的额外IPV4的地址

TIP

不同子网内的IP地址,如果附加时不指定MAC地址,那么路由器无法识别源 MAC 地址,流量将被标记为“滥用”,并“可能”导致服务器被阻止。 (如果使用Hetzner的独立服务器务建议提供附加IPV4地址对应的MAC地址防止被报告滥用)

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_manual_ip.sh -o buildvm_manual_ip.sh && chmod +x buildvm_manual_ip.sh

各参数含义

shell
# ./buildvm_manual_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N) MAC地址(不提供时将不指定虚拟机的MAC地址)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_manual_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d/24 N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
子网/24 子网
IPV6
MAC地址

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

宿主机手动附加额外IPV4地址后再指定IPV4地址开设虚拟机

  • 需要自己在/etc/network/interfaces中给vmbr0添加额外的IPV4地址(注意chattr -i解锁文件修改后再chattr +i加锁回去)
  • 其他功能类似开设NAT的虚拟机,只不过这里映射不再是部分端口映射,也不再是映射到宿主机的IPV4地址上,而是全端口一一映射到额外的IPV4地址上
  • 在虚拟机外进入虚拟机的流量走绑定的额外IPV4的地址,在虚拟机内发出的流量走原有的宿主机的IPV4地址

TIP

务必保证开设前你能使用额外的IPV4地址通过SSH登录宿主机,但curl ip.sb却仍显示原来的宿主机IPV4地址

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_fullnat_ip.sh -o buildvm_fullnat_ip.sh && chmod +x buildvm_fullnat_ip.sh

各参数含义

shell
# ./buildvm_fullnat_ip.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘 IPV4地址 独立IPV6(默认为N)

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

测试示例

shell
./buildvm_fullnat_ip.sh 152 root oneclick123 1 1024 10 debian12 local a.b.c.d N

上述命令意义为开设一个带独立IPV4地址的虚拟机

属性
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)
IPV4地址a.b.c.d
IPV6

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

进出流量都走绑定的IPV4地址

执行

line="-A POSTROUTING -s 172.16.1.0\/24 -o vmbr0 -j MASQUERADE"
+sed -i "\|$line|d" /etc/iptables/rules.v4
+service netfilter-persistent restart

即可,但这会导致宿主机丧失开设非独立IPV4地址的NAT的虚拟机/容器的能力,慎重执行

执行后你只能开设独立IPV4地址的虚拟机了。

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际虚拟机仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应虚拟机编号的V6地址绑定到虚拟机上
  • 系统的相关信息将会存储到对应的虚拟机的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_onlyv6.sh -o buildvm_onlyv6.sh && chmod +x buildvm_onlyv6.sh

各参数含义

shell
# ./buildvm_onlyv6.sh VMID 用户名 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

TIP

注意这里的密码最好仅英文与数字混合,且以英文开头,避免密码在设置过程中因为特殊字符被转义而设置失败

创建示例

shell
./buildvm_onlyv6.sh 152 root oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的虚拟机

参数
VMID152
用户名root
密码oneclick123
CPU1核
内存1024MB
硬盘10G
系统debian12
存储盘local

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

删除vm152示例

shell
qm stop 152
+qm destroy 152
+systemctl restart ndpresponder.service
+rm -rf vm152
+ \ No newline at end of file diff --git a/guide/pve/pve_lxc.html b/guide/pve/pve_lxc.html index 0138afc5dd..e8ade351f6 100644 --- a/guide/pve/pve_lxc.html +++ b/guide/pve/pve_lxc.html @@ -5,33 +5,36 @@ LXC容器 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

LXC容器

WARNING

如果你需要在一台服务器上开启超过200个LXC容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

开设LXC容器可使用的镜像

x86_64:

自动修补镜像:https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

每日自动拉取进行编译和修补

手动修补镜像: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

其中的部分镜像有缺陷,不保证所有PVE可用,名字为 ubuntu16.04debian6centos7opensuse42.2opensuse42.3 非必要不要使用。

执行pveam available --section system查看官方可用的系统名字和版本号

优先级:自修补镜像(Proxmox-VE 5及其以下版本不支持) > 官方默认镜像(都支持)

已通过脚本自动识别版本使用对应镜像

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

可在上面的文件中查看支持的系统,其中列出的debian和ubuntu系统不要使用里面的别名,使用数字代号即可。

TIP

系统参数一律是小写的系统名字拼接版本号,如:debian11,ubuntu22等。 (自修补镜像支持一些偏门系统,如 centos6、centos7、debian8、debian9 等)

所有系统的CT默认用户名是root

TIP

当然有时候会存在特殊情况,version可能是current/base,此时系统参数仅使用英文系统名字即可,如 archlinux、gentoo、kali。

单独开设LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 自动开设NAT服务器,默认使用Debian11镜像,也可自定义系统
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部配置好网络以及登陆信息,大概需要3分钟
  • 默认开设的网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

各参数含义

shell
# ./buildct.sh CTID 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6(默认为N)

测试示例

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

开设完毕可执行cat ct111查看信息,或在web端的NOTES查看

以下为开设的示例CT的信息:

属性
CTID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小5G
SSH端口20001
80端口20002
443端口20003
内外网映射端口一致的区间30000到30025
系统debian11
宿主机的存储盘local
IPV6

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除指定容器

  • 停止CT
  • 删除CT
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应CTID的容器,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个CTID即可,可一次性删除多个

批量开设NAT的LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成CT容器,但需要注意的是宿主机内存记得开点swap免得机器炸了开SWAP点我跳转
  • 每个容器创建之间有间隔等待60秒避免突发性能不足
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

开设完毕可执行cat ctlog查看信息,或在web端的NOTES查看

删除所有CT

  • 删除所有CT
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
-rm -rf ct*
-iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-systemctl restart ndpresponder.service
-iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
-iptables-save > /etc/iptables/rules.v4

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际容器仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应容器编号的V6地址绑定到容器上
  • 系统的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

各参数含义

shell
# ./buildct_onlyv6.sh CTID 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

创建示例

shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的容器

属性
容器类型CT
CTID152
用户名root
密码oneclick123
CPU核心数1
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除示例

shell
rm -rf ct*
-pct stop 152 
-pct destroy 152
-systemctl restart ndpresponder.service
- +
Skip to content

LXC容器

WARNING

如果你需要在一台服务器上开启超过200个LXC容器,那么不推荐你使用本项目,可能会出现lxcfs访问漂移的问题,产生IO占用无法释放。(系lxc原生问题无法修复)

开设LXC容器可使用的镜像

x86_64:

自动修补镜像:https://github.com/oneclickvirt/lxc_amd64_images/blob/main/fixed_images.txt

TIP

每日自动拉取进行编译和修补

手动修补镜像: https://github.com/oneclickvirt/pve_lxc_images/blob/main/fixed_images.txt

TIP

其中的部分镜像有缺陷,不保证所有PVE可用,名字为 ubuntu16.04debian6centos7opensuse42.2opensuse42.3 非必要不要使用。

执行pveam available --section system查看官方可用的系统名字和版本号

优先级:自修补镜像(Proxmox-VE 5及其以下版本不支持) > 官方默认镜像(都支持)

已通过脚本自动识别版本使用对应镜像

arm:

https://github.com/oneclickvirt/lxc_arm_images/blob/main/fixed_images.txt

可在上面的文件中查看支持的系统,其中列出的debian和ubuntu系统不要使用里面的别名,使用数字代号即可。

TIP

系统参数一律是小写的系统名字拼接版本号,如:debian11,ubuntu22等。 (自修补镜像支持一些偏门系统,如 centos6、centos7、debian8、debian9 等)

所有系统的CT默认用户名是root

TIP

当然有时候会存在特殊情况,version可能是current/base,此时系统参数仅使用英文系统名字即可,如 archlinux、gentoo、kali。

单独开设LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 自动开设NAT服务器,默认使用Debian11镜像,也可自定义系统
  • 自动进行内外网端口映射,含22,80,443端口以及其他25个内外网端口号一样的端口
  • 生成后需要等待一段时间虚拟机内部配置好网络以及登陆信息,大概需要3分钟
  • 默认开设的网络配置为:22,80,443端口及一个25个端口区间的内外网映射
  • 可自定义开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 可在命令中指定存储盘位置,默认不指定时为local盘即系统盘,可指定为PVE中显示的挂载盘
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct.sh -o buildct.sh && chmod +x buildct.sh

各参数含义

shell
# ./buildct.sh CTID 密码 CPU核数 内存 硬盘 SSH端口 80端口 443端口 外网端口起 外网端口止 系统 存储盘 独立IPV6(默认为N)

测试示例

shell
./buildct.sh 111 oneclick123 1 512 5 20001 20002 20003 30000 30025 debian11 local N

开设完毕可执行cat ct111查看信息,或在web端的NOTES查看

以下为开设的示例CT的信息:

属性
CTID111
SSH登录的用户名root
SSH登录的密码oneclick123
CPU核数1
内存大小512MB
磁盘大小5G
SSH端口20001
80端口20002
443端口20003
内外网映射端口一致的区间30000到30025
系统debian11
宿主机的存储盘local
IPV6

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除指定容器

  • 停止CT
  • 删除CT
  • 删除端口映射
  • 重启网络
  • 删除log文件

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/pve_delete.sh -o pve_delete.sh && chmod +x pve_delete.sh

使用方法

可以删除对应CTID的容器,这里用上文中的示例111做演示

shell
./pve_delete.sh 111

实际删除数量不固定,空格分隔每个CTID即可,可一次性删除多个

批量开设NAT的LXC虚拟化的CT

WARNING

初次使用前需要保证当前PVE纯净且宿主机未进行过任何端口映射,否则设置冲突可能出现BUG

TIP

开设前请使用screen挂起执行,避免批量开设时间过长,SSH不稳定导致中间执行中断

  • 可多次运行批量生成CT容器,但需要注意的是宿主机内存记得开点swap免得机器炸了开SWAP点我跳转
  • 每个容器创建之间有间隔等待60秒避免突发性能不足
  • 可自定义批量开设的核心数,内存大小,硬盘大小,使用宿主机哪个存储盘,记得自己计算好空闲资源开设
  • 开设的CT默认已启用SSH且允许root登陆,且已设置支持使用docker的嵌套虚拟化
  • 容器的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看
  • 如果宿主机自带IPV6子网将自动附加上IPV6网络,但无公网IPV6地址
  • 可选择是否开启独立IPV6,需要宿主机至少有一个/104的子网,最好是一个/64子网

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/create_ct.sh -o create_ct.sh && chmod +x create_ct.sh && bash create_ct.sh

开设完毕可执行cat ctlog查看信息,或在web端的NOTES查看

删除所有CT

  • 删除所有CT
  • 删除所有nat的端口映射
  • 重启网络
  • 删除log文件
shell
pct list | awk 'NR>1{print $1}' | xargs -I {} sh -c 'pct stop {}; pct destroy {}'
+rm -rf ct*
+iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+systemctl restart ndpresponder.service
+iptables-save | awk '{if($1=="COMMIT"){delete x}}$1=="-A"?!x[$0]++:1' | iptables-restore
+iptables-save > /etc/iptables/rules.v4

开设纯IPV6地址的虚拟机

前提是宿主机给的是IPV6子网而不是单独一个IPV6地址,且宿主机未开启MAC地址校验

自动选择IPV6地址无需手动指定

  • 纯IPV6指绑定的公共IPV6地址,实际容器仍旧有宿主机的IPV4网络但无外网IPV4端口
  • 自动检测可用的IPV6区间,对应容器编号的V6地址绑定到容器上
  • 系统的相关信息将会存储到对应的容器的NOTE中,可在WEB端查看

使用方法

下载脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildct_onlyv6.sh -o buildct_onlyv6.sh && chmod +x buildct_onlyv6.sh

各参数含义

shell
# ./buildct_onlyv6.sh CTID 密码 CPU核数 内存大小以MB计算 硬盘大小以GB计算 系统 存储盘

创建示例

shell
./buildct_onlyv6.sh 152 oneclick123 1 1024 10 debian12 local

上述命令意义为开设一个纯IPV6地址的容器

属性
容器类型CT
CTID152
用户名root
密码oneclick123
CPU核心数1
内存1024MB
硬盘10G
系统debian12
存储盘local盘 (系统盘)

TIP

注意这里的CTID仅可使用100到256,其他数字不可用

删除示例

shell
rm -rf ct*
+pct stop 152 
+pct destroy 152
+systemctl restart ndpresponder.service
+ \ No newline at end of file diff --git a/guide/pve/pve_macos.html b/guide/pve/pve_macos.html index 13a9185727..613f2895fa 100644 --- a/guide/pve/pve_macos.html +++ b/guide/pve/pve_macos.html @@ -5,31 +5,34 @@ 开设MacOS虚拟机 | 一键虚拟化项目 - + + + - - - - - - + + + + + + - + + -
Skip to content
On this page

开设MacOS虚拟机

前置需求

系统和硬件配置要求 --> 检测环境

只有检测环境检测出宿主机支持KVM嵌套虚拟化时,才可以开设MACOS虚拟机,否则会被硬件识别无法开设。

前置环境设置

  • 自动识别 CPU 类型(AMD 或 Intel),并根据类型设置嵌套虚拟化参数。
  • 修改 GRUB 启动参数,启用 IOMMU 和禁用默认 framebuffer。
  • 添加 VFIO 模块支持,便于直通硬件设备。
  • 黑名单声卡和显卡驱动模块,避免与 macOS 冲突。
  • 配置 KVM 相关内核参数,忽略 MSR 错误,提高兼容性。
  • 修补 Proxmox 前端状态检测逻辑,绕过状态限制。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

执行成功后会显示15秒后重启本机,这是正常的流程,不重启无法使得内核参数生效。

系统镜像下载

  • 所有镜像已预装组件,体积较大(最小约4.9GB),下载与解压任务将后台挂起执行。
  • 镜像为完整系统含所有组件,无需联网即可引导使用。
  • 若系统盘空闲空间不足镜像大小的2倍,将拒绝下载。
  • 镜像为7z压缩格式,下载后需解压才能使用。
  • 可随时查看当前下载与解压任务状态,完成后方可创建虚拟机。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

shell
bash install_macos_images.sh

后台下载任务挂起执行后,可关闭SSH窗口,等待半小时到3个小时(具体等待时间取决于你的服务器带宽大小和连通性),下载iso的7z压缩包。

下载任务执行完毕后,查询显示当前下载任务为空时,就可以选择解压任务执行了,解压挂起执行等待的时间取决于你的服务器CPU性能。

当解压任务执行完毕,查询显示当前解压任务为空时,一切准备工作就算准备好了。

相同类型的任务可以并发,也可以随时取消某个任务,取消时需要输入PID的值。

通过 https://github.com/oneclickvirt/macos 制作的目前支持的镜像压缩包:

# 按系统发布时间从旧到新
-high-sierra.iso.7z (大小: 5.23GB)
-mojave.iso.7z (大小: 6.03GB)
-catalina.iso.7z (大小: 8.33GB)
-big‑sur.iso.7z (大小: 12.21GB)
-monterey.iso.7z (大小: 12.36GB)
-ventura.iso.7z (大小: 12.31GB)
-sonoma.iso.7z (大小: 14.41GB)
-sequoia.iso.7z (大小: 15.02GB)

MACOS虚拟机模板设置

  • 系统high-sierramojavecatalina需要至少2核4G内存40G硬盘进行开设
  • big‑sur及更新版本的MACOS系统需要至少6核6G内存50G硬盘进行开设
  • 系统版本越新(下载的序号越靠后)所需的硬件就越多
  • 所有镜像均为启动盘镜像,未设置任何个人数据,所以关于硬盘分配,登录信息设置,网络设置都需要后续按照说明手动设置
  • 需要手动在web端启动虚拟机,启动前可以查看所有模板是否符合预期再启动

下载模板脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

参数含义

shell
# ./buildvm_macos.sh VMID CPU核数 内存 硬盘 SSH端口 VNC端口 系统 存储盘 独立IPV6(留空默认N)

TIP

这块的硬盘大小只是你开设的虚拟机的硬盘大小,实际开设过程中,程序还会挂载引导盘和系统镜像,所以实际开设一个虚拟机的硬盘需求是 虚拟机硬盘大小+镜像本体大小+引导盘大小(500MB) 请时刻注意你的硬盘空间是否足够开设虚拟机

示例命令

以最旧的版本(high-sierra)为例,实验支持的配置如下(非常卡顿)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

模板开设完毕可执行cat vm100查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID100
CPU核数2
内存大小4096MB
磁盘大小45G
SSH端口44022
VNC端口45901
系统high-sierra
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

MACOS系统引导和安装

前面的流程走完后,面板端可以看到一个灰色的虚拟机待启动

mac0

点击启动后,进入VNC面板,左侧选择框有一个全屏按钮,实际操作时建议全屏操作,避免分辨率问题

mac00

经过大概3分钟的引导盘加载后,屏幕中央靠左侧会显示有一个启动盘可用,直接点击或回车

然后又是大概3~5分钟的启动盘加载后,会出现四个选择框,选择Disk Utility点击进入

mac1

进入后可以看到有三个盘和一个镜像,找到那个盘大小大于40G且名字叫QEMU HARDDISK Media的盘,点击Erase

mac2

此时会出现一个弹窗,需要给name重命名为macos方便后续识别使用,然后点击Erase继续初始化

mac3

初始化完毕后,点击Done

mac4

此时需要退出Disk Utility界面,右上角点击Disk Utility选择Quit Disk Utility退出当前选择框

mac5

然后回到了之前那四个选择框那里,选择Install macOS XXXX(由于我在以Big Sur为示例安装,所以XXXX为Big Sur系统),点击continue

mac6

后续就是继续点击continue,然后点击Agree,然后又是点击Agree

mac7

mac8

mac9

直到又出现那三个盘,但在这块可以那个盘大小大于40G且名字叫macos的盘,选择它,然后点击continue

mac10

一段时间的文件复制硬盘加载(大概跑个12分钟)后,正式进入系统安装环节,这块看你宿主机在哪个地区选哪个

mac11

选择完地区后一路点击continue

mac12

mac13

直到出现数据迁移选项Migration Assistant,选择左下角的Not Now不导入用户数据

mac14

然后就会提示你创建用户,填写用户名和账户名,还有登录所需的密码,设置完毕后点击continue

mac15

然后后面就会一路畅通点击continue,直到系统安装完毕了

网络配置

由于是离线环境进行的系统安装,所以这块需要手动配置静态网络连接宿主机的网桥

右上角点击WIFI按钮,关闭WIFI后,点击Network Preferences ...

mac16

进入设置界面后,点击Advanced按钮,进入高级设置界面

mac17

TCP/IP这一栏填写静态网络配置

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

如果你需要配置IPV6网络,类比上面的IPV4设置,需要填写的会是虚拟机绑定的公网IPV6地址(PVE面板中的Note框有写),子网掩码填128,默认网关填写cat /usr/local/bin/pve_check_ipv6在宿主机执行后显示的地址。

mac18

DNS这一栏填写静态网络的DNS配置

一般加入8.8.8.81.1.1.1足够了,中国境内使用114.114.114.114即可。

mac19

填写完毕且apply后,设置的左上角会显示网络已连通

mac20

此时打开默认的浏览器,随便打开一个网址,都是可访问公网资源的,证明网络已配置成功

mac21

卸载iso镜像

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

Macos系统就是卸载opencore.isoxxxx(安装使用的系统镜像).iso,类似上面示例图片的Windows系统卸载win镜像和virtio镜像一样。

- +
Skip to content

开设MacOS虚拟机

前置需求

系统和硬件配置要求 --> 检测环境

只有检测环境检测出宿主机支持KVM嵌套虚拟化时,才可以开设MACOS虚拟机,否则会被硬件识别无法开设。

前置环境设置

  • 自动识别 CPU 类型(AMD 或 Intel),并根据类型设置嵌套虚拟化参数。
  • 修改 GRUB 启动参数,启用 IOMMU 和禁用默认 framebuffer。
  • 添加 VFIO 模块支持,便于直通硬件设备。
  • 黑名单声卡和显卡驱动模块,避免与 macOS 冲突。
  • 配置 KVM 相关内核参数,忽略 MSR 错误,提高兼容性。
  • 修补 Proxmox 前端状态检测逻辑,绕过状态限制。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/extra_scripts/configure_macos.sh -o configure_macos.sh && chmod +x configure_macos.sh && bash configure_macos.sh

执行成功后会显示15秒后重启本机,这是正常的流程,不重启无法使得内核参数生效。

系统镜像下载

  • 所有镜像已预装组件,体积较大(最小约4.9GB),下载与解压任务将后台挂起执行。
  • 镜像为完整系统含所有组件,无需联网即可引导使用。
  • 若系统盘空闲空间不足镜像大小的2倍,将拒绝下载。
  • 镜像为7z压缩格式,下载后需解压才能使用。
  • 可随时查看当前下载与解压任务状态,完成后方可创建虚拟机。

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/install_macos_images.sh -o install_macos_images.sh && chmod +x install_macos_images.sh && bash install_macos_images.sh

shell
bash install_macos_images.sh

后台下载任务挂起执行后,可关闭SSH窗口,等待半小时到3个小时(具体等待时间取决于你的服务器带宽大小和连通性),下载iso的7z压缩包。

下载任务执行完毕后,查询显示当前下载任务为空时,就可以选择解压任务执行了,解压挂起执行等待的时间取决于你的服务器CPU性能。

当解压任务执行完毕,查询显示当前解压任务为空时,一切准备工作就算准备好了。

相同类型的任务可以并发,也可以随时取消某个任务,取消时需要输入PID的值。

通过 https://github.com/oneclickvirt/macos 制作的目前支持的镜像压缩包:

# 按系统发布时间从旧到新
+high-sierra.iso.7z (大小: 5.23GB)
+mojave.iso.7z (大小: 6.03GB)
+catalina.iso.7z (大小: 8.33GB)
+big‑sur.iso.7z (大小: 12.21GB)
+monterey.iso.7z (大小: 12.36GB)
+ventura.iso.7z (大小: 12.31GB)
+sonoma.iso.7z (大小: 14.41GB)
+sequoia.iso.7z (大小: 15.02GB)

MACOS虚拟机模板设置

  • 系统high-sierramojavecatalina需要至少2核4G内存40G硬盘进行开设
  • big‑sur及更新版本的MACOS系统需要至少6核6G内存50G硬盘进行开设
  • 系统版本越新(下载的序号越靠后)所需的硬件就越多
  • 所有镜像均为启动盘镜像,未设置任何个人数据,所以关于硬盘分配,登录信息设置,网络设置都需要后续按照说明手动设置
  • 需要手动在web端启动虚拟机,启动前可以查看所有模板是否符合预期再启动

下载模板脚本

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/buildvm_macos.sh -o buildvm_macos.sh && chmod +x buildvm_macos.sh

参数含义

shell
# ./buildvm_macos.sh VMID CPU核数 内存 硬盘 SSH端口 VNC端口 系统 存储盘 独立IPV6(留空默认N)

TIP

这块的硬盘大小只是你开设的虚拟机的硬盘大小,实际开设过程中,程序还会挂载引导盘和系统镜像,所以实际开设一个虚拟机的硬盘需求是 虚拟机硬盘大小+镜像本体大小+引导盘大小(500MB) 请时刻注意你的硬盘空间是否足够开设虚拟机

示例命令

以最旧的版本(high-sierra)为例,实验支持的配置如下(非常卡顿)

shell
./buildvm_macos.sh 100 2 4096 45 44022 45901 high-sierra local N

模板开设完毕可执行cat vm100查看信息,或到WEB端对应VM的NOTES中查看

以下为开设的示例VM的信息:

属性
VMID100
CPU核数2
内存大小4096MB
磁盘大小45G
SSH端口44022
VNC端口45901
系统high-sierra
宿主机的存储盘local
绑定独立IPV6(留空默认N)N

TIP

注意这里的VMID仅可使用100到256,其他数字不可用

MACOS系统引导和安装

前面的流程走完后,面板端可以看到一个灰色的虚拟机待启动

mac0

点击启动后,进入VNC面板,左侧选择框有一个全屏按钮,实际操作时建议全屏操作,避免分辨率问题

mac00

经过大概3分钟的引导盘加载后,屏幕中央靠左侧会显示有一个启动盘可用,直接点击或回车

然后又是大概3~5分钟的启动盘加载后,会出现四个选择框,选择Disk Utility点击进入

mac1

进入后可以看到有三个盘和一个镜像,找到那个盘大小大于40G且名字叫QEMU HARDDISK Media的盘,点击Erase

mac2

此时会出现一个弹窗,需要给name重命名为macos方便后续识别使用,然后点击Erase继续初始化

mac3

初始化完毕后,点击Done

mac4

此时需要退出Disk Utility界面,右上角点击Disk Utility选择Quit Disk Utility退出当前选择框

mac5

然后回到了之前那四个选择框那里,选择Install macOS XXXX(由于我在以Big Sur为示例安装,所以XXXX为Big Sur系统),点击continue

mac6

后续就是继续点击continue,然后点击Agree,然后又是点击Agree

mac7

mac8

mac9

直到又出现那三个盘,但在这块可以那个盘大小大于40G且名字叫macos的盘,选择它,然后点击continue

mac10

一段时间的文件复制硬盘加载(大概跑个12分钟)后,正式进入系统安装环节,这块看你宿主机在哪个地区选哪个

mac11

选择完地区后一路点击continue

mac12

mac13

直到出现数据迁移选项Migration Assistant,选择左下角的Not Now不导入用户数据

mac14

然后就会提示你创建用户,填写用户名和账户名,还有登录所需的密码,设置完毕后点击continue

mac15

然后后面就会一路畅通点击continue,直到系统安装完毕了

网络配置

由于是离线环境进行的系统安装,所以这块需要手动配置静态网络连接宿主机的网桥

右上角点击WIFI按钮,关闭WIFI后,点击Network Preferences ...

mac16

进入设置界面后,点击Advanced按钮,进入高级设置界面

mac17

TCP/IP这一栏填写静态网络配置

Configure IPV4: Manually

IPV4 Address: 172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

Subnet Mask: 255.255.255.0

Router: 172.16.1.1

如果你需要配置IPV6网络,类比上面的IPV4设置,需要填写的会是虚拟机绑定的公网IPV6地址(PVE面板中的Note框有写),子网掩码填128,默认网关填写cat /usr/local/bin/pve_check_ipv6在宿主机执行后显示的地址。

mac18

DNS这一栏填写静态网络的DNS配置

一般加入8.8.8.81.1.1.1足够了,中国境内使用114.114.114.114即可。

mac19

填写完毕且apply后,设置的左上角会显示网络已连通

mac20

此时打开默认的浏览器,随便打开一个网址,都是可访问公网资源的,证明网络已配置成功

mac21

卸载iso镜像

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

Macos系统就是卸载opencore.isoxxxx(安装使用的系统镜像).iso,类似上面示例图片的Windows系统卸载win镜像和virtio镜像一样。

+ \ No newline at end of file diff --git a/guide/pve/pve_precheck.html b/guide/pve/pve_precheck.html index e319a78e0c..36d502133a 100644 --- a/guide/pve/pve_precheck.html +++ b/guide/pve/pve_precheck.html @@ -5,24 +5,27 @@ 前言 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果有未适配的商家或机器欢迎联系@spiritlhl_bot,有空会尝试支持一下

WARNING

会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/pve

各种要求

建议debian在使用前尽量使用最新的稳定版本的系统

不要在动态IP的服务器上使用本套脚本(重启机器后自动切换本机IP的服务器暂不支持,重启机器后IP不自动切换的支持)

本项目的一键安装脚本只适配Debian系统,非Debian无法通过APT源安装,官方只给了Debian的镜像,其他系统只能使用ISO安装,或使用自定义分区和常见问题分区中的其他方式解决问题。

  • 系统要求:Debian 8+

TIP

建议debian12而不是debian11,debian11在部分独立服务器上有网络重启的BUG。

  • 硬件要求:2核2G内存x86_64arm架构服务器硬盘至少20G
  • 可开KVM的硬件要求:VM-X或AMD-V支持 (部分VPS和全部独服支持)
  • 如果硬件或系统需求不满足,可使用incus批量开LXC容器跳转

如果使用IPV6隧道进行宿主机的IPV6子网附加,务必在PVE安装成功但网关未自动设置时在对应文件添加内容,不要在一开始(未安装PVE)就进行IPV6隧道的添加。

开设虚拟内存(SWAP)(非必须的可选项)

TIP

内存开点swap免得机器炸了,如果你的宿主机内存不够用硬盘又很多空闲的话

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

检测环境

  • 本项目相关脚本执行前务必执行本脚本检测环境,如果不符合安装PVE的要求则无法使用后续的脚本
  • 检测本机IPV6的网络配置情况(有无IPV6都可安装,只是查询一下罢了)
  • 检测硬件配置是否满足最低要求
  • 检测硬件环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 检测系统环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 不可嵌套虚拟化KVM的服务器不推荐安装PVE,不如使用incus性能更好

国际

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

国内

bash
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

如果你需要更新IPV6信息再查询,那么执行以下命令后再查询

bash
rm -rf /usr/local/bin/pve_ipv6*
-rm -rf /usr/local/bin/pve_check_ipv6*
-rm -rf /usr/local/bin/pve_last_ipv6*

执行本项目的检测环境的命令,展示如下

图片

查询如上的只需使用下面的一键脚本自动创建虚拟机即可,无需手动再修改WEB端设置

图片

查询如上的在使用后续脚本创建了虚拟机后,可能需要手动修改WEB端设置,需要关闭对应每个虚拟机的硬件嵌套虚拟化,如下图

图片

先停止虚拟机再修改,修改完后再开机才能使用NOVNC,不关闭可能导致这个虚拟机有BUG无法使用

如果强行安装PVE开KVM,启动不了的也可以关闭这个选项试试能不能启动虚拟机,导致这些问题的原因就是上面说的,宿主机不支持嵌套虚拟化KVM进行加速

TIP

开设虚拟机前请使用screen挂起执行,避免开设时间过长,SSH不稳定导致中间执行中断



- +
Skip to content

前言

以下为非自定义部分的介绍,自定义部分有自己对应的介绍,勿弄混了

如果有未适配的商家或机器欢迎联系@spiritlhl_bot,有空会尝试支持一下

WARNING

会改变宿主机的网络结构,请保证宿主机随时可重置系统,且运行前无重要数据在宿主机上

欢迎给项目一个Star进行免费的支持-->https://github.com/oneclickvirt/pve

各种要求

建议debian在使用前尽量使用最新的稳定版本的系统

不要在动态IP的服务器上使用本套脚本(重启机器后自动切换本机IP的服务器暂不支持,重启机器后IP不自动切换的支持)

本项目的一键安装脚本只适配Debian系统,非Debian无法通过APT源安装,官方只给了Debian的镜像,其他系统只能使用ISO安装,或使用自定义分区和常见问题分区中的其他方式解决问题。

  • 系统要求:Debian 8+

TIP

建议debian12而不是debian11,debian11在部分独立服务器上有网络重启的BUG。

  • 硬件要求:2核2G内存x86_64arm架构服务器硬盘至少20G
  • 可开KVM的硬件要求:VM-X或AMD-V支持 (部分VPS和全部独服支持)
  • 如果硬件或系统需求不满足,可使用incus批量开LXC容器跳转

如果使用IPV6隧道进行宿主机的IPV6子网附加,务必在PVE安装成功但网关未自动设置时在对应文件添加内容,不要在一开始(未安装PVE)就进行IPV6隧道的添加。

开设虚拟内存(SWAP)(非必须的可选项)

TIP

内存开点swap免得机器炸了,如果你的宿主机内存不够用硬盘又很多空闲的话

单位换算:输入 1024 产生 1G SWAP-虚拟内存,虚拟内存占用硬盘空间,当实际内存不够用时将自动使用虚拟内存做内存使用,但随之带来IO高占用以及CPU性能占用

建议只开实际内存大小两倍大小的虚拟内存

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/addswap/main/addswap.sh -o addswap.sh && chmod +x addswap.sh && bash addswap.sh

检测环境

  • 本项目相关脚本执行前务必执行本脚本检测环境,如果不符合安装PVE的要求则无法使用后续的脚本
  • 检测本机IPV6的网络配置情况(有无IPV6都可安装,只是查询一下罢了)
  • 检测硬件配置是否满足最低要求
  • 检测硬件环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 检测系统环境是否可嵌套虚拟化KVM类型的服务器,不可嵌套虚拟化KVM的也可以开QEMU的TCG的服务器,性能较差
  • 不可嵌套虚拟化KVM的服务器不推荐安装PVE,不如使用incus性能更好

国际

bash
bash <(wget -qO- --no-check-certificate https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

国内

bash
bash <(wget -qO- --no-check-certificate https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh)

如果你需要更新IPV6信息再查询,那么执行以下命令后再查询

bash
rm -rf /usr/local/bin/pve_ipv6*
+rm -rf /usr/local/bin/pve_check_ipv6*
+rm -rf /usr/local/bin/pve_last_ipv6*

执行本项目的检测环境的命令,展示如下

图片

查询如上的只需使用下面的一键脚本自动创建虚拟机即可,无需手动再修改WEB端设置

图片

查询如上的在使用后续脚本创建了虚拟机后,可能需要手动修改WEB端设置,需要关闭对应每个虚拟机的硬件嵌套虚拟化,如下图

图片

先停止虚拟机再修改,修改完后再开机才能使用NOVNC,不关闭可能导致这个虚拟机有BUG无法使用

如果强行安装PVE开KVM,启动不了的也可以关闭这个选项试试能不能启动虚拟机,导致这些问题的原因就是上面说的,宿主机不支持嵌套虚拟化KVM进行加速

TIP

开设虚拟机前请使用screen挂起执行,避免开设时间过长,SSH不稳定导致中间执行中断



+ \ No newline at end of file diff --git a/guide/pve/pve_qa.html b/guide/pve/pve_qa.html index 7bf5e2bce9..1f47b31f05 100644 --- a/guide/pve/pve_qa.html +++ b/guide/pve/pve_qa.html @@ -5,34 +5,37 @@ 解惑 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

解惑

执行脚本不到30秒机器就掉线了

原装系统执行

systemctl restart networking

看看是不是直接掉线,如果是那就是机器原生有问题,热插拔或者dhcp导致的网络无法自重启,此时建议更换宿主机的系统或DD一个新系统尝试

一般来说这种情况都是出现在独服的Debian11系统上,切换为Debian12系统就没问题了

安装PVE失败且报错显示某些安装包不存在

执行下述命令查询apt的源

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

如果看到

deb file://
-deb cdrom:[

这种开头的行,那么证明宿主机使用的是本地源而不是网络源,需要替换/etc/apt/sources.list的源,如

图片

一样替换为网络源才可使用PVE一键安装脚本进行安装。

替换网络源

国内服务器可使用

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)

国外服务器可使用

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

进行apt源的替换

安装PVE成功但重启后失联

如果什么机器安装PVE成功后WEB可用,但重启失联,请安装成功PVE后,重启前执行以下命令再重启

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
-if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
-    chattr -i /etc/network/interfaces
-    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
-    chattr +i /etc/network/interfaces
-fi

然后将重启失联的机器报给 @spiritlhl_bot 待更新脚本自动修复

安装PVE成功但重启后无法解析网址

常见于低版本的Debian系统(云服务器)安装PVE重启后无论访问什么网址都报错

curl: (6) Could not resolve host:

此时查看文件

cat /etc/resolv.conf

可发现无nameserver开头的语句

需要在web端这个页面设置DNS

screenshot-1708136079861

设置完成后再次查看文件会发现有如下内容

search .
-nameserver 8.8.8.8
-nameserver 8.8.4.4

此时再去请求网址就能解析成功了

安装PVE失败或非Debian系统

如果有什么机器安装不了,着急的可以尝试使用以下仓库的脚本先重装为debian12先

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明,一个常见的问题是机器是raid0不是raid10,需要加参数指定raid的值

如果有空或者还是不行,请联系 @spiritlhl_bot 尝试

非Debian系统也可使用自定义分区的内容自行尝试

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

不小心删除了NAT的映射规则怎么办

先查看

cat /etc/iptables/rules.v4

检测是否有问题,且备份数据到本地避免被覆盖

然后再使用下面的命令映射回来

shell
iptables -t nat -F
-iptables -t filter -F
-service networking restart
-systemctl restart networking.service
-cat /etc/iptables/rules.v4 | iptables-restore

检测是不是商家虚标IPV6子网大小导致无法开设独立IPV6地址的虚拟机/容器

使用以下命令在纯净的未安装ProxmoxVE的机器上测试实际的子网掩码大小

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

如果检测结果为128证明商家虚标子网大小,仅一个IPV6地址无法额外分配给虚拟机/容器。

在现有的 PVE 中纳管新的 PVE(创建 / 加入集群)

为了将两个独立的 Proxmox VE 实例组成一个集群,需满足以下前提条件:

集群前提条件

  1. 主机名唯一
    两个节点的 hostname 不可相同,避免命名冲突。建议使用诸如 pve1pve2 等命名方式。

  2. VMID 唯一
    两台 PVE 上不能存在相同 VMID 的虚拟机或容器。若存在冲突,请调整 VMID 以避免合并时发生冲突。

  3. 网络互通、延迟低
    两台主机之间必须能互相 ping 通,建议网络延迟低(局域网或高速公网),以保障集群通信质量。

创建集群(在任意节点执行)

  1. 登录主节点(如 pve1)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Create Cluster
  3. 输入集群名称(Cluster Name)。
  4. 选择要用于集群通信的网卡(如仅有公网 IP,可选择此网卡)。
  5. 点击 Create 创建集群。
  6. 创建成功后,点击 Join Information,复制该页面显示的信息备用。

PS: 在哪个节点上创建集群都可以,集群中不分主从节点。

加入集群(在第二个节点执行)

  1. 登录待加入节点(如 pve2)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Join Cluster
  3. pve1Join Information 粘贴到输入框中。
  4. 填入 pve1 上具的 root 用户密码到 Peer Password
  5. 点击 Join 开始加入过程。
  6. 等待页面提示成功后,刷新页面或重新登录,即可看到两个节点已组成集群。

集群优势

  • 集群节点间可共享资源、迁移虚拟机。
  • 互传 ISO 镜像或模板更加便捷。

目前已验证的VPS商家

可开设KVM虚拟化的NAT的商家

spartanhost 中的独立服务器的Debian12(Debian11有问题)

interserver 中的VPS或独立服务器

frantech 中的拉斯维加斯第二档

eugamehost 中的美国凤凰城黑五促销款

amhost 中的测试款

digitalocean 中的 Perminu Intel 和 Regular 4核款

skrime 中的 AMD Ryzen KVM Server 最低配款

webdock 中的 AMD KVM Server

4vps 中的 俄罗斯和希腊 测试款

adtaq 中的最低配存储KVM服务器

nocix 中的独立服务器

online.net 中的低配独立服务器的Debian12(Debian11有问题)

OVH 中的 Public Cloud 服务器 需要使用以下命令dd为纯净系统后安装

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明。一个常见的问题是OVH独立服务器进行dd,需要源系统默认重装为raid1的debian12,然后用参数指定dd为raid0,才能成功,使用如下命令

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

只可开设LXC虚拟化的NAT的商家

腾讯云 中的无忧款和特惠款(学生机)

spectraip 中的KVM服务器

Linode 中美国专用CPU的最低配

hosthatch 中的特价高配服务器

hetzner 的cloud服务器

rackdog 的浮动IP的服务器

vultr 的Cloud普通服务器

azure 的普通机器

scaleway 中的ARM架构的服务器

aws 中的ec2实例

Google cloud platform - GCP 的 AMD 服务器

- +
Skip to content

解惑

执行脚本不到30秒机器就掉线了

原装系统执行

systemctl restart networking

看看是不是直接掉线,如果是那就是机器原生有问题,热插拔或者dhcp导致的网络无法自重启,此时建议更换宿主机的系统或DD一个新系统尝试

一般来说这种情况都是出现在独服的Debian11系统上,切换为Debian12系统就没问题了

安装PVE失败且报错显示某些安装包不存在

执行下述命令查询apt的源

shell
grep -r "deb " /etc/apt/sources.list /etc/apt/sources.list.d/

如果看到

deb file://
+deb cdrom:[

这种开头的行,那么证明宿主机使用的是本地源而不是网络源,需要替换/etc/apt/sources.list的源,如

图片

一样替换为网络源才可使用PVE一键安装脚本进行安装。

替换网络源

国内服务器可使用

bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)

国外服务器可使用

bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) --abroad

进行apt源的替换

安装PVE成功但重启后失联

如果什么机器安装PVE成功后WEB可用,但重启失联,请安装成功PVE后,重启前执行以下命令再重启

bash
auto_interface=$(grep '^auto ' /etc/network/interfaces | grep -v '^auto lo' | awk '{print $2}' | head -n 1)
+if ! grep -q "^post-up /sbin/ethtool" /etc/network/interfaces; then
+    chattr -i /etc/network/interfaces
+    echo "post-up /sbin/ethtool -K $auto_interface tx off rx off" >> /etc/network/interfaces
+    chattr +i /etc/network/interfaces
+fi

然后将重启失联的机器报给 @spiritlhl_bot 待更新脚本自动修复

安装PVE成功但重启后无法解析网址

常见于低版本的Debian系统(云服务器)安装PVE重启后无论访问什么网址都报错

curl: (6) Could not resolve host:

此时查看文件

cat /etc/resolv.conf

可发现无nameserver开头的语句

需要在web端这个页面设置DNS

screenshot-1708136079861

设置完成后再次查看文件会发现有如下内容

search .
+nameserver 8.8.8.8
+nameserver 8.8.4.4

此时再去请求网址就能解析成功了

安装PVE失败或非Debian系统

如果有什么机器安装不了,着急的可以尝试使用以下仓库的脚本先重装为debian12先

bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明,一个常见的问题是机器是raid0不是raid10,需要加参数指定raid的值

如果有空或者还是不行,请联系 @spiritlhl_bot 尝试

非Debian系统也可使用自定义分区的内容自行尝试

开设centos7发现报错CGroupV1不支持怎么办

启用CGroup V1:要在Ubuntu系统上启用CGroup V1,需要编辑内核启动参数。

请注意,在更改内核启动参数之前,请务必备份重要的数据和设置,以防止意外的问题。

编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX_DEFAULT中的参数末尾加上systemd.unified_cgroup_hierarchy=0,如

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=0"

保存文件并运行以下命令更新GRUB引导。

bash
sudo update-grub

重启系统,使更改生效

如果上述更改仍旧不支持开设centos7,那么请使用别的宿主机系统尝试

不小心删除了NAT的映射规则怎么办

先查看

cat /etc/iptables/rules.v4

检测是否有问题,且备份数据到本地避免被覆盖

然后再使用下面的命令映射回来

shell
iptables -t nat -F
+iptables -t filter -F
+service networking restart
+systemctl restart networking.service
+cat /etc/iptables/rules.v4 | iptables-restore

检测是不是商家虚标IPV6子网大小导致无法开设独立IPV6地址的虚拟机/容器

使用以下命令在纯净的未安装ProxmoxVE的机器上测试实际的子网掩码大小

国际

shell
curl -L https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/spiritLHLS/ecs/main/archive/eo6s.sh -o eo6s.sh && chmod +x eo6s.sh && bash eo6s.sh

如果检测结果为128证明商家虚标子网大小,仅一个IPV6地址无法额外分配给虚拟机/容器。

在现有的 PVE 中纳管新的 PVE(创建 / 加入集群)

为了将两个独立的 Proxmox VE 实例组成一个集群,需满足以下前提条件:

集群前提条件

  1. 主机名唯一
    两个节点的 hostname 不可相同,避免命名冲突。建议使用诸如 pve1pve2 等命名方式。

  2. VMID 唯一
    两台 PVE 上不能存在相同 VMID 的虚拟机或容器。若存在冲突,请调整 VMID 以避免合并时发生冲突。

  3. 网络互通、延迟低
    两台主机之间必须能互相 ping 通,建议网络延迟低(局域网或高速公网),以保障集群通信质量。

创建集群(在任意节点执行)

  1. 登录主节点(如 pve1)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Create Cluster
  3. 输入集群名称(Cluster Name)。
  4. 选择要用于集群通信的网卡(如仅有公网 IP,可选择此网卡)。
  5. 点击 Create 创建集群。
  6. 创建成功后,点击 Join Information,复制该页面显示的信息备用。

PS: 在哪个节点上创建集群都可以,集群中不分主从节点。

加入集群(在第二个节点执行)

  1. 登录待加入节点(如 pve2)Web 管理界面。
  2. 依次点击:Datacenter → Cluster → Join Cluster
  3. pve1Join Information 粘贴到输入框中。
  4. 填入 pve1 上具的 root 用户密码到 Peer Password
  5. 点击 Join 开始加入过程。
  6. 等待页面提示成功后,刷新页面或重新登录,即可看到两个节点已组成集群。

集群优势

  • 集群节点间可共享资源、迁移虚拟机。
  • 互传 ISO 镜像或模板更加便捷。

目前已验证的VPS商家

可开设KVM虚拟化的NAT的商家

spartanhost 中的独立服务器的Debian12(Debian11有问题)

interserver 中的VPS或独立服务器

frantech 中的拉斯维加斯第二档

eugamehost 中的美国凤凰城黑五促销款

amhost 中的测试款

digitalocean 中的 Perminu Intel 和 Regular 4核款

skrime 中的 AMD Ryzen KVM Server 最低配款

webdock 中的 AMD KVM Server

4vps 中的 俄罗斯和希腊 测试款

adtaq 中的最低配存储KVM服务器

nocix 中的独立服务器

online.net 中的低配独立服务器的Debian12(Debian11有问题)

OVH 中的 Public Cloud 服务器 需要使用以下命令dd为纯净系统后安装

shell
bash <(curl -sSL https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh) -debian 12 -pwd 'oneclickvirt139' --network "static"

此时dd后的系统用户名为root,密码为oneclickvirt139

如果不成功,请查看 https://github.com/leitbogioro/Tools 中的issues和说明。一个常见的问题是OVH独立服务器进行dd,需要源系统默认重装为raid1的debian12,然后用参数指定dd为raid0,才能成功,使用如下命令

shell
wget --no-check-certificate -qO InstallNET.sh 'https://raw.githubusercontent.com/leitbogioro/Tools/master/Linux_reinstall/InstallNET.sh' && chmod a+x InstallNET.sh && bash InstallNET.sh -debian 12  -mirror "http://ftp.debian.org/debian/" -pwd oneclickvirt139 -raid 0

只可开设LXC虚拟化的NAT的商家

腾讯云 中的无忧款和特惠款(学生机)

spectraip 中的KVM服务器

Linode 中美国专用CPU的最低配

hosthatch 中的特价高配服务器

hetzner 的cloud服务器

rackdog 的浮动IP的服务器

vultr 的Cloud普通服务器

azure 的普通机器

scaleway 中的ARM架构的服务器

aws 中的ec2实例

Google cloud platform - GCP 的 AMD 服务器

+ \ No newline at end of file diff --git a/guide/pve/pve_thanks.html b/guide/pve/pve_thanks.html index 75b2e0bf02..2ccea68d30 100644 --- a/guide/pve/pve_thanks.html +++ b/guide/pve/pve_thanks.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
- +
Skip to content
+ \ No newline at end of file diff --git a/guide/pve/pve_windows.html b/guide/pve/pve_windows.html index 638cba0dc1..49dbcc4690 100644 --- a/guide/pve/pve_windows.html +++ b/guide/pve/pve_windows.html @@ -5,24 +5,27 @@ 开设Windows虚拟机 | 一键虚拟化项目 - + + + - - - - - - + + + + + + - + + -
Skip to content
On this page

开设Windows虚拟机

开设时选择KVM虚拟化还是QEMU的TCG仿真

宿主机本身如果支持嵌套虚拟化,那么就可用hostkvm64qemu64类型的CPU

从性能上来说,host > kvm64 > qemu64

qemu类型虚拟化性能损耗很多

如果本身不支持嵌套虚拟化,那么只能用qemu64类型的CPU,且需要在启动虚拟机前修改Options[选项]中的KVM hardware virtualization[KVM硬件虚拟化]

设置为no取消Enabled[启用]的勾选

kvm

如果你实在不清楚本机是否支持嵌套虚拟化,那么查看 系统与硬件配置要求 --> 检测环境 检测确保可用(含尝试性启用功能)

它的主体逻辑在

https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh

这块的逻辑中,主要检测

egrep -c '(vmx|svm)' /proc/cpuinfo 检测是否为1

cat /sys/module/kvm_intel/parameters/nested是否存在且为1

lsmod | grep -q kvm检测是否已加载

这些都支持的时候,才可选host类型。

使用带virtio的iso镜像文件开设

1.下载镜像

安装需要提前下载镜像文件local(pve) --> ISO images --> Download from URL

下载链接URL:可使用

https://github.com/ILLKX/Windows-VirtIO

中的文件链接,文件名字File Name:win.iso

download

点击下载Download,下载完成后当前的页面可见win.iso的文件大小,可见格式为iso。

downloaded

2.设置模板

页面顶部右上角点击Create VM

General窗口中,Resource Pool:勾选mypoolName填写win,然后点击Next

general

OS窗口中,ISO image勾选win.isoGuest OS勾选TypeMicrosoft Windows类型,Version选择当前ISOwin的版本,示例下载是2022,就选11/2022类型,然后点击Next

OS

System窗口中,Graphic card勾选VirtIO-GPU类型,Machine勾选q35类型,SCSI Controller勾选VirtIO SCSI类型,BIOS勾选Default (SeaBIOS)类型,然后点击Next

system

Disk窗口中,Cache勾选Write Back类型,Disk size (GiB)填写你要分配的硬盘大小,一般不小于20Storage选择存储在哪个盘,示例只有系统盘local所以就选loacl,然后点击Next

disk

CPU窗口中,Cores填写所需核数,CPU类型按照前面描述的方法选择,然后点击Next

cpu

Memory窗口中,Memory (MiB)填写所需内存大小,然后点击Next

memory

Network窗口中,Bridge勾选vmbr1类型,Model勾选VirtIO (paravirtualized)类型,Firewall取消勾选,然后点击Next

Network

Confirm窗口中,点击Finish

finish

3.图形化配置安装

左侧点击设置好的模板,右上角点击Start启动虚拟机,然后点击Console进入VNC界面,等待操作系统启动。

console

然后在VNC中点击下一页,然后点击现在安装,然后点击我没有产品密钥,然后勾选接受许可,点击下一页,然后勾选自定义安装

win0

win1

win2

win3

win4

然后如果镜像本身带virtio,那么应该可见可选系统存储的硬盘及其大小,选中后点击下一页

win5

win6

然后等待系统安装,应该会自动重启几次,大概耗时10分钟以上。

win7

安装完成后首次登录会要求设置密码,正常设置即可

win8

设置完成后,NOVNC页面左侧有一个弹出框,点击第一个按钮,然后根据登录提示,点击Ctrl+Alt+最后一个按钮,进入登录页面。

4.初始化网络

由于通过本项目设置的PVE是静态网络,所以登陆后需要手动修改绑定的IP地址,不通过DHCP

在桌面右下角右击点出打开 网络和Internet设置,点击后,在弹出的设置页面中点击更改适配器设置

win9

然后在网络链接中勾选以太网,点击更改此连接的设置

win10

在弹出框中点击Internet协议版本4(TCP/IPV4)选中后点击属性

win11

在新弹出的弹出框中,选择并点击使用下面的IP地址(s),然后分别填入

IP地址(I):172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码(U):255.255.255.0

默认网关(D):172.16.1.1

然后选择点击使用下面的DNS服务器地址(E),分别填入

8.8.8.8
-144.144.144.144

然后右下角点击确定,注意不要勾选退出时验证

win12

然后其他弹出框都选确定就行了,然后本虚拟机就有网络了。

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

使用不带virtio的iso镜像开设

1.下载镜像

无virtio的win镜像下载可使用

https://down.idc.wiki/ISOS/Windows/

这块的镜像

virtio的iso镜像可使用

https://down.idc.wiki/ISOS/Toolkit/

或者

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

下载

virtio也可以只下载msi包,本地用软件打包成iso压缩格式再本地上传到ProxmoxVE中也可以

这样的话包小一些,前者官方的是包含所有WIN镜像支持的包总计500MB左右,后者自己打包5MB左右

2.virtio导入

注意这里的导入在ProxmoxVE的8.x及之后的版本中,OS这一栏默认可选择virtio启动加载,如图所示

virtio

而在更低版本的ProxmoxVE中,比如7.x和6.x的版本,OS这一栏默认无法选择virtio启动加载

lower

需要手动在Hardware[硬件]中点击Add[添加]添加CD/DVD Drive选择下载好的virtioISO文件

lower

然后其他的一切照常,直到

nodisk

这块找不到硬盘,需要选择加载驱动程序

nodisk

然后选择驱动盘virtio的,点击打开,从amd64那导入对应系统名字的驱动

nodisk

我的是windows server 2019的镜像所以导入的是2k19的驱动,导入完毕后选择导入的驱动,点击下一页

nodisk

nodisk

这样就能看得到硬盘了,选中后继续后续的安装步骤,选中后继续后续的安装步骤如同前面的教程,直到系统安装完毕,进入桌面。

3.通过virtio-win-guest-tools安装驱动

此时安装成功,出现桌面后,还需要手动安装驱动

打开VirtIO驱动所在的CD光驱目录,最下面有一个virtio-win-guest-tools程序,会安装用到的virtio驱动,这个驱动也会包含virtio的网卡驱动

wk

wk

wk

点击安装完毕后就安装上网卡驱动了,后续网络设置参考前面的初始化网络的教程

4.安装网卡驱动(备选)

此时安装成功,出现桌面后,还需要手动安装网卡驱动才能连通网络:

  1. 打开 控制面板设备管理器
  2. 找到 以太网控制器,右键选择 更新驱动程序
  3. 选择 浏览我的计算机以查找驱动程序软件 (R)
  4. 浏览到VirtIO驱动所在的CD光驱目录
  5. 打开其中的 NetKVM 文件夹
  6. 根据当前系统版本选择对应的驱动文件夹(和上面相同的操作,我会选择2k19文件夹,里面的amd64驱动)
  7. 确认安装,完成后即可成功加载VirtIO的网卡驱动

wk

wk

wk

后续网络设置参考前面的初始化网络的教程

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

- +
Skip to content

开设Windows虚拟机

开设时选择KVM虚拟化还是QEMU的TCG仿真

宿主机本身如果支持嵌套虚拟化,那么就可用hostkvm64qemu64类型的CPU

从性能上来说,host > kvm64 > qemu64

qemu类型虚拟化性能损耗很多

如果本身不支持嵌套虚拟化,那么只能用qemu64类型的CPU,且需要在启动虚拟机前修改Options[选项]中的KVM hardware virtualization[KVM硬件虚拟化]

设置为no取消Enabled[启用]的勾选

kvm

如果你实在不清楚本机是否支持嵌套虚拟化,那么查看 系统与硬件配置要求 --> 检测环境 检测确保可用(含尝试性启用功能)

它的主体逻辑在

https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pve/main/scripts/check_kernal.sh

这块的逻辑中,主要检测

egrep -c '(vmx|svm)' /proc/cpuinfo 检测是否为1

cat /sys/module/kvm_intel/parameters/nested是否存在且为1

lsmod | grep -q kvm检测是否已加载

这些都支持的时候,才可选host类型。

使用带virtio的iso镜像文件开设

1.下载镜像

安装需要提前下载镜像文件local(pve) --> ISO images --> Download from URL

下载链接URL:可使用

https://github.com/ILLKX/Windows-VirtIO

中的文件链接,文件名字File Name:win.iso

download

点击下载Download,下载完成后当前的页面可见win.iso的文件大小,可见格式为iso。

downloaded

2.设置模板

页面顶部右上角点击Create VM

General窗口中,Resource Pool:勾选mypoolName填写win,然后点击Next

general

OS窗口中,ISO image勾选win.isoGuest OS勾选TypeMicrosoft Windows类型,Version选择当前ISOwin的版本,示例下载是2022,就选11/2022类型,然后点击Next

OS

System窗口中,Graphic card勾选VirtIO-GPU类型,Machine勾选q35类型,SCSI Controller勾选VirtIO SCSI类型,BIOS勾选Default (SeaBIOS)类型,然后点击Next

system

Disk窗口中,Cache勾选Write Back类型,Disk size (GiB)填写你要分配的硬盘大小,一般不小于20Storage选择存储在哪个盘,示例只有系统盘local所以就选loacl,然后点击Next

disk

CPU窗口中,Cores填写所需核数,CPU类型按照前面描述的方法选择,然后点击Next

cpu

Memory窗口中,Memory (MiB)填写所需内存大小,然后点击Next

memory

Network窗口中,Bridge勾选vmbr1类型,Model勾选VirtIO (paravirtualized)类型,Firewall取消勾选,然后点击Next

Network

Confirm窗口中,点击Finish

finish

3.图形化配置安装

左侧点击设置好的模板,右上角点击Start启动虚拟机,然后点击Console进入VNC界面,等待操作系统启动。

console

然后在VNC中点击下一页,然后点击现在安装,然后点击我没有产品密钥,然后勾选接受许可,点击下一页,然后勾选自定义安装

win0

win1

win2

win3

win4

然后如果镜像本身带virtio,那么应该可见可选系统存储的硬盘及其大小,选中后点击下一页

win5

win6

然后等待系统安装,应该会自动重启几次,大概耗时10分钟以上。

win7

安装完成后首次登录会要求设置密码,正常设置即可

win8

设置完成后,NOVNC页面左侧有一个弹出框,点击第一个按钮,然后根据登录提示,点击Ctrl+Alt+最后一个按钮,进入登录页面。

4.初始化网络

由于通过本项目设置的PVE是静态网络,所以登陆后需要手动修改绑定的IP地址,不通过DHCP

在桌面右下角右击点出打开 网络和Internet设置,点击后,在弹出的设置页面中点击更改适配器设置

win9

然后在网络链接中勾选以太网,点击更改此连接的设置

win10

在弹出框中点击Internet协议版本4(TCP/IPV4)选中后点击属性

win11

在新弹出的弹出框中,选择并点击使用下面的IP地址(s),然后分别填入

IP地址(I):172.16.1.xxx(xxx换成你想绑定的ip,我的vmid是100,为了方便写了100)

子网掩码(U):255.255.255.0

默认网关(D):172.16.1.1

然后选择点击使用下面的DNS服务器地址(E),分别填入

8.8.8.8
+144.144.144.144

然后右下角点击确定,注意不要勾选退出时验证

win12

然后其他弹出框都选确定就行了,然后本虚拟机就有网络了。

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

使用不带virtio的iso镜像开设

1.下载镜像

无virtio的win镜像下载可使用

https://down.idc.wiki/ISOS/Windows/

这块的镜像

virtio的iso镜像可使用

https://down.idc.wiki/ISOS/Toolkit/

或者

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/

下载

virtio也可以只下载msi包,本地用软件打包成iso压缩格式再本地上传到ProxmoxVE中也可以

这样的话包小一些,前者官方的是包含所有WIN镜像支持的包总计500MB左右,后者自己打包5MB左右

2.virtio导入

注意这里的导入在ProxmoxVE的8.x及之后的版本中,OS这一栏默认可选择virtio启动加载,如图所示

virtio

而在更低版本的ProxmoxVE中,比如7.x和6.x的版本,OS这一栏默认无法选择virtio启动加载

lower

需要手动在Hardware[硬件]中点击Add[添加]添加CD/DVD Drive选择下载好的virtioISO文件

lower

然后其他的一切照常,直到

nodisk

这块找不到硬盘,需要选择加载驱动程序

nodisk

然后选择驱动盘virtio的,点击打开,从amd64那导入对应系统名字的驱动

nodisk

我的是windows server 2019的镜像所以导入的是2k19的驱动,导入完毕后选择导入的驱动,点击下一页

nodisk

nodisk

这样就能看得到硬盘了,选中后继续后续的安装步骤,选中后继续后续的安装步骤如同前面的教程,直到系统安装完毕,进入桌面。

3.通过virtio-win-guest-tools安装驱动

此时安装成功,出现桌面后,还需要手动安装驱动

打开VirtIO驱动所在的CD光驱目录,最下面有一个virtio-win-guest-tools程序,会安装用到的virtio驱动,这个驱动也会包含virtio的网卡驱动

wk

wk

wk

点击安装完毕后就安装上网卡驱动了,后续网络设置参考前面的初始化网络的教程

4.安装网卡驱动(备选)

此时安装成功,出现桌面后,还需要手动安装网卡驱动才能连通网络:

  1. 打开 控制面板设备管理器
  2. 找到 以太网控制器,右键选择 更新驱动程序
  3. 选择 浏览我的计算机以查找驱动程序软件 (R)
  4. 浏览到VirtIO驱动所在的CD光驱目录
  5. 打开其中的 NetKVM 文件夹
  6. 根据当前系统版本选择对应的驱动文件夹(和上面相同的操作,我会选择2k19文件夹,里面的amd64驱动)
  7. 确认安装,完成后即可成功加载VirtIO的网卡驱动

wk

wk

wk

后续网络设置参考前面的初始化网络的教程

5.取消CD盘挂载

在ProxmoxVE的web端手动在Hardware[硬件]中点击对应的CD选择Remove[删除]然后再重启虚拟机,这样就能直接使用了

wk

+ \ No newline at end of file diff --git a/hashmap.json b/hashmap.json index 1992376187..cc29abc573 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"en_guide_block_block_pve.md":"86088ae1","en_guide_block_block_incus.md":"95762549","case_case7.md":"b84f4c02","en_guide_block_block_iptables.md":"6506e0bc","en_guide_docker_docker_install.md":"2b0bb4e4","en_guide_docker_docker_custom.md":"4e05a2c3","en_guide_docker_docker_precheck.md":"a9b1c276","en_guide_docker_docker_qa.md":"fed2a991","developer_l10n.md":"f381c679","en_developer_index.md":"a033415e","en_guide_incus_incus_install.md":"ce7c0d18","en_incomplete_cockpit.md":"a60c11d2","en_incomplete_convoy.md":"ccd54afd","en_guide_docker_docker_macos.md":"48b99172","en_incomplete_virtualizor-docker.md":"449703b7","case_case3.md":"8bd8db2f","en_incomplete_index.md":"675215c6","en_incomplete_pterodactyl.md":"df0ba4ff","en_guide_block_block_lxd.md":"616a5093","en_guide_lxd_lxd_thanks.md":"bbb08af5","en_incomplete_webvirtcloud_retspen.md":"8ec2f567","en_incomplete_webvirtmgr.md":"611aa9ab","en_index.md":"83e2fa26","en_incomplete_virtfusion.md":"e7f03a8b","guide_block_block_iptables.md":"56fd36c5","guide_block_block_lxd.md":"cf1b102e","guide_block_block_pve.md":"0b046fe8","guide_dashboard.md":"7c9eeb09","guide_incus_incus_qa.md":"780b508f","en_guide_dashboard.md":"04c46e68","case_case5.md":"991f7ced","en_developer_l10n.md":"2567a7c2","guide_lxd_lxd_install.md":"8dc77da5","case_case4.md":"14b56d9f","guide_lxd_lxd_precheck.md":"42adf95c","en_guide_incus_incus_qa.md":"bea92aa8","guide_lxd_lxd_qa.md":"44833073","guide_lxd_lxd_thanks.md":"6aebeab6","guide_pve_images_readme.md":"e91db2b4","guide_pve_pve_android.md":"5728ca62","case_case6.md":"d14d2ac7","guide_block_block_docker.md":"5830a230","en_guide_lxd_lxd_precheck.md":"995523b7","en_guide_docker_docker_windows.md":"aeb5b431","en_guide_dashboardq.md":"220142b4","en_guide_docker_docker_android.md":"ffbfb237","en_guide_pve_images_readme.md":"f8849b0b","guide_incus_incus_lxc.md":"3de28e6b","guide_block_block_incus.md":"9da06b17","en_guide_incus_incus_thanks.md":"5f3fccbe","guide_incus_incus_windows.md":"5ba7b2ce","en_guide_pve_pve_android.md":"bc9044ee","en_guide_lxd_lxd_extra_config.md":"3ce9da2c","guide_incus_incus_thanks.md":"4ec3421d","guide_pve_pve_custom.md":"c31784f7","en_guide_lxd_lxd_windows.md":"586d29ea","developer_index.md":"4b11aa55","guide_lxd_lxd_custom.md":"20323fda","en_guide_pve_pve_install.md":"69e0d919","en_incomplete_bashvm.md":"fce6926b","en_guide_block_block_docker.md":"2627dfbd","guide_pve_pve_lxc.md":"704d4792","en_guide_pve_pve_kvm.md":"97ca4d66","en_guide_lxd_lxd_install.md":"b53a57be","en_guide_incus_incus_lxc.md":"c5c0a6f8","en_guide_docker_docker_build.md":"5395d3b9","en_guide_pve_pve_qa.md":"3406e13c","guide_dashboardq.md":"02164389","en_guide_lxd_lxd_qa.md":"7268ae8d","case_index.md":"259f5ee0","en_guide_pve_pve_lxc.md":"5f264fc4","guide_lxd_lxd_lxc.md":"728ada33","guide_incus_incus_install.md":"ba70a2a0","en_guide_pve_pve_precheck.md":"2c6a4e25","en_guide_pve_pve_custom.md":"4615a36e","guide_docker_docker_android.md":"c556d7ea","case_case2.md":"d9673a40","en_guide_pve_pve_macos.md":"785a524c","en_guide_incus_incus_extra_config.md":"06d84d9b","en_guide_pve_pve_thanks.md":"dc0491f9","en_guide_pve_pve_windows.md":"923bbd33","en_guide_incus_incus_precheck.md":"44458de1","guide_docker_docker_custom.md":"01bd0eed","guide_docker_docker_macos.md":"7497eb24","guide_docker_docker_install.md":"69dee249","guide_docker_docker_precheck.md":"78609506","guide_docker_docker_qa.md":"94f80b81","guide_docker_docker_thanks.md":"4049eaf0","guide_docker_docker_windows.md":"9011d893","en_guide_lxd_lxd_custom.md":"f8616b5f","guide_lxd_lxd_extra_config.md":"c1ea1bc8","index.md":"33ff85ee","en_incomplete_webvirtcloud.md":"a6e9dff8","case_case1.md":"3cf726ff","guide_incus_incus_extra_config.md":"91dfbfa5","en_guide_incus_incus_windows.md":"7fb5eecc","incomplete_webvirtcloud_retspen.md":"8469ad25","guide_incus_incus_custom.md":"b1aba773","guide_pve_pve_macos.md":"21762f54","en_guide_docker_docker_thanks.md":"d7efa635","guide_incus_incus_precheck.md":"6bf5b424","guide_pve_pve_precheck.md":"2c856c99","guide_lxd_lxd_windows.md":"9b33f709","en_guide_lxd_lxd_lxc.md":"5c2b1e85","guide_pve_pve_install.md":"b9ed6cd8","guide_pve_pve_qa.md":"76a49097","incomplete_virtfusion.md":"a22bdacd","incomplete_virtualizor-docker.md":"a05fb0f7","incomplete_bashvm.md":"e680b5ae","incomplete_cockpit.md":"77e4fe67","en_guide_incus_incus_custom.md":"f6f0e581","guide_pve_pve_kvm.md":"43713910","incomplete_convoy.md":"f7a4bd52","incomplete_pterodactyl.md":"16ac57df","incomplete_index.md":"13d9bf0c","incomplete_webvirtmgr.md":"d2161404","guide_docker_docker_build.md":"d0d61806","guide_pve_pve_thanks.md":"3bbf24dc","incomplete_webvirtcloud.md":"2369e889","guide_pve_pve_windows.md":"37289db4"} +{"case_case1.md":"URFLodrr","case_case2.md":"CDLx6tKM","case_case3.md":"Dr71EzwR","case_case4.md":"BCt0xHGw","case_case5.md":"D0hZllGZ","case_case6.md":"DBcKFtJZ","case_case7.md":"Ca88kvzN","case_index.md":"D_IkUok9","developer_index.md":"CXHgEkLk","developer_l10n.md":"DbKLx65f","en_developer_index.md":"zTlMOyHV","en_developer_l10n.md":"CFaXJ2l2","en_guide_block_block_docker.md":"Bu7zbkEq","en_guide_block_block_incus.md":"BTs-piI_","en_guide_block_block_iptables.md":"ByV6snur","en_guide_block_block_lxd.md":"BToyiHH5","en_guide_block_block_pve.md":"Bi62dGs9","en_guide_dashboard.md":"CwRb4UsX","en_guide_dashboardq.md":"BaUPP2a8","en_guide_docker_docker_android.md":"BulF4nM1","en_guide_docker_docker_build.md":"DvGO9A3O","en_guide_docker_docker_custom.md":"CoAvHe_n","en_guide_docker_docker_install.md":"DMUsaTt3","en_guide_docker_docker_macos.md":"DItPel8U","en_guide_docker_docker_precheck.md":"BrsWou7M","en_guide_docker_docker_qa.md":"q3nJoH_p","en_guide_docker_docker_thanks.md":"CLSD9Nhw","en_guide_docker_docker_windows.md":"CDb3Bppx","en_guide_incus_incus_custom.md":"DUBzNIug","en_guide_incus_incus_extra_config.md":"BkutcTAl","en_guide_incus_incus_install.md":"BgEyJdKz","en_guide_incus_incus_lxc.md":"BxXye95l","en_guide_incus_incus_precheck.md":"DeMpsPcV","en_guide_incus_incus_qa.md":"L3eCjNtY","en_guide_incus_incus_thanks.md":"CjY9f-A0","en_guide_incus_incus_windows.md":"CPQ_HdzK","en_guide_lxd_lxd_custom.md":"-wt5FjRv","en_guide_lxd_lxd_extra_config.md":"BsivFFBx","en_guide_lxd_lxd_install.md":"z7YfDjTq","en_guide_lxd_lxd_lxc.md":"xW6rYEDm","en_guide_lxd_lxd_precheck.md":"COYnNjKf","en_guide_lxd_lxd_qa.md":"Bs8c7UP0","en_guide_lxd_lxd_thanks.md":"CeZBLRKW","en_guide_lxd_lxd_windows.md":"CDGEBwH6","en_guide_pve_images_readme.md":"Dq3BR6Q6","en_guide_pve_pve_android.md":"D8JpIji1","en_guide_pve_pve_custom.md":"BNwEwNPy","en_guide_pve_pve_install.md":"DG8IYoZ0","en_guide_pve_pve_kvm.md":"CutjUOCm","en_guide_pve_pve_lxc.md":"DacQBeid","en_guide_pve_pve_macos.md":"Cy9mzi8X","en_guide_pve_pve_precheck.md":"Dc6vpMBO","en_guide_pve_pve_qa.md":"BYBr2UQn","en_guide_pve_pve_thanks.md":"Dw43XV-y","en_guide_pve_pve_windows.md":"vqwXYaPa","en_incomplete_bashvm.md":"DWaL7zdf","en_incomplete_cockpit.md":"DKGXpcw0","en_incomplete_convoy.md":"ClbXbvA3","en_incomplete_index.md":"B8q1NrDT","en_incomplete_pterodactyl.md":"CFqYcu_4","en_incomplete_virtfusion.md":"C7tkSFJE","en_incomplete_virtualizor-docker.md":"CKtWMSs2","en_incomplete_webvirtcloud.md":"DfzbkCBK","en_incomplete_webvirtcloud_retspen.md":"CjZPDsE1","en_incomplete_webvirtmgr.md":"8Ub32E-h","en_index.md":"DhJzLyfV","guide_block_block_docker.md":"C-tufkRV","guide_block_block_incus.md":"D3fB2bDD","guide_block_block_iptables.md":"DkS3brgv","guide_block_block_lxd.md":"BrbV-k4o","guide_block_block_pve.md":"BntEIKAB","guide_dashboard.md":"D2bjCnlL","guide_dashboardq.md":"DGJ9X51L","guide_docker_docker_android.md":"DyBMNwLg","guide_docker_docker_build.md":"DoAlFeWZ","guide_docker_docker_custom.md":"uaKETGnt","guide_docker_docker_install.md":"DkBio7r4","guide_docker_docker_macos.md":"B-ddHhbN","guide_docker_docker_precheck.md":"Dgik3VYv","guide_docker_docker_qa.md":"BAZeywiq","guide_docker_docker_thanks.md":"CMHMSDTy","guide_docker_docker_windows.md":"BAGQZpoB","guide_incus_incus_custom.md":"Bm8HnEPC","guide_incus_incus_extra_config.md":"AJ5M0HDo","guide_incus_incus_install.md":"BmXHRJpC","guide_incus_incus_lxc.md":"CcPIDp5T","guide_incus_incus_precheck.md":"DTFAD1HQ","guide_incus_incus_qa.md":"D2Pi0dJG","guide_incus_incus_thanks.md":"DJw_BEEC","guide_incus_incus_windows.md":"CFcsS3lD","guide_lxd_lxd_custom.md":"gEdxHFHM","guide_lxd_lxd_extra_config.md":"DhbmRlmf","guide_lxd_lxd_install.md":"D4zH3hWU","guide_lxd_lxd_lxc.md":"PKqgxyhI","guide_lxd_lxd_precheck.md":"BDmkuKzJ","guide_lxd_lxd_qa.md":"C4FXk4za","guide_lxd_lxd_thanks.md":"oRZKHNsx","guide_lxd_lxd_windows.md":"CpTtBXvV","guide_pve_images_readme.md":"ZJUoqm_K","guide_pve_pve_android.md":"DauuQgmC","guide_pve_pve_custom.md":"0uRKiuWM","guide_pve_pve_install.md":"CdRZOjQC","guide_pve_pve_kvm.md":"DiXxjdva","guide_pve_pve_lxc.md":"D_RYunJp","guide_pve_pve_macos.md":"CRq8lCuz","guide_pve_pve_precheck.md":"Bwa9qWce","guide_pve_pve_qa.md":"KEIUXkXN","guide_pve_pve_thanks.md":"DqgEZrWa","guide_pve_pve_windows.md":"CLu8AekJ","incomplete_bashvm.md":"B5fMrqJh","incomplete_cockpit.md":"HGnaxkEA","incomplete_convoy.md":"CxPU1hOM","incomplete_index.md":"CYVk98K2","incomplete_pterodactyl.md":"ywtPLv_5","incomplete_virtfusion.md":"DnaD-J8U","incomplete_virtualizor-docker.md":"BgClRxGW","incomplete_webvirtcloud.md":"4rNDyChD","incomplete_webvirtcloud_retspen.md":"BzOOyV6B","incomplete_webvirtmgr.md":"y6DQ_-c0","index.md":"BVw2CyLu"} diff --git a/incomplete/bashvm.html b/incomplete/bashvm.html index 6592c54a4c..1a736e0ca6 100644 --- a/incomplete/bashvm.html +++ b/incomplete/bashvm.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/babywhale321/bashvm

https://bashvm.com/

说明

如果你想深入了解怎么开设一个虚拟机,怎么转发端口,那么这个项目将完全从底层开始,一步步教你如何开设虚拟机

缺点

非常的繁琐,非常的耗时,不如别的项目快速设置网络和开设

- +
Skip to content

仓库

https://github.com/babywhale321/bashvm

https://bashvm.com/

说明

如果你想深入了解怎么开设一个虚拟机,怎么转发端口,那么这个项目将完全从底层开始,一步步教你如何开设虚拟机

缺点

非常的繁琐,非常的耗时,不如别的项目快速设置网络和开设

+ \ No newline at end of file diff --git a/incomplete/cockpit.html b/incomplete/cockpit.html index 3794460822..df55610c89 100644 --- a/incomplete/cockpit.html +++ b/incomplete/cockpit.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

hits

https://github.com/oneclickvirt/cockpit

安装

支持的系统:Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

只安装带容器的

shell
bash install.sh --ct

只安装带虚拟机的

shell
bash install.sh --vm

仅安装面板

shell
bash install.sh

容器和虚拟机依赖都进行安装

shell
bash install.sh --all

缺点

网络自行配置,镜像自行导入,端口自行映射,只是比纯命令行多了一个GUI界面罢了

致谢

https://cockpit-project.org/running.html

- +
Skip to content

仓库

hits

https://github.com/oneclickvirt/cockpit

安装

支持的系统:Debian,Ubuntu,Almalinux,Rockylinux,Fedora,Centos,Arch

国际

shell
curl -L https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/cockpit/refs/heads/main/scripts/install.sh -o install.sh && chmod +x install.sh

只安装带容器的

shell
bash install.sh --ct

只安装带虚拟机的

shell
bash install.sh --vm

仅安装面板

shell
bash install.sh

容器和虚拟机依赖都进行安装

shell
bash install.sh --all

缺点

网络自行配置,镜像自行导入,端口自行映射,只是比纯命令行多了一个GUI界面罢了

致谢

https://cockpit-project.org/running.html

+ \ No newline at end of file diff --git a/incomplete/convoy.html b/incomplete/convoy.html index 1595f96ec1..6dc25c7ba2 100644 --- a/incomplete/convoy.html +++ b/incomplete/convoy.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

安装前提条件:

  • 已安装 PVE,但不能是同一节点(不能是同一台机器)
  • 系统为 Debian 11
  • CPU 至少 2 核,硬盘至少 20G,内存至少 4G(内存包含 swap)

我不保证这个脚本没有错误,本项目未完整

国际

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

- +
Skip to content

Repo

https://github.com/oneclickvirt/convoypanel-scripts

hits

convoypanel-scripts

安装前提条件:

  • 已安装 PVE,但不能是同一节点(不能是同一台机器)
  • 系统为 Debian 11
  • CPU 至少 2 核,硬盘至少 20G,内存至少 4G(内存包含 swap)

我不保证这个脚本没有错误,本项目未完整

国际

shell
curl -L https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

国内

shell
curl -L https://cdn.spiritlhl.net/https://github.com/oneclickvirt/convoypanel-scripts/raw/main/installconvoy.sh -o installconvoy.sh && chmod +x installconvoy.sh && bash installconvoy.sh

Thanks

Base on https://github.com/oneclickvirt/pve

Base on https://docs.convoypanel.com/guide/deployment/#installation

Base on https://github.com/ConvoyPanel/panel

+ \ No newline at end of file diff --git a/incomplete/index.html b/incomplete/index.html index 3b78062533..7823e5c86b 100644 --- a/incomplete/index.html +++ b/incomplete/index.html @@ -5,22 +5,25 @@ 其他虚拟化项目 | 其他不完整的虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content

其他虚拟化项目

一些不完整的虚拟化项目

- +
Skip to content

其他虚拟化项目一些不完整的虚拟化项目

+ \ No newline at end of file diff --git a/incomplete/pterodactyl.html b/incomplete/pterodactyl.html index 3254678dab..45e0e749c7 100644 --- a/incomplete/pterodactyl.html +++ b/incomplete/pterodactyl.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

进一步调研发现开设servers和绑定用户极麻烦,不如原生直接docker方便,故而暂不做后续开发了

说明

目前支持的系统

系统类型版本范围备注
Ubuntu20.04(推荐), 22.04, 24.04已支持
Debian11(Bullseye), 12(Bookworm)已支持

Panel

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

wings端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

会生成需要在wings端执行的命令

生成的命令执行完毕后等待20秒以上,避免一些初始化流程未走完,然后wings端再执行:

shell
bash install_wings.sh

然后在http://<your_ip>/admin/nodes就能看到你的节点已经被自动添加纳管,心跳是绿色的

Thanks

https://pterodactyl.io/

- +
Skip to content

Repo

https://github.com/oneclickvirt/pterodactyl

hits

pterodactyl-scripts

进一步调研发现开设servers和绑定用户极麻烦,不如原生直接docker方便,故而暂不做后续开发了

说明

目前支持的系统

系统类型版本范围备注
Ubuntu20.04(推荐), 22.04, 24.04已支持
Debian11(Bullseye), 12(Bookworm)已支持

Panel

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_pterodactyl.sh -o install_pterodactyl.sh && chmod 777 install_pterodactyl.sh && bash install_pterodactyl.sh

Wings

wings端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/install_wings.sh -o install_wings.sh && chmod 777 install_wings.sh && bash install_wings.sh

Import

panel端执行:

国际

shell
curl -slk https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

国内

shell
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/pterodactyl/main/scripts/import_node.sh -o import_node.sh && chmod 777 import_node.sh && bash import_node.sh

会生成需要在wings端执行的命令

生成的命令执行完毕后等待20秒以上,避免一些初始化流程未走完,然后wings端再执行:

shell
bash install_wings.sh

然后在http://<your_ip>/admin/nodes就能看到你的节点已经被自动添加纳管,心跳是绿色的

Thanks

https://pterodactyl.io/

+ \ No newline at end of file diff --git a/incomplete/virtfusion.html b/incomplete/virtfusion.html index 450b28a4a9..e6f94919ba 100644 --- a/incomplete/virtfusion.html +++ b/incomplete/virtfusion.html @@ -3,30 +3,33 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

官方文档

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

一键安装

debian11

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
-curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
-curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

缺点

每台服务器每个邮箱只有一次30天试用的证书,无永久的免费的证书

- +
Skip to content

官方文档

https://docs.virtfusion.com/next/installation/control-server/#activating-a-license

一键安装

debian11

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-11.sh | sh -s -- --verbose

debian12

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-debian-12.sh | sh -s -- --verbose

RHEL8

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-8.sh | sh -s -- --verbose

RHEL9

shell
dnf install curl -y
+curl https://install.virtfusion.net/install-control-rhel-9.sh | sh -s -- --verbose

Ubuntu22.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-22.04.sh | sh -s -- --verbose

Ubuntu24.04

shell
apt install curl -y
+curl https://install.virtfusion.net/install-control-ubuntu-24.04.sh | sh -s -- --verbose

缺点

每台服务器每个邮箱只有一次30天试用的证书,无永久的免费的证书

+ \ No newline at end of file diff --git a/incomplete/virtualizor-docker.html b/incomplete/virtualizor-docker.html index eae8b7de26..55018d2ba2 100644 --- a/incomplete/virtualizor-docker.html +++ b/incomplete/virtualizor-docker.html @@ -3,24 +3,27 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

仓库

https://github.com/ivstiv/virtualizor-docker

说明

在docker中开设的 virtualizor

证书用的是试用的证书,有效期一天,且默认只安装了OpenVZ的虚拟化方式

缺点

毫无社区,一切自行摸索

admin面板的端口不要看脚本的提示信息,以仓库说明为准。

- +
Skip to content

仓库

https://github.com/ivstiv/virtualizor-docker

说明

在docker中开设的 virtualizor

证书用的是试用的证书,有效期一天,且默认只安装了OpenVZ的虚拟化方式

缺点

毫无社区,一切自行摸索

admin面板的端口不要看脚本的提示信息,以仓库说明为准。

+ \ No newline at end of file diff --git a/incomplete/webvirtcloud.html b/incomplete/webvirtcloud.html index ef48b9a70a..1892be7855 100644 --- a/incomplete/webvirtcloud.html +++ b/incomplete/webvirtcloud.html @@ -5,69 +5,72 @@ WebVirtCloud 安装指南 | 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/webvirtcloud/webvirtcloud

应该算是全网中文第一份完整的部署指南,官方的指南实际上有很多地方是和本项目部署的方式有出入的。

1. 控制端安装

系统要求

最低配置要求:

  • CPU: 1 核
  • 内存: 1 GB RAM
  • 硬盘: 空余 10 GB
  • 系统:Debian11+,Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

默认登录信息

  • 用户名: admin@webvirt.cloud
  • 密码: admin

面板地址

  • 用户面板: https://192-168-0-114.nip.io
  • 管理后台: https://192-168-0-114.nip.io/admin

注意: 请将 192.168.0.114 替换为你的公网 IP,以获取真实可访问地址。

安装命令

国际版本:

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
-&& chmod +x install_webvirt_cloud.sh \
-&& bash install_webvirt_cloud.sh

国内版本:

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
-&& chmod +x install_webvirt_cloud.sh \
-&& bash install_webvirt_cloud.sh

TIP

执行过程中可能会卡在clone仓库后一直不动,此时按ctrl+c退出执行后,重新执行安装脚本就行了,系Docker安装后卡在build项目的阶段了。

2. 计算节点安装

重要提示: Hypervisor 和 Controller 不能在同一虚拟机上安装,否则网络会出现冲突。

系统要求

建议配置:

  • CPU: 2 核
  • 内存: 4 GB RAM
  • 硬盘: 空余 40 GB
  • 系统:AlmaLinux8+,RockyLinux8+

额外说明:

  • 实际使用建议更高配置,测试环境只够开 4 台最小的虚拟机。
  • 服务器推荐支持 KVM 嵌套虚拟化的,若VM-x/AMD-V/Hyper-V未启用也可以,会自动切换为QEMU使用TCG仿真开设虚拟机,只不过性能会有所损耗。
  • 跳过 env 检测安装,直接使用二进制文件,无需安装依赖。

环境检测

检测服务器是否支持 KVM 嵌套虚拟化:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

选择硬件单项测试

计算节点安装步骤

  1. 下载安装脚本:

    国际版本:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    -&& chmod +x install_hypervisor.sh

    国内版本:

    bash
    curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    -&& chmod +x install_hypervisor.sh
  2. 执行安装(替换为你的 Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    请将 x.x.x.x 替换为你的 Controller 控制端的实际 IP 地址。

  3. 面板纳管节点
    执行完毕后会有提示需要在Controller面板端需要填写的内容。
    面板端要填入Hostname的是当前计算节点的IPV4地址,还有要填入Token识别节点。

NetworkManager 版本问题

安装过程中可能会出现以下错误:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
-Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
-Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

解决方法: 重启服务器后重新执行安装命令。

安装耗时提示

  • 整个过程大约耗时 10~25 分钟
  • 大部分时间用于下载 finnix-125.iso/var/lib/libvirt/isos/finnix-125.iso
  • 该部分无法加速,建议使用 tmux 或 screen 等工具防止中断。

添加计算节点到控制面板

安装完成后会生成一个 Token,用于在控制端(Admin 面板)中添加计算节点:

路径: Admin Panel > Computers > Add Computer

  • HostName 需要填写计算节点的公网IPV4地址
  • Token 填在计算节点上获取到的token密钥

3. 公网IPV4端口映射

3.1 自动映射

自动映射功能特点:

  • 自动监控:实时监控虚拟机状态变化,自动应用或清理端口映射规则
  • 智能端口分配:根据虚拟机IP地址自动计算和分配不冲突的端口
  • 规则持久化:使用firewall-cmd确保端口映射规则在宿主机重启后依然有效
  • 映射记录:自动维护映射信息记录文件,便于查看和管理
  • 冲突防护:智能检测并避免端口冲突,确保每个虚拟机都有唯一的端口映射

安装方法

  1. 下载脚本到临时目录: 国际版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh

    国内版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. 添加执行权限:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. 运行安装程序:

    bash
    /tmp/vm_port_mapping_setup.sh

脚本会自动完成以下操作:

  • 将自身复制到系统目录 /usr/local/sbin/vm_port_mapping_daemon.sh
  • 创建systemd服务单元文件
  • 启用并启动服务

端口映射规则

守护进程会为每个虚拟机分配以下端口:

  1. SSH端口

    • 计算公式:(IP最后一段) × 100 + 22 + 10000
    • 示例:对于IP地址 192.168.33.114,映射的SSH端口为 114×100+22+10000 = 21422
  2. 额外端口

    • 每个虚拟机分配10个额外端口
    • 起始端口:20000 + (IP最后一段) × 100
    • 结束端口:起始端口 + 9
    • 示例:对于IP地址 192.168.33.114,额外端口范围为 20000+(114×100) 至 20000+(114×100)+9

如果计算出的端口已被占用,程序会自动寻找下一个可用端口,确保不发生冲突。

映射文件

所有端口映射信息保存在 /etc/vm_port_mapping/mapping.txt 文件中,格式为:

虚拟机名字 IP地址 MAC地址 SSH映射端口 额外端口起始 额外端口结束

例如:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

服务管理

  • 查看服务状态

    bash
    systemctl status vm-port-mapping
  • 启动服务

    bash
    systemctl start vm-port-mapping
  • 停止服务

    bash
    systemctl stop vm-port-mapping
  • 禁用自启动

    bash
    systemctl disable vm-port-mapping
  • 查看日志

    bash
    journalctl -u vm-port-mapping
    -# 或
    -cat /var/log/vm_port_mapping.log
  • 手动触发规则更新

    bash
    systemctl restart vm-port-mapping

常见问题

端口映射不生效

检查以下内容:

  • 确认服务正在运行:systemctl status vm-port-mapping
  • 检查日志文件:cat /var/log/vm_port_mapping.log
  • 确认防火墙服务正常:systemctl status firewalld
  • 验证虚拟机网络接口配置:virsh domiflist 虚拟机名称
手动添加映射规则

通常不需要手动添加规则,但如果需要,可以这样操作:

  1. 停止服务:

    bash
    systemctl stop vm-port-mapping
  2. 编辑映射文件:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. 启动服务:

    bash
    systemctl start vm-port-mapping
清理所有规则
bash
systemctl stop vm-port-mapping
-grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
-  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
-  for ((port=port_start; port<=port_end; port++)); do
-    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
-  done
-done
-firewall-cmd --reload
安全建议
  • 定期检查映射文件和日志,确保没有未授权的映射
  • 不要手动修改 /etc/vm_port_mapping/ 目录下的文件,除非你完全了解其影响
  • 确保 firewalld 服务正常运行,以便规则能够正确持久化

卸载方法

如需卸载此服务:

bash
systemctl stop vm-port-mapping
-systemctl disable vm-port-mapping
-rm -f /etc/systemd/system/vm-port-mapping.service
-rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
-rm -rf /etc/vm_port_mapping
-systemctl daemon-reload

3.2 手动映射

假设此时你的虚拟机在用户端控制面板显示为

wv1

且宿主机的命令执行ip a | head -n 15结果为

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-       valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
-    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
-    altname enp0s3
-    inet 你的公网IPV4地址/对应的子网掩码 scope global noprefixroute ens3
-       valid_lft forever preferred_lft forever
-    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
-       valid_lft forever preferred_lft forever
-    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
-       valid_lft forever preferred_lft forever

可见公网IPV4地址绑定的接口是ens3,所以后面的命令这里用ens3

那么映射当前虚拟机的22端口到公网IPV4的3322端口的命令为:

shell
# 添加 DNAT 规则:将公网3322流量转发到宿主机本地的192.168.33.130:22
-iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
-# 添加 POSTROUTING:本机 NAT 伪装,以便连接正常返回
-iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
-# 需要允许 INPUT 的3322端口通过(firewalld 默认是开启了的)
-iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

这样内网的虚拟机就被映射出来,可以直接远程登录使用了。

4. 问题排查

添加计算节点错误排查

在Controller控制端执行:

shell
telnet <node ip> 8884

在计算节点执行:

shell
systemctl status webvirtcompute
-systemctl status libvirtd
-systemctl status prometheus
-systemctl status prometheus-libvirt-exporter

如果以上都查不出问题,那么就需要到Controller控制端执行:

shell
docker exec -it webvirtcloud-backend /bin/sh
-vi webvirtcloud/settings/production.py

DEBUG=False 改成 DEBUG=True,然后保存文件后,容器内执行:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

然后exit退出容器后,执行:

shell
docker restart webvirtcloud-backend
-sleep 3
-docker logs webvirtcloud-backend -f

然后前端去触发错误的位置,这块日志实时加载就会看到对应的报错了。

Controller 重启后 Docker 容器不自重启

如果 Docker 容器在系统重启后没有自动重启,执行以下命令:

bash
docker start $(docker ps -a -q)

5. 缺点

系统镜像是写死的,没法使用自己制作的自定义镜像,也没办法导出使用。

https://github.com/retspen/webvirtcloud 不是同一个项目,不要搞混淆了。

致谢

https://webvirt.cloud/

- +
Skip to content

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/webvirtcloud/webvirtcloud

应该算是全网中文第一份完整的部署指南,官方的指南实际上有很多地方是和本项目部署的方式有出入的。

1. 控制端安装

系统要求

最低配置要求:

  • CPU: 1 核
  • 内存: 1 GB RAM
  • 硬盘: 空余 10 GB
  • 系统:Debian11+,Ubuntu20.04+, Centos8+, AlmaLinux8+, RockyLinux8+

默认登录信息

  • 用户名: admin@webvirt.cloud
  • 密码: admin

面板地址

  • 用户面板: https://192-168-0-114.nip.io
  • 管理后台: https://192-168-0-114.nip.io/admin

注意: 请将 192.168.0.114 替换为你的公网 IP,以获取真实可访问地址。

安装命令

国际版本:

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
+&& chmod +x install_webvirt_cloud.sh \
+&& bash install_webvirt_cloud.sh

国内版本:

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud.sh -o install_webvirt_cloud.sh \
+&& chmod +x install_webvirt_cloud.sh \
+&& bash install_webvirt_cloud.sh

TIP

执行过程中可能会卡在clone仓库后一直不动,此时按ctrl+c退出执行后,重新执行安装脚本就行了,系Docker安装后卡在build项目的阶段了。

2. 计算节点安装

重要提示: Hypervisor 和 Controller 不能在同一虚拟机上安装,否则网络会出现冲突。

系统要求

建议配置:

  • CPU: 2 核
  • 内存: 4 GB RAM
  • 硬盘: 空余 40 GB
  • 系统:AlmaLinux8+,RockyLinux8+

额外说明:

  • 实际使用建议更高配置,测试环境只够开 4 台最小的虚拟机。
  • 服务器推荐支持 KVM 嵌套虚拟化的,若VM-x/AMD-V/Hyper-V未启用也可以,会自动切换为QEMU使用TCG仿真开设虚拟机,只不过性能会有所损耗。
  • 跳过 env 检测安装,直接使用二进制文件,无需安装依赖。

环境检测

检测服务器是否支持 KVM 嵌套虚拟化:

bash
curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && ./goecs.sh install && goecs

选择硬件单项测试

计算节点安装步骤

  1. 下载安装脚本:

    国际版本:

    bash
    curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    +&& chmod +x install_hypervisor.sh

    国内版本:

    bash
    curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_hypervisor.sh -o install_hypervisor.sh \
    +&& chmod +x install_hypervisor.sh
  2. 执行安装(替换为你的 Controller IP):

    bash
    bash install_hypervisor.sh x.x.x.x

    请将 x.x.x.x 替换为你的 Controller 控制端的实际 IP 地址。

  3. 面板纳管节点
    执行完毕后会有提示需要在Controller面板端需要填写的内容。
    面板端要填入Hostname的是当前计算节点的IPV4地址,还有要填入Token识别节点。

NetworkManager 版本问题

安装过程中可能会出现以下错误:

Connection 'eth0' (bed050e9-ff49-4665-8112-24ddf2a1cd3c) successfully deleted.
+Warning: nmcli (1.48.10) and NetworkManager (1.42.2) versions don't match. Restarting NetworkManager is advised.
+Error: Failed to add 'br-ext' connection: connection.autoconnect-ports: unknown property

解决方法: 重启服务器后重新执行安装命令。

安装耗时提示

  • 整个过程大约耗时 10~25 分钟
  • 大部分时间用于下载 finnix-125.iso/var/lib/libvirt/isos/finnix-125.iso
  • 该部分无法加速,建议使用 tmux 或 screen 等工具防止中断。

添加计算节点到控制面板

安装完成后会生成一个 Token,用于在控制端(Admin 面板)中添加计算节点:

路径: Admin Panel > Computers > Add Computer

  • HostName 需要填写计算节点的公网IPV4地址
  • Token 填在计算节点上获取到的token密钥

3. 公网IPV4端口映射

3.1 自动映射

自动映射功能特点:

  • 自动监控:实时监控虚拟机状态变化,自动应用或清理端口映射规则
  • 智能端口分配:根据虚拟机IP地址自动计算和分配不冲突的端口
  • 规则持久化:使用firewall-cmd确保端口映射规则在宿主机重启后依然有效
  • 映射记录:自动维护映射信息记录文件,便于查看和管理
  • 冲突防护:智能检测并避免端口冲突,确保每个虚拟机都有唯一的端口映射

安装方法

  1. 下载脚本到临时目录: 国际版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh

    国内版本:

    bash
    wget -O /tmp/vm_port_mapping_setup.sh https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/refs/heads/main/extra_scripts/vm_port_mapping_daemon.sh
  2. 添加执行权限:

    bash
    chmod +x /tmp/vm_port_mapping_setup.sh
  3. 运行安装程序:

    bash
    /tmp/vm_port_mapping_setup.sh

脚本会自动完成以下操作:

  • 将自身复制到系统目录 /usr/local/sbin/vm_port_mapping_daemon.sh
  • 创建systemd服务单元文件
  • 启用并启动服务

端口映射规则

守护进程会为每个虚拟机分配以下端口:

  1. SSH端口

    • 计算公式:(IP最后一段) × 100 + 22 + 10000
    • 示例:对于IP地址 192.168.33.114,映射的SSH端口为 114×100+22+10000 = 21422
  2. 额外端口

    • 每个虚拟机分配10个额外端口
    • 起始端口:20000 + (IP最后一段) × 100
    • 结束端口:起始端口 + 9
    • 示例:对于IP地址 192.168.33.114,额外端口范围为 20000+(114×100) 至 20000+(114×100)+9

如果计算出的端口已被占用,程序会自动寻找下一个可用端口,确保不发生冲突。

映射文件

所有端口映射信息保存在 /etc/vm_port_mapping/mapping.txt 文件中,格式为:

虚拟机名字 IP地址 MAC地址 SSH映射端口 额外端口起始 额外端口结束

例如:

Virtance-1 192.168.33.114 52:54:00:5f:77:92 21422 31400 31409

服务管理

  • 查看服务状态

    bash
    systemctl status vm-port-mapping
  • 启动服务

    bash
    systemctl start vm-port-mapping
  • 停止服务

    bash
    systemctl stop vm-port-mapping
  • 禁用自启动

    bash
    systemctl disable vm-port-mapping
  • 查看日志

    bash
    journalctl -u vm-port-mapping
    +# 或
    +cat /var/log/vm_port_mapping.log
  • 手动触发规则更新

    bash
    systemctl restart vm-port-mapping

常见问题

端口映射不生效

检查以下内容:

  • 确认服务正在运行:systemctl status vm-port-mapping
  • 检查日志文件:cat /var/log/vm_port_mapping.log
  • 确认防火墙服务正常:systemctl status firewalld
  • 验证虚拟机网络接口配置:virsh domiflist 虚拟机名称
手动添加映射规则

通常不需要手动添加规则,但如果需要,可以这样操作:

  1. 停止服务:

    bash
    systemctl stop vm-port-mapping
  2. 编辑映射文件:

    bash
    nano /etc/vm_port_mapping/mapping.txt
  3. 启动服务:

    bash
    systemctl start vm-port-mapping
清理所有规则
bash
systemctl stop vm-port-mapping
+grep -f /etc/vm_port_mapping/mapping.txt | while read -r vm_name ip_address mac ssh_port port_start port_end; do
+  firewall-cmd --permanent --remove-forward-port="port=$ssh_port:proto=tcp:toport=22:toaddr=$ip_address"
+  for ((port=port_start; port<=port_end; port++)); do
+    firewall-cmd --permanent --remove-forward-port="port=$port:proto=tcp:toport=$port:toaddr=$ip_address"
+  done
+done
+firewall-cmd --reload
安全建议
  • 定期检查映射文件和日志,确保没有未授权的映射
  • 不要手动修改 /etc/vm_port_mapping/ 目录下的文件,除非你完全了解其影响
  • 确保 firewalld 服务正常运行,以便规则能够正确持久化

卸载方法

如需卸载此服务:

bash
systemctl stop vm-port-mapping
+systemctl disable vm-port-mapping
+rm -f /etc/systemd/system/vm-port-mapping.service
+rm -f /usr/local/sbin/vm_port_mapping_daemon.sh
+rm -rf /etc/vm_port_mapping
+systemctl daemon-reload

3.2 手动映射

假设此时你的虚拟机在用户端控制面板显示为

wv1

且宿主机的命令执行ip a | head -n 15结果为

shell
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+    inet 127.0.0.1/8 scope host lo
+       valid_lft forever preferred_lft forever
+    inet6 ::1/128 scope host
+       valid_lft forever preferred_lft forever
+2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
+    link/ether 52:54:00:f1:d6:8b brd ff:ff:ff:ff:ff:ff
+    altname enp0s3
+    inet 你的公网IPV4地址/对应的子网掩码 scope global noprefixroute ens3
+       valid_lft forever preferred_lft forever
+    inet6 2a0b:4140:4c60::2/48 scope global noprefixroute
+       valid_lft forever preferred_lft forever
+    inet6 fe80::5054:ff:fef1:d68b/64 scope link noprefixroute
+       valid_lft forever preferred_lft forever

可见公网IPV4地址绑定的接口是ens3,所以后面的命令这里用ens3

那么映射当前虚拟机的22端口到公网IPV4的3322端口的命令为:

shell
# 添加 DNAT 规则:将公网3322流量转发到宿主机本地的192.168.33.130:22
+iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 3322 -j DNAT --to-destination 192.168.33.130:22
+# 添加 POSTROUTING:本机 NAT 伪装,以便连接正常返回
+iptables -t nat -A POSTROUTING -p tcp -d 192.168.33.130 --dport 22 -j MASQUERADE
+# 需要允许 INPUT 的3322端口通过(firewalld 默认是开启了的)
+iptables -I INPUT -p tcp --dport 3322 -j ACCEPT

这样内网的虚拟机就被映射出来,可以直接远程登录使用了。

4. 问题排查

添加计算节点错误排查

在Controller控制端执行:

shell
telnet <node ip> 8884

在计算节点执行:

shell
systemctl status webvirtcompute
+systemctl status libvirtd
+systemctl status prometheus
+systemctl status prometheus-libvirt-exporter

如果以上都查不出问题,那么就需要到Controller控制端执行:

shell
docker exec -it webvirtcloud-backend /bin/sh
+vi webvirtcloud/settings/production.py

DEBUG=False 改成 DEBUG=True,然后保存文件后,容器内执行:

shell
UV_PROJECT_ENVIRONMENT=/usr/local uv sync --dev

然后exit退出容器后,执行:

shell
docker restart webvirtcloud-backend
+sleep 3
+docker logs webvirtcloud-backend -f

然后前端去触发错误的位置,这块日志实时加载就会看到对应的报错了。

Controller 重启后 Docker 容器不自重启

如果 Docker 容器在系统重启后没有自动重启,执行以下命令:

bash
docker start $(docker ps -a -q)

5. 缺点

系统镜像是写死的,没法使用自己制作的自定义镜像,也没办法导出使用。

https://github.com/retspen/webvirtcloud 不是同一个项目,不要搞混淆了。

致谢

https://webvirt.cloud/

+ \ No newline at end of file diff --git a/incomplete/webvirtcloud_retspen.html b/incomplete/webvirtcloud_retspen.html index dd98fd4f33..cc2c77ba19 100644 --- a/incomplete/webvirtcloud_retspen.html +++ b/incomplete/webvirtcloud_retspen.html @@ -3,30 +3,33 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtcloud

控制节点和计算节点同时安装

  • 支持系统:Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • 推荐系统:Debian12+,Ubuntu22.04+
  • 低版本系统会自动编译python新版本的安装包后再进行部署,所以推荐使用新系统不必编译直接安装

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
-&& chmod +x install_webvirt_cloud_retspen.sh \
-&& bash install_webvirt_cloud_retspen.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
-&& chmod +x install_webvirt_cloud_retspen.sh \
-&& bash install_webvirt_cloud_retspen.sh

安装完成后打开公网IP地址,就能看到登录页面。

登录信息用户名和密码都是admin,记得登录后自行修改。

开设Linux虚拟机

进入控制面板后,修改完admin的密码后,需要自行设置计算节点。

vcr1

选择本地类型,添加命名为local。

vcr2

创建完成后,点击眼睛按钮,进入查看

vcr3

存储一栏中添加存储,选择Dir类型,添加名字叫local。如果你需要使用ISO类型的系统引导,那么需要创建ISO类型的存储,如果不需要的话跟着本指南走,就仅需要创建Dir类型。

vcr4

vcr5

创建完毕后,下载对应系统的qcow2文件,使用下面这个仓库的链接

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

示例中下载使用debian12的qcow2镜像使用

shell
cd /var/lib/libvirt/images
-wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
-chmod 777 debian12.qcow2

回到实例页面创建实例

vcr6

计算节点选择local

vcr7

芯片组使用默认的就行,换不换都没问题

vcr8

创建虚拟机可以使用预定义的配置大小,也可以自行使用自定义大小,看你的选择。

vcr9

注意这块填写的实例名字不能和系统名字重复,比如示例中就不能填写debian12

vcr10

创建成功后不能立即点击开机。

vcr11

需要修改磁盘设置。

vcr12

这块修改qcow2文件为debian12.qcow2,对应之前下载的qcow2的文件的名字,使用镜像。

vcr13

修改完成确认无误后,才可回到电源页面开机。

vcr14

镜像的默认登录的用户名是root,密码是password或者是 oneclickvirt

缺点

网络还是没有自动配置,不如上一个项目智能,还得手动配置一下。

- +
Skip to content

WebVirtCloud 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtcloud

控制节点和计算节点同时安装

  • 支持系统:Debian10+, Ubuntu18.04+, Centos8+, AlmaLinux8+, RockyLinux8+
  • 推荐系统:Debian12+,Ubuntu22.04+
  • 低版本系统会自动编译python新版本的安装包后再进行部署,所以推荐使用新系统不必编译直接安装

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
+&& chmod +x install_webvirt_cloud_retspen.sh \
+&& bash install_webvirt_cloud_retspen.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirt_cloud_retspen.sh -o install_webvirt_cloud_retspen.sh \
+&& chmod +x install_webvirt_cloud_retspen.sh \
+&& bash install_webvirt_cloud_retspen.sh

安装完成后打开公网IP地址,就能看到登录页面。

登录信息用户名和密码都是admin,记得登录后自行修改。

开设Linux虚拟机

进入控制面板后,修改完admin的密码后,需要自行设置计算节点。

vcr1

选择本地类型,添加命名为local。

vcr2

创建完成后,点击眼睛按钮,进入查看

vcr3

存储一栏中添加存储,选择Dir类型,添加名字叫local。如果你需要使用ISO类型的系统引导,那么需要创建ISO类型的存储,如果不需要的话跟着本指南走,就仅需要创建Dir类型。

vcr4

vcr5

创建完毕后,下载对应系统的qcow2文件,使用下面这个仓库的链接

https://github.com/oneclickvirt/pve_kvm_images/releases/tag/images

示例中下载使用debian12的qcow2镜像使用

shell
cd /var/lib/libvirt/images
+wget https://github.com/oneclickvirt/pve_kvm_images/releases/download/images/debian12.qcow2
+chmod 777 debian12.qcow2

回到实例页面创建实例

vcr6

计算节点选择local

vcr7

芯片组使用默认的就行,换不换都没问题

vcr8

创建虚拟机可以使用预定义的配置大小,也可以自行使用自定义大小,看你的选择。

vcr9

注意这块填写的实例名字不能和系统名字重复,比如示例中就不能填写debian12

vcr10

创建成功后不能立即点击开机。

vcr11

需要修改磁盘设置。

vcr12

这块修改qcow2文件为debian12.qcow2,对应之前下载的qcow2的文件的名字,使用镜像。

vcr13

修改完成确认无误后,才可回到电源页面开机。

vcr14

镜像的默认登录的用户名是root,密码是password或者是 oneclickvirt

缺点

网络还是没有自动配置,不如上一个项目智能,还得手动配置一下。

+ \ No newline at end of file diff --git a/incomplete/webvirtmgr.html b/incomplete/webvirtmgr.html index a41bd8cd7d..c350104284 100644 --- a/incomplete/webvirtmgr.html +++ b/incomplete/webvirtmgr.html @@ -3,28 +3,31 @@ - 一键虚拟化项目 | 一键虚拟化项目 + 一键虚拟化项目 - + + + - - - - - + + + + + - + + -
Skip to content
On this page

WebVirtMgr 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtmgr

控制节点和计算节点同时安装

  • 支持系统:Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • 系统会自动编译python的2.7的安装包后再进行部署,编译过程中会有报错提示但不用理会,只要脚本还在跑就说明一切正常

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
-&& chmod +x install_webvirtmgr.sh \
-&& bash install_webvirtmgr.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
-&& chmod +x install_webvirtmgr.sh \
-&& bash install_webvirtmgr.sh

缺点

原项目已经不再有维护,完全不推荐使用。

- +
Skip to content

WebVirtMgr 安装指南

hits

仓库地址: https://github.com/oneclickvirt/webvirtcloud

原项目对应仓库:https://github.com/retspen/webvirtmgr

控制节点和计算节点同时安装

  • 支持系统:Debian[8,9,10],Ubuntu[16.04,18.04,20.04]
  • 系统会自动编译python的2.7的安装包后再进行部署,编译过程中会有报错提示但不用理会,只要脚本还在跑就说明一切正常

国际

bash
curl -slk https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
+&& chmod +x install_webvirtmgr.sh \
+&& bash install_webvirtmgr.sh

国内

bash
curl -slk https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/webvirtcloud/main/scripts/install_webvirtmgr.sh -o install_webvirtmgr.sh \
+&& chmod +x install_webvirtmgr.sh \
+&& bash install_webvirtmgr.sh

缺点

原项目已经不再有维护,完全不推荐使用。

+ \ No newline at end of file diff --git a/index.html b/index.html index bfb08f1e8f..8f9fb02e61 100644 --- a/index.html +++ b/index.html @@ -5,22 +5,25 @@ 库苏恩 - + + + - - - - - + + + + + - + + -
Skip to content

一键虚拟化项目

开源、易于使用的服务器虚拟化项目

- +
Skip to content

一键虚拟化项目开源、易于使用的服务器虚拟化项目

+ \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 92126a8b0a..3d19b63479 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://www.spiritlhl.net/case/case1.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/developer/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/dashboard.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_build.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/block/block_docker.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_android.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/bashvm.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case4.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case5.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case3.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case6.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case7.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/case2.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/case/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/developer/l10n.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/dashboardq.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_macos.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_extra_config.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/incus/incus_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_extra_config.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_kvm.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/cockpit.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/convoy.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/virtfusion.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/pterodactyl.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/virtualizor-docker.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/webvirtcloud.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/webvirtcloud_retspen.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/index.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/incomplete/webvirtmgr.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/block/block_docker.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/images/readme.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/developer/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_android.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/bashvm.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/images/readme.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/developer/l10n.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/block/block_incus.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/block/block_pve.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/block/block_iptables.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/block/block_lxd.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/dashboard.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/dashboardq.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_build.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_macos.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_extra_config.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_extra_config.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_android.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_custom.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_kvm.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_install.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_lxc.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_thanks.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_precheck.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_qa.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/cockpit.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/convoy.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/pterodactyl.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/virtfusion.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtcloud.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/virtualizor-docker.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtcloud_retspen.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtmgr.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/block/block_lxd.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/block/block_incus.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/block/block_iptables.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/block/block_pve.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/docker/docker_android.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_macos.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_windows.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_macos.html2025-05-23T03:47:28.000Zhttps://www.spiritlhl.net/guide/pve/pve_windows.html2025-05-23T03:47:28.000Z \ No newline at end of file +https://www.spiritlhl.net/case/case1.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/developer/l10n.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case2.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case5.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case3.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case4.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case6.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/case7.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/case/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/developer/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/developer/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/images/readme.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_extra_config.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/bashvm.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/developer/l10n.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/dashboard.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/dashboardq.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_android.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_build.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_macos.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/docker/docker_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_extra_config.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/incus/incus_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/lxd/lxd_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_kvm.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_android.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/cockpit.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/convoy.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/virtualizor-docker.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/virtfusion.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/pterodactyl.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtcloud.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_macos.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/pve/pve_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/block/block_docker.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/block/block_incus.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/block/block_iptables.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/block/block_lxd.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/guide/block/block_pve.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtcloud_retspen.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/dashboard.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_android.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/incomplete/webvirtmgr.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/en/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/dashboardq.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_build.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/block/block_docker.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_android.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/bashvm.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/block/block_incus.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/block/block_lxd.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/block/block_iptables.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/block/block_pve.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/docker/docker_macos.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_extra_config.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/incus/incus_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_windows.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_custom.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_install.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_kvm.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/lxd/lxd_extra_config.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_lxc.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_precheck.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_qa.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_thanks.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/cockpit.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/convoy.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/pterodactyl.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/virtfusion.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/virtualizor-docker.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/webvirtcloud.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/webvirtcloud_retspen.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/incomplete/webvirtmgr.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/index.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/images/readme.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_macos.html2025-05-23T07:22:42.000Zhttps://www.spiritlhl.net/guide/pve/pve_windows.html2025-05-23T07:22:42.000Z \ No newline at end of file diff --git a/vp-icons.css b/vp-icons.css new file mode 100644 index 0000000000..ddc5bd8edb --- /dev/null +++ b/vp-icons.css @@ -0,0 +1 @@ +.vpi-social-github{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")} \ No newline at end of file
Skip to content
On this page

仓库

Hits

Hits

融合怪测评项目

(GO版本除非必须的环境安装使用shell外无额外shell文件依赖,环境安装只是为了测的更准,极端情况下无环境依赖也可全测项目)

如有问题请 issues 反馈。

Go 版本:https://github.com/oneclickvirt/ecs

Shell 版本:https://github.com/spiritLHLS/ecs


适配系统和架构

编译与测试支持情况

编译支持的架构测试支持的架构编译支持的系统测试支持的系统
amd64amd64LinuxLinux
armarmWindowsWindows
arm64arm64FreeBSDFreeBSD
386386OpenBSD
mipsMacOS
mipsle
s390xs390x
riscv64

功能

本项目初次使用建议查看说明:跳转


使用说明

Linux/FreeBSD/OpenBSD/MacOS

一键命令

一键命令默认安装依赖默认更新包管理器默认非互动模式

  • 国际用户无加速:

    bash
    export noninteractive=true && curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
  • 国际/国内使用 CDN 加速:

    bash
    export noninteractive=true && curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs
  • 国内用户使用 CNB 加速:

    bash
    export noninteractive=true && curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh && bash goecs.sh env && bash goecs.sh install && goecs

详细说明

详细说明中的命令可控制是否安装依赖是否更新包管理器默认互动模式可进行选择

  1. 下载脚本

    国际用户无加速:

    bash
    curl -L https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国际/国内使用 CDN 加速:

    bash
    curl -L https://cdn.spiritlhl.net/https://raw.githubusercontent.com/oneclickvirt/ecs/master/goecs.sh -o goecs.sh && chmod +x goecs.sh

    国内用户使用 CNB 加速:

    bash
    curl -L https://cnb.cool/oneclickvirt/ecs/-/git/raw/main/goecs.sh -o goecs.sh && chmod +x goecs.sh
  2. 更新包管理器(可选择)并安装环境

    bash
    ./goecs.sh env

    非互动模式:

    bash
    export noninteractive=true && ./goecs.sh env
  3. 安装 goecs

    bash
    ./goecs.sh install
  4. 升级 goecs

    bash
    ./goecs.sh upgrade
  5. 卸载 goecs

    bash
    ./goecs.sh uninstall
  6. 帮助命令

    bash
    ./goecs.sh -h
  7. 唤起菜单

    bash
    goecs

命令参数化

bash
Usage: goecs [options]
-  -backtrace
-        Enable/Disable backtrace test (in 'en' language or on windows it always false) (default true)
-  -basic
-        Enable/Disable basic test (default true)
-  -comm
-        Enable/Disable common media test (default true)
-  -cpu
-        Enable/Disable CPU test (default true)
-  -cpum string
-        Set CPU test method (supported: sysbench, geekbench, winsat) (default "sysbench")
-  -cput string
-        Set CPU test thread mode (supported: single, multi) (default "multi")
-  -disk
-        Enable/Disable disk test (default true)
-  -diskm string
-        Set disk test method (supported: fio, dd, winsat) (default "fio")
-  -diskmc
-        Enable/Disable multiple disk checks, e.g., -diskmc=false
-  -diskp string
-        Set disk test path, e.g., -diskp /root
-  -email
-        Enable/Disable email port test (default true)
-  -h    Show help information
-  -l string
-        Set language (supported: en, zh) (default "zh")
-  -log
-        Enable/Disable logging in the current path
-  -memory
-        Enable/Disable memory test (default true)
-  -memorym string
-        Set memory test method (supported: sysbench, dd, winsat) (default "sysbench")
-  -menu
-        Enable/Disable menu mode, disable example: -menu=false (default true)
-  -nt3
-        Enable/Disable NT3 test (in 'en' language or on windows it always false) (default true)
-  -nt3loc string
-        Specify NT3 test location (supported: GZ, SH, BJ, CD for Guangzhou, Shanghai, Beijing, Chengdu) (default "GZ")
-  -nt3t string
-        Set NT3 test type (supported: both, ipv4, ipv6) (default "ipv4")
-  -security
-        Enable/Disable security test (default true)
-  -speed
-        Enable/Disable speed test (default true)
-  -spnum int
-        Set the number of servers per operator for speed test (default 2)
-  -upload
-        Enable/Disable upload the result (default true)
-  -ut
-        Enable/Disable unlock media test (default true)
-  -v    Display version information

Windows

  1. 下载带 exe 文件的压缩包:Releases
  2. 解压后,右键以管理员模式运行。

Docker

国际镜像地址:https://hub.docker.com/r/spiritlhl/goecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host spiritlhl/goecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm spiritlhl/goecs:latest -menu=false -l zh

使用Docker执行测试,硬件测试会有一些偏差和虚拟化架构判断失效,还是推荐直接测试而不使用Docker测试。

国内镜像地址:https://cnb.cool/oneclickvirt/ecs/-/packages/docker/ecs

请确保执行下述命令前本机已安装Docker

特权模式+host网络

shell
docker run --rm --privileged --network host docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

非特权模式+非host网络

shell
docker run --rm docker.cnb.cool/oneclickvirt/ecs:latest -menu=false -l zh

从源码进行编译

  1. 克隆仓库的 public 分支(不含私有依赖)
bash
git clone -b public https://github.com/oneclickvirt/ecs.git
-cd ecs
  1. 安装 Go 环境(如已安装可跳过)
bash
# 下载并安装 Go
-wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz
-rm -rf /usr/local/go && tar -C /usr/local -xzf go1.23.4.linux-amd64.tar.gz
-export PATH=$PATH:/usr/local/go/bin
  1. 编译
bash
go build -o goecs
  1. 运行测试
bash
./goecs -menu=false -l zh

支持的编译参数:

  • GOOS:支持 linux、windows、darwin、freebsd、openbsd
  • GOARCH:支持 amd64、arm、arm64、386、mips、mipsle、s390x、riscv64

跨平台编译示例:

bash
# 编译 Windows 版本
-GOOS=windows GOARCH=amd64 go build -o goecs.exe
-# 编译 MacOS 版本
-GOOS=darwin GOARCH=amd64 go build -o goecs_darwin

QA

Q: 为什么默认使用sysbench而不是geekbench

A: 比较二者特点

比较项sysbenchgeekbench
适用范围轻量级,几乎可在任何服务器上运行重量级,小型机器无法运行
测试要求无需网络,无特殊硬件需求需联网,IPV4环境,至少1G内存
开源情况基于LUA,开源,可自行编译各架构版本官方二进制闭源代码,不支持自行编译
测试稳定性核心测试组件10年以上未变每个大版本更新测试项,分数不同版本间难以对比(每个版本对标当前最好的CPU)
测试内容仅测试计算性能覆盖多种性能测试,分数加权计算,但部分测试实际不常用
适用场景适合快速测试,仅测试计算性能适合综合全面的测试

goecs测试使用何种CPU测试方式可使用参数指定,默认只是为了更多用户快速测试的需求

Q: 为什么使用Golang而不是Rust重构

A: 因为网络相关的项目目前以Golang语言为趋势,大多组件有开源生态维护,Rust很多得自己手搓,我懒得搞我没那个技术力

Q: 为什么不继续开发Shell版本而是选择重构

A: 因为太多千奇百怪的环境问题了,还是提前编译好测试的二进制文件比较容易解决环境问题(泛化性更好)

Q: 每个测试项目的说明有吗?

A: 每个测试项目有对应的维护仓库,自行点击查看仓库说明

Q: 测试进行到一半如何手动终止?

A: 按ctrl键和c键终止程序,终止后依然会在当前目录下生成goecs.txt文件和分享链接,里面是已经测试到的信息。

Q: 非Root环境如何进行测试?

A: 手动执行安装命令,实在装不上也没问题,直接在release中下载对应架构的压缩包解压后执行即可,只要你能执行的了文件。或者你能使用docker的话用docker执行。

致谢

感谢 he.net bgp.tools ipinfo.io ip.sb cheervision.co scamalytics.com abuseipdb.com virustotal.com ip2location.com ip-api.com ipregistry.co ipdata.co ipgeolocation.io ipwhois.io ipapi.com ipapi.is ipqualityscore.com bigdatacloud.com 等网站提供的API进行检测,感谢互联网各网站提供的查询资源

感谢

h501

提供的免费托管支持本开源项目的共享测试结果存储

同时感谢以下平台提供编辑和测试支持

golandibm

ZW z>LvWci|0Ys_~}zA<#r!FpYB||^on+Us`%f%qy+jTHN#5H_iqB-3Ph=a%NV&Ad-gHw zl4kvsk9?lBv!OO#qTiYn;vKECa%fn4tT|~nfbKPSY6FQp8|vk7r?}G(%x$_VOxJ)1tWAXy zcO*??y!+8dxoc9|2dW^~GN;B|U287!Nm=LIaJ|ooF+aLwJ~NGa1&q?uVsgUYS0mKc z^NMXa(-R0U<;Xo`mUgC|{_3V_zm68nk4b20hpwkRQkMb*pZZl2rg(>RoxTxgS~q>5 zb7#x}f7-3WFBmEwNSeWAM6RG)CF_BlV(;Q7?x!tD9MS)>b17=hXlnJg>danU(&=^r z-)3(3ih3{goV}bHi+zaagq6RWx_bm``PwSmsO_Yvdpio+qC;yl?_p;yv+s7FpwBj+ zQai?Me5wWN2(b*{1y)CJlZqTYJZ35$0sP!^-i64 z`d(46qTZAIEg zkrG#q7P)*}dk)#g;1erffjC^O)0hAQnxgE(`z}fm7Ix$@FIwC;_oNa zQb&n&LZp+=b$_xc{dgqZKj`Ci-p9j(Ryc}Wu~;G%Dtxnv98OyN+DAJgu2V;>(~qs& zkMFpj*r+4-hRg21{p371)eP8HBbcxVziL&b4fi2d@`LnFB1U$xu*{2mR8p>ft_poh zSMe{nu_Rcv;3^rP@5-rh|9xug(~ls?I)#9qyBhPnOY%II$Co)f@D+Kv_-R{h zXnyH(AMtPjD&-$N=K_KvHgl>^4Qkuj!*!WJ;SH=1X9TjeBd-x-1AbEA=ZaACwu*`O z0>$QkuFPMm%7?1@#NE3ripz13?~-Ww-aowBr@cqTsggA3 z3*J}p+tOY*WsqHRX2`&Z9p9#Ro4ul0WWTiGS|uwMo;BEVjY$vB+Ym)-U6|ZqF;3$! zrN(UN4VB^Vp_&@OB&0&+WJq@9)n3uzf+f zznj$JjkJc79b(a6waK(YWIRJ!Az;Yhj+_A5DxQ;Kv6B~B21}U1912nRRMCh4kTHon zgbPU{0EAg->BR!bLNdrCvr;(nAvdf6$s-c7u*ozhQK>)$bE0}2sB+FpRM6te|9d$z zsI5ztZ;OpjIolBaY**(tM0%96Ey=yE_lNV?pF1vK9eCUcm|=EY0VN(v_@u(f(o4}T zDPatNGza`q^$)!d@XiKafG`2@@smOcv1e`|<84JnJ<$xy@d428$9~ES%Y{8c)7c^n zCH|?WB}1}yOj(oly=x^m+d|brlb`{e)F_{pX_W>XA3CIEa{FgYkrY``lAH5~dex~$_1`jOy7Z>Rpw0O{g&wfc8 zQ=iC8D4!jalOX>Fj04tz^xgg$v?*Z*31uAo@4$U-n?rDBUjS!7h(YY2#tQ$g;|q`r z6c%wSK>q>Ig@9dl3le8G5Au%?{(s&QOGwMY?0V1x?*aY^;4c7v0ez8T2t?=ziU<*Q zMO}m4;J1V=b6XHD85m<@a-6rmf|5WzKtBLaw>$69b&G*`@%w?2Zjkc6QO@>=?2gJu zMR{rB{F(XX^z=(DJg1{C4X|8La0Q*-*h>dA!_qQDU=a$>G17i^XM`|v+iBl(Iv zYKMTn2yGB%@URuq#LNm(UQD`(h0j;Ag2v$b`0g3dRV!}5!n zTEcQZP5dOYHo4Ry7aVg&nCFwJ2=gMA7n7(ac8`;5MfKxIOA+d#TpcGn)LMvumjl_h zo=TuG8$p7Bf?;A&ZWQJu%%NpI#B&ojr;fSBGH2qv7l(3@jmyn)W{liT=O16Sw9;6L z{+-oC>l{M`sr;;@i}Pi}QD426)og?M6l$x zS285gwp@ILu`&NdHn$V;c6%=3-X!G9AXa1=cvs@ZL_|Vzr9F`=Ah$kY%Ji~+lH_D= zL7O9Z_ZSs!;N;Rya`B7GUm$`~Ji@B)bdN(}y-bR7g;nIr$RbUF^}8O`al0rNtw&g9LmFGLLJ}WJawYEuP%qpMa8&>OX((BGB7iL zav?s(?X2X)K#H-Ts&MCC_gC4>xZM`an()wF`FE zPdn)sjI?+bN3B7c4y#bF(PghHNxk}6vvN;Hv9F)~fUp=P%q3OF#j%NXp`xxh9l&44 z=jAvS{$#zW>(Kg?qqK&v&9m7?f77mxS$qJamj}TvR_Dm;DMFOQlcdEP`#VYx52Zox z-mW5ry3tedKXOK9e4(}cBy7K?kQR(iqc`g3o>c4aj!5&8Dy-LeO~M~!p(oxiu2*ho zLn9%w#gIoN#i!|qhQWk6#pSD%kD|;?in_(rx~ssH%rag?Sjw^?0W77Lz6RlQyIDF6 zJtPH865f#Vfh;!wD{fUcKiApATY)Fe&3}eFxo$iE0yUeVWI=<02d`rfxL5(W8Fs#& zD|%!AIC-?{7S>{`YwSP(puevN~8bE$j8Jz9Ekdec7tG3laqtU^S2(R!)|IFZidr8 zM?Ea*~cX?!2l%ch2t}LH@d0Z>zRw?(&cvQi&qA_X^7*j~MH%?!Vm{?-F zxBBi%s!LWQvKy7tFNzyd(X@tmZZzX@Tb{P0yIXo%MwByDUZ8^EiY8{k;i2N8iQ%i^ z=I3y8RZ=4?%qcxrOT?;@#QKt{uBuaGJH6_0+swNcL+{P~?o~_`Dy-W}Ij@h=n5$$m zPtoC`@Ym^ek#5v99bXR=wJd zjkC{>G-$8y&Q^AI=k_wycCAiIO>0onge-b}zDm_Sv$$%Rk(O5D)@m)!-4Pb9g0h^u zVh2jIrA)hORnx4S@%M{8>DJ1qwA0qIT)o#W^aRELD#loE<*;gecZ7;xU5Y3uCuLxMY*o3kV_?;x+$zS;kApXLtMS$yDy3%qX zFNWaAY&g0y92u@ zQbSQ1ixw`%hGI1p=aS+zmtaRV{HoQ_OU}%)X#LBKwRe`NWyfuHEq*Pzj zXVW&bQTtMDwPtyPfwI0&(ghi4>tTYLV%}?Vd**`tkiz(DqP3o}&%U>P4c{lrKJboL z^hH{#Y32c&bC0Gi$z4)^L8>~3O-(n!s*Z?i)z}2Aa4%$Q34HV3-t;6~PAHrQ%^J{8?pu7zZ2WqILvIix5cu~< z2cS5?>}{Zqt>^b`6&34|EjYvDU1h5H-N!Qkr3KbR9i=&rdqxMYwJ0m9{g`QoK3J z?cQ5Vzb2bf7Il>LYlch)(|rSKi><>nC)z9uhdB=+A^FS0mScljN_~eq8=8idCM4_H zG{T8czae68BX6#A(^U_S-_%L17*8(OS4WSrha#&&T223QEl{~|7BfyaSz7=N42Lb> z%3JS(T`RT{dIlXGQ#j5jtzZBMTV?EOFgu|(rT=2*D1Wo5Xr!23jnWfO-Q)V}K` zQPAF~LWXiwq>i{&PH;LI(%};6myPrntCEkHhjpXzR-2Fb z;?5o{%&u2lp~a6=#+Yf+)B7V7QmmGvdM^_3J5kir`MNpE_bk-w@7%;%IkaWfWMdFa zI&~ZNV_lD@LhHQvD53w8J6|v>kiSdK*9hq4jh++qR_j;RT6dcOGoE5f( zq~yp`FeKufrjhV&sgVleT4Dqgp<$^YHUE{7hT^?!R9Z^$cSd|P<=|SYlvDI4_bb6x zBUNqy&2h9%Ys>FZe6p0@H=ko(*>F2F^hG3N#pa^oJW<}YvTQ#jp02r9yuaQ%V@$qf zF-TS58swLOSYUkM2Unw`XgE>f{4gPqssfm?bWjQ#u0=$U> z=Jc?I?J=zxqkVC^1)C?mTmKS4M9MvcSCCjBiVE>B8vdy<0&FPPkf)XE9zKE%O21G4yIA*H6;_4fUyD;Cwk#)oXq2pLv#nW zKCi?Bq0JBx(&sR;M_GIYVsuT}5`X3L?0#HUCIEfRY694F#>%4_U8i-?QcgI!EMm$b ze|F3!dvVx8aJI>fg4hLsYsLg=nX{3~4agk1r$@=A*_%tD?E}=XSD^TwKD=v zTbsGdLP#Hz5Kv-eM<|n~H}YOAR|fksLfmO+e(Bf_L$hkx8C9rVgb**Z#yVBTq_F`h zx7_~0Uy&l_(gGi`Do$>YtHgVtc=yFcWi^(RF7XDqC351j{-nWUU_hq-f-DWJURP`d zQl27WA&6oeim2D7*Rqs{fN&5ZS#{fIh`yD~MTVpH8+`BfQ;Mm&&BImP6~-L0j5^aG zpfQVy)3ozqs_zbK`E~|qW&^Mm;_uY#9MEC?0HP6vnN>K~GOq}+0D`(!D z_KhCJC4n&(Rv9mn#X)1YPbe6V0(KZ%QUk}{4@mO@D8+9?aNrDFW?~@uk-fB$7sXt2 zp!w|&*KrhF*4GZU2Ra}M3VYj}QWz|MKHtfai+Y0e3ltW3vB4Aw3>D!D%mkICL6Vqb zIFe5pBKQ*TWo!)tndBT=V_XknuGkqF8nHO-5G{60g) zG&u(uh-CmrXe@}S1_q@3x5jZolcBo?Q$_;a;)i2~87(XzdbV+Jgc^Q?^|&fDm~?<_ zgKV@dltBUpwhkDu+6Yx*ihJ3}f>ZtxMYD%v~@)Z4coYVX8t;{Z2RMDD zTg)1GWmmEBB z6)Unp=FYv;i`MeJ4N6T#?$DUoW_X7Vxx;g|155RgZrH-b6_n_zbndns7gfXw@I-_S z=99|J0_L&B2^6Xa5?Zwyn{A@`IVZcMG)JRy$?W0-Nt_t z3)w@ClC|O?A2jfk6wojb9xGDU@ob}0k-J~OXkyi4%n?*t6(Aeq=T4q}O~4&C)9pIp zSEf#5eBe&@86Y)2iI~s8zYsIvw$^eqxWjnmhv}Q}f2tUSb*-3WW-;wkMuR?5)9r0v z9Ou#4&U9%!-d)ea4s}6STGnrj282tVgI3cC&_yYIkm$fQf)739>1{wwLd=XRA%_Qr zgH%P%(qwyK$_2my@7VH^p|k!hPyE6Td1Quf${;A+o^S$0-F(RJ_M`r4S6_TD?O&YV z%6-pqEsgmp%T(~M<%hrK?={3V{GE>D!< z6Qdlgz)g~tye8quf|t1kRD+MdJ(zzer_XqFmGk1A>kSN8E3+A1l9xx{J=D$mTzj@p zAHI~COYX-r8k8uhroB2}RT4rsWerlyZgzAys8eaoj5})qIxjE!>Nez%0X7^uCbi^& z=z2u*@yu7B6PmT|~?rr(PMa8;)g!;T~!S^(GSvD7! zD4Z>Lz!lQ%JQ4g)Z^ z2G7<_%0*Fu1J+ER>Ss1H7})UdwHPg)5uxe+sN=y01JWxWOf|f&n$Jx%je+k3W>#W7 z=`b>@9*K8d1K1R%_F!BYQSUV-a=1bF2v^p#J ztp}B6;=xa<_LK;f4#(;8m1}416L3f)yyQt}q+Z3vnxnz6LzA>b@Nr}rfiV`{npCr_ z`fc}cAB$~fkc)&xgR6S|-?8fzxBtqZVq^q``rc(}hND0B__^CRI-QyU>w@Pa)?JO0 zbpid?-)3wku=Pz7EtEJLA*MEo0eoH-a9c9UFr~jCiTg@|U>ngiJ7zM!zZhkDwx3P} zY|>n?wnU8)5b-njb<9JlRPH&`cQXOg(&nNH;yP4^rfb{hAI=UHWeBO_M`36~qkhEV zT{xVFR9dT8N6(-4+f^tfq%eha8OW#0K01%+w8AoVg3kqCA+O`<>aE#<(xVl7Giu)Hr2v53$$PF_!5& zZ7c3aH_Be+GJ=ZDwvN3VD8xls0B8D|b`r;)enF_(- zh?E-F7uPBqy|2Km`ntwK_%w$Z=*eKKYrb*u8<&vwkG!J0hws8xOi zBr%OCi6aE@)zx|IQEI7Nx0Df^}3U)$Ma{Vq(ZUEejB!Hlk ztBXR&vMCKZ0B{FEHhFbP}_@MbbxQ!45l|k(`VSj14nL3`&|Vsv&j&- z8tluCu*-ER(Y*#K(m(O|n<=uvnRs$b{@*wk38N?yVp=K_A73UuQX9D+FDdzAy!ObG zKIz(8i>@#TrmL&&`%Ad&K3RFIb@@)a&bk^y+J3z{Gqbq5P2MMOc4?^9fOGKi;sA!utAc%nTXqcgS${X|TFu*Ad-$sq zhFwT(jgL!jE@zy^r~{0=zY(ZSsV zQ`j_Y@9&!riaF^!K=j%AFmxR;y2`+Fz<1Ecbqc4qR8~d+uCqUFQCIj!! zqyY|7ahrSJ`_YOsRb1*0bHIHMMx+ni?0LhAQ+H|}Pt)Pmf}_%nQY&WJQ&H->yMx}@ zhfxjolgyTaJO{g~<{Q+@u^v7aB~`v!{bpJ=a*i_hMPn`ioukjeCjXMY-L&?{QEx?2 z#RUTaf!#NyKHVApc^AC;%+z>4D(p{}SXDnid|0WX+xu}B+Ub~1^c~O4^nE&$(8UJg zJ|G9%>4WnbR|<0kG~uTRrWrKChU&N*b?oZ3Rw-y#$>}zI(AiLJ=LPxpb*K0Z&Ja3( zyHInY?i{sF@tnvEoSIO~+Q@=)LGW|Ws{kBh9L^8ZpW#XMp$P>ALk^B7=8bSju01;^ zb+WvZCFO8S0AWfV{V&x8B&O)Ki`Z+WZ~Up9q=>}a$GF%t-|aqH%N@?Y3i>MT#4WamuUyCCO{98U~66ci+clIow~>BEQfU?0HT55-qbHZRnE_4xIs zpT{(QR_aV;4d~;jTD&f`&85&^|%k%7#goXx-k|T<|RfdLzW{-Og^G>nF zCI!G;0KcpZ1p@%lfVgiTi2DGM{_YP){w9>^05Gw9wObXYv#cynnKyES9RSA!)-#2M42Vf_?cV^Yyhs`v!kM zd}o4GG5_`y3TQ{SwKWTyZ6ikVhrBW1?HnMytb8!v@-MH}+2jo;)ANxy3)_R^_a9sx z_l~-EwW*LV1#*_;EzT@N3)TjQK|Cpgqw@Cw8-{* z0gD%7j@&%fd)!sa1U_wPYr8X6b-`mDcljod`N2HJf%6kPHvPB3J;8!>A~EqXE@Y{g z6CZjnc=Zhdm5;o3)YDI@Nk2HsH}g>zNCJw7ZiNdxjqeWkP?LP}pSZF9#GhXhTKIkW z5woMIloEbX{OcTgZ^rJ+tkQs5{rH$OxVLDf>m=j65&8wXe0lfM+GsIuhmHz&}r-;QS2H`2B zZ>WD31Gy&v5L*INeNfJW(B!4kiRy58FDp!VqP)CzsxDNtwVfb2#RRfEFa@!(;>zWw zuMTEDdL4k_YIuJ^2;hWV1$z;sXh$sG*9MLC*s+sJGUTUcG8&E0L7@TyvE$WLM_gzd z+b^r(alXe?#1gTqQUi|SYYdlle;Ei^QHIYJXqWsw7s%Tx8#`iGnH(L)W$8=-KGlVl zNa^eh;_j0_;_3J^{-_WG#Qs3byg!Lgz{e}}Sk215(Myd;O#))?1je?2XU3B$0Qv8R zq8E^Yw!@-?mE*rluWuPFq&{p%9-)2@&ss4S<6lsy2FE$kqJH!5;C@Zg>VuT)kw1u!YRRmC0Or`)p2zHSM zX{*H#Z@tgT2U80I&fqAoE9Fs0)CgG3TR{O6M?sbD(CDXrZxOVxg9hp7%h@Yy)UVyw zm+QjDn3tU_{IEuz>yuao0tD7hJPK?=11v2AHoNZh?uRQff;YOtM=n+QtyrNncz!&w zT3TK@kw!{ihvlTEa!9N4pI~BnGm6`hI#hc=TjU*`<{stQCFI!&O#p|^*9`x)t4(Wy z3F;Ik2B!}MKp+HrNaBE|Uzyqj2@MMbyfCx6_~>%8yIVL60~8hj-v>~Kp|9;wK+#U* zFL45t4Jnih^{@drmtb17xrLn4kJ-@{HQtSy4hi>s!rBrz@!pbeI}&oV>YR@9%4&-3Rt?=aBr4)ISSS5C@&qbP z4g0X$8y?t&eKdUcLrS5_{8H2G?GW*Xh7gI_wx-V4#xD58$2lO=gAr*ZrvJQQFW7>b z$5+3C6liNo>RU4**zIhUir53-gWlciBcUWcD_%=4(Eu*C_E0MIP9Zgc4Mv^*4wk|c z2;5&79n{8(?aeABAB#zKJBlrB?DwQ7VT@Fk2{TUpuf zG}6PibvZuRozRiVt?sx|c4W#Z}yFEE%SRdFO@~o_}lfTz7_ln^rr2Bz@q$-mL1x zy3x7J{>+Mw@#3(yxB7>d7j?Od&H0tnKN4HFM5n=t*!=C=O5sebsj4Bt;)q`}zuwo) zyT~E6%#@(?-DZLXJy&?4+o(-sdaE_1#*+NziNz(|GSw1n3v2yZ*HJN$c{X$1NOj`U ztf2pBdhI;z_A@?T_pK5Ad``G`*f6D}q4MTg95Av4JQQ!6C;)L^A()2xE9$GrZ)z`* zy^dQFo_J;5F91D*@3o70zuTX4eWVN8YrVZsi5mhS@Y=+Nx>^x%u2&p=qx4I?SDxMO zVKnv(e%g8wLm8i(sr4|v5gW!Z3=(r6AxhRH9*PIzD%c^^&=CB%gK$c*ps)!<5pCbL z_Li^b>?dvv3G|X<06G12uFT z;p$oSfY@f!F6B-gi~ct(;LF7hc>*wmu%);2vy{a)qy;0KpsY~?(H56dHg6afP zD@84{fMkWI^hehu1;K(=<*7!$zq^j%tlaU@m>nPAQ4X$f*3>yQ`uk$#S0NT+GW(Ca zO3K?D#t-kjk=wf>6e;M{y_QrtI;+(EFD)Gdg6foC-`K;m9i+aHh!Ma(kc=dkKEl&gFhgMbe-*`lnr-2iwxiW*{))&xbQE3S0fHM%uxaBX3WVzq9zXWUYI zvah*FQs?%6V(M0Ah~xCi@@Nj+Y8}XJDM0M}K0C6YU;rXQl&fWd^&*NfWZcj}LiZC0 z=tmtX4WRYE+py2cwd9`c>(7;yYtDX3p1=G+&Ck!~Dv^@ttAEZHXKN=rV&o;C;o%ae zoN4K6+Lo3(V1KQ4Ix+phnV@-`oQ+LjeTm1cIZVd^G91_k}-f%WPbi87eC|98%^s*fGOUIFO zWqs_!P~mRNUPAo!w#)8U+q|MXWEgBd+w5u7J_m?>f0q|c0gB}Dch~gGSKfjJ_=aEhp#|nt%&>QFTC@8 zXXC?ju6C9MZmEw8dRu=jsF&`$y>%`DP_H9-xfGyCUSDvXl4wl-cDmgS03>Ort59v? zVoJFfd!SncXu1wygF{piccW=oWnB;(+p(+A#Ol)DANVEEf^lo|@APu|=z()Wkpuw< z!4b0dDb!XsU$fYs+9V+x;bF_mSA=Z-6@c2!aEzAa^ZX|SFA55(Tj7y>A<|A|@WrXW zuF0J=G3zmc-r0>I8Wc{vCG^X(tx?dv0Q67!1S``JegBmuCete&&^ zzpcCFM_aYc=L1Q3ZEhg$Pr+WypS*#K>XV{CjD2elJSM84IOsH&Dv2f>5CQ06)CHK& z#1GHwfbcJ`#m;^B9RG5*;^h8D`Gp_l?aad=hSDp3#g$VJ`DW?L13!t+qS~V%?D`4& z?<&)Ox*h%V*~4yoo0eD4akv{87jf%>7cs3jIPhMofZZW;mNCGVW!w^KN_1VB61zV- z`yMd_ft7RsjY8UVRNtwacfN=>?j9-HVBgB&rjq8U1u2WO8TlXpOq%|`tswq#R~7QM z^OJt_i$&zRW&-9B(04k3%PL*F!Kc8FsWw=Ag|+< zKv%%B6LX}BDS?z(<^wU?&fZdtwya}kt!KNPjvf~2tN>!oQvg{sK-eN%y~xVI%& zp@0?9?h{-eO#RL6K@kzHL4nP|!GZOyKH&_{*kr6@EZMV1$&T2cR|*v9#pFA8$iJM^ z%go(8uUrY3hcf^LxGnelB02Gu49;09FD5l_xpiK=G2oi1jZL_2A{;cX>r}7lBEmkm zz`*5q3-$zVz>&wl6FKM)I2GAEe56RTd$5Tq>UvF!RgQ@Ut z^#89d6gYITj0x-SXUbfxhs0mPi^oZXenQoou-Zcly#EmWcSvqFv;oF{gvGvA-dWgDzmnS=r*xjbjlqUZ@+H!u?5xg zCN1pkzD?eInXvtA!7(UH8qPI9;&Ph2 zqWrm=%q^3m+tS>k_&4*-6)KJj!CRxn!@>UT5hTyfA^+MeAih!2M`%}elA@^%GZ4V2 zpnEJQhIa9Gb8+?qW@4@s!zq*TwlTA+o2QGTt0&N#Uf#&rxIHn^ zsOJwc8t)$$?dyLcuu5iQT_)T1C2$?8+S@I!=B(WQW%xJAD%#6GBEk;+@diw2V zUI8K~z1uGxapJw1v!9EL8;r7HZx@^;B9T!>EcA#fzFp!RPQ|L& z_g}_h`3kW>7ps~XyD#&d>ich4`Cw1?kOvH>sHGF5;wDaI4`xL8Cb(L|fdO5*4Yx0~ zM819e_fPmB;yE{JL9m_;Dx9UJZjV-uRdCBK3RbsLSi&f%sM}u#$HYDm`>Y8A(h;*h zPfSf_;w(@JU&Dk0?wAA3(LX(1O|{I2dZ*6|D#AVQCmzu)rrML^@%3G zEmV8uN#xLkoMoTPqij+ZDLD}ii+ZA(T)(l(is-B|_is(8R>tQb^X>xW^1%W;1XfEL zO4`Us?ZSEeaDA)_`1!pH^Lpwn;tEYHTzwo}+;Kyme8c3gu~x`^ERaTs~5 z{g-#Ckxz)Z>38{Fx#=7%xl}R|NM8c1Zk_SIa@LXgv(mqM6>=+q?sZEiDh(Ei$SU4I zluq@D5=*CP?9;0VJzcKs9Cp){$Mod>L*7F*l- zCEDjYB}UpY5&?4G%Pua_G1n#$Z%2!ymCuMK_VSLG7H{StMSdDduD|3`#Y_zWfhf z>x9XC=bKG^s7%hRq5)G5Z%a|m?X>9E2gf)hR%GbY0<-%i>Bli8(?VcTt7+`J->FQq z=*yuxHkRd8qFMUAIsQP+!Bs;W<)Iy0$m`~THQ1J~&GLH9)InZ152V^*7P=Rt6wF-w zaL%sm>!4n?aPwlEv#6`5BiXzwk6wsZ&m#&oh0UjOx2o8mMPMLz=}$oVTp)Y_=4tH0})g^L{2~5(D4@0mS~Hao;~| z5S+E40jdX_;1Q<39>A{_Y2-UCNlABZlLOq&X-O|McXKs0<$!tcJC;D~hx=J3?jB~A z?p`L8)J|q5xwGn$?4L8MOdcSgg;_CDBJ1_N&N@o24#{@NVEk1t1-i=ov#7(D@<7rv zgFMa7TT35@R>O~DOXi;a4c6OQ)RE~`3EC}{uW0UIjk>^3;(q$Mh`gEz2OmA0o|%?8 zRxd3G%VtKH`|J8D$9}7A1s2%lWyw6q%)=zENfPIL4se-~rX0H3OW@|>hcmTbAu+W20u({;IEV(9E=HXt5>V-|XQqE`wTtE0}z6lU0a3Cw)y0&4+eW0ji= zcQsZ0t4N8L-=7e>^0x~{Rji)3Uvd`i5P6@T{by%o+I!&}i@`jDI|)&pByl++i&ofC z+nGmeXsb`9UKP@lIkpG@O2=SYFza%pT!oa4rJJT)u|!@>n#{V$wAU8aE{MBClm{|+ z0FV@l_Af2q^!=?PYB&BoT)v$)=+t2)pw>LK%V`}=2;|8YqOMxJwr75h8RlgvV~@_P z#iYLZ0M^ehytj>I{x?E-SMg|may)m$EutbAb(j6ktdKutQ1}2gI`YKI3&wwXgmkkp zQLUxHQ_#7`@$>(%+AMFp^+7u|U-(HO@@a1fAFMsc7Z}^I?yl3aZ_)|^=orUTH$-*W zDm-mqU+LS*@HeZ;_j0m~o7L!A*m#&&JKSm&aT#}~;mh4Z|1l6QY=#8lUtlIoE(g?A z9XJPBK>p@Zz2+y5HP1CR?Z@c=4g$adhO|+|75t4EnPMr2&%y>ZT>dJesqmS0LyTxE#=>tDXfT3Fce44g8a@(f(q zSzuLe{+m)GzDiNdFQpYz=!@#WkT#^a;#D|(Up1dU*@vkH!vd2DGNLyE;TrQ>#n-lKlbrV zm$5=($WU_}xu~PU{;Rpr10ePvB!F}9cD?{5C<~P4j0}A1D|I>X-uq}DUbbS4PoRy; zOjiV)_#f3^|Fxr{h};|(GNh1be5UKk$AO#ORgT|)?YJ2b-zKN9C8q$yx8ZD5q1-50 zprId+0ALW!n0G2I-sSKEl>4t%FuYP~`|iWbq+x%mJCLmG-_nrJLH^W}di|K&GJE-v zq(}nN%inrZB`)^e9wF5WXBuKZe!0QNu*{k%V-2_Smm4dXyq+FEWE2vFVt}$O*X}ZO zkq!*RR!UP`txnC>|p1~)DoJW$AZoRP){pD?i2uhU;hUP0m%MUaG))!+pXVG6WWxiKjIcE zo@`p^_)Nd`#`$=W)2bb1&;++CuC4L5`~2UP)xTLO+++90eCp2hPipda@24;$U);$} z{w>0vGVZK{T#OBxu5#R7Zb7!)& z{H5&drF=^E@={KI>96$Um6ZIPrRD70uXr*sjz}iqeKSbJxC|mtvjs?zENtTa3B~Yk zgi3Ho^!iF!&R$X-{vJ-seY+Fu3b4NZ&xPQ8WJbdSPe3>$a_u-cLJS?JA)Tkr*H{sW zWKTSa>|a^#-xR}TtqxSuFZLk|j7y+L69IWB>(i^wilxW(99`XQT+S5B%W>mmt+X4? zv*XAC&nL5)?c=$g&(l&pPWDqy|2#=^oL?UR-mnF}8vy)|VF&pbh{b^s6|d#oqc#-&QX4R}Rm|%2pZ?$jK@X4VjE9q(jDIg5`i<_7 zIkc098QR^`MgU27za3#W|H&V29nE%~Ji}#{iG2NN8ju@UdykWH#hs4SNgA!#hF-`7 zGHOk`9InTY^^tid{v!h)2S%oWj=~+8xMGL+NdWlTNyTG01oHy&g3B~wYz*Roz17bu zuu^mn;jUA~JT}YtwqAM(^}mS?hnc(6&+B;Ns7(t;^j% zu`1}~+i^jCU#8*KS7A_|U0I9Mm8B9fs+w-!!Wh*MU5E2Jd-#{13=HaSqM~4`za~n_ z80O#_yRuzm5BSZ#>g}8#5XR=!l=+8$B=4|Z$FSjyn^I)ik~-B)H|B`o%>$}0Tn@8t z;~NT=NC`k@wwTTQ{m0`?Q!{Db$+4-a8x`^tynBHDTHk-E_I4>1^~1h_o<&P8w`Lmfi+VXKwFuWCwa$Uw*HZ#MI zs5?cOFdITRMk!(SNJ7pZ7Msf-7R2cx2KmFi>@bP9GatKVh{Rm1LostbP$v zI3$Bl$rd;0X$v}Zv!pnfo%Z0<2PSOe9)|Iz2R+rhzKtCc?Klzvj3~wE!GR}vkyH?K>Wcf{jmEROvCVH5HUW|pdy^D8{J|HB!sFI@Kp4xOtIRL|O*PcpLKyJZ^G5S>$Nvnbs z7gWvZu>?!tJT)OG>-f#|Tc$n@qcJyZvP5DF4|#}D%P!~1d2g19&))Wv&i8RGEMss? zyi^!_TObTFubQ;(i!$fC(Y<};g3_`hx+&Ki;GHS_zA632>)*g^eZk&}wruuxqj99I&$jpncu$r0JQ(fhZ=4J#3_GLH zyzn%`8|Nrn{w>fml0oNn;}t@<0yO_edzxX*GnV1K6~mz{@E-N2U|KW(5jzYsm%~y2 z5Ch6wS7_FUbSPOz+U$65gZ(+`DcFU46!xdZr-F%Z4rjyoc5Yz$o3X}_;0|(sYpVKu zN(01N1=hbeo3hs*v$=zt;OB$nQD}-zV{O!q9c)Fg4v<+ z*^Z6v+N_r8wupC2C&n9BOD9*W?#=Ebb!d&2qiHo%C{tTCWl9v9tW?3_jH3qz!(`Md zw$smHydrQw6*C1zM>Fcx>3i(gR`ktghgd5>a^vg{tUeiI>u`L7)k{ZPSZy~G-#C8F zOz=k(U9YwM&28syA{qcIC&C_RvO62#x`|978Gr|ZSU*2>p zs0z6MbErJAtJp34DG9jq{=)P&Pyd#TBd6=cje14nk~k=z5`XiUMV~^73pzGmN~e&A zQ#Ne_{LswUG*R%+>Z_ap7pE7mz1x%2b-D4+6}{M(Q*3?p{NmjEPnE}}{lBgp-#WXs zWpOe5cVWBC!oufozxAJ||Mlwjw;x;9;>PX&wqMVyTAVzn|F;AdERz9%cXI&14B#z5 z1wa_fd1Wl}J=-D0Jx3(2qYU#PEJKqK=~t(;2Pn4?wluGVst|4LxJGPPI#v-}c_$`7 z-&SW4BU@!2mq?9VAhh{jz*4(0eDk8DARR$m>4S1KECe!?D~2G#lA#*`%G&`wo+&A+ zB)T{}ksC+E4w*GW14-}NR*j$?4RlPsZi*LjF!d+^^ZrUER+6*icEmNrRij_k&WB_X zj7WQ~NFiiemR+jH8m`x-Rf0^}4OXdtq_K6GGGMImNbbsG@rPi)s!WY`;r!)t0cmcP zU=zC;q!QIH*Gk`Sfx$1+z=*AT0Kl-k0&;jMVCt65>)v0v`BF<=vv)FkYLOa|v20{; zpN1MH*E%+?C09nzYqVt88Z9akRM(Wsjp733;scMS>w@j0zyBrG?pYCNqGi(MdnKAC4S{8V+)a?+t zMqqKDo3Uk|QDbAe8SVjfb@sD>v28uF#aM*Mu_hsXmBt*YmZEtNF(t7jgJefGN8KG})I$;WIKE{Nf8n3Vg zl9(HmCyJ7|G94+}u+E_!xKDA`Bi7F1HXO#}kZR;He{OEO3O6-P!y$5aVC$9d#>dh5 zazz%tZfJSYRkb%h9>v@2Acm&gs|MsG3vzI*|s9d@8-D?nb8{*@jPdJ%y?Q3cCoMHsQiZdx)tRwOy?A z&MD=oo1+>gj7n$bl-;Nq88USDh~+*V`dZJ4&7VQ<7Gs^2m%BMlXXy-F8l`AgxpC}T zkqT!$CsB)_u==89G(F>LBS5=_01J1&WQVU?m|)G(IyV`hA+o9Ud5ByiuvlU;w(Mi7 z9A26hI$(;-^jNI{2HlDzNQ*H;Vi%O0RjXq)OxCC@`|BP?p@b02a75;-Z%qQ`??sZE7=~w%8!sKZ7Rp(4KK#1Z;sLe)yBYeAI=7NX zgBrl}PD+mC|i$mw86{pc0yLY)sybs z4Q_H5mOT8_m^w~AsJ^EDfAwwk_v(erubWC)8_XYO{Wa@mmOtx3RxBH{{KoRS1!RwB zJ8qlRuF9xMwWu~p(?BBm)R6~;Q6f<&PLs4mGF_)ht=3mv>7QOOUp0Sw$%a^>&9=oB z*#)~}-?wvioxzD|wz%Xo5A$`NV4h{CT<-+uxyHGT(P6weV1@)|I(L!_kKRs zXZlIcc;2rEgcz7$hAbRHQlNzGa1_QuOmcx95P$&az#T$>2-yH(6}lsv&Ou+gOG7k8 zA^ry!a1FO{KR@MRj_@L<5JGxHKmw!}4V1f!70*rzS1VS8SK`|tOgDtoQ6vSYa3m&=R+q{O)@(un(2$2Me zC`JWNdJNDod zdSMtQV?L5Ng-a;oG1ADRtj)U9O*-mPjYGTGE>{=A0xgT{@79c!zSgea#h=@E$w;Fl zOQAIFoPGHCx+*D-Qmc#lYm8^rW=8Q14(Zq`YKD5Q`@Sqv3RMQy>BuJX7nD(P~*+$^t^R2lO* ze)b){&(C=uALSqUYkt&6{YqevFdOipK5*gxqAgCbBW}g#aViQ?Nw&00MOsP$>DM%u z?7Z&7Pd?*&etWu|C6{QB12%Ai+x5||+Z`LSX&bYctws+ciKxho-c2a})ymqf*3(8h zzDM@7PU}^@wfA*S5A>6+d$9k}o(t$)vJ!o>cRu4fkv~+w1yfH(axu_7AxK77lpq zM=`HcuR~*YbujmpU3h=|b{+7(>b=njpJtz7pUZZxeboGIy07!S>UaBW&kt$8WxsnP zIl28S{>`&xjxK015U?IlwOZEf76Kpkm3?cc&f@d-^xo4VZX=l}Ceat?Y9h*Ix&ChNk~*=Yg5hPw)j3$GMlB|B{A3WZ01Kbd%sdTgNU2TB$cLZ+3zNr)%hO8|hFlK2iyb&$MJgFMPoExr;F5S0#m z#uhiyk$ssgAVF`+Xxe!kWZ}A6{8E#xSkzB0;%iv7czIh6=s4yUtjdj5#E2_bZ(EwS zFpVoLmR?qyPLq9JbV~!ZiE?%@Ej3J?2XR{~fU1Weq1x5}&|3=fA)%&<2&sC8NjQdB zPsZ^0>Al+`sN?Y4f|hi_QBkx_u_Gi3$SyiUOd+Z}QcGv_^=x7ZZ90KkGwHH>j@U;2 zIp4oQISN$aB?pcMBB7lz!Y(QHby=Vr>S7@@0dy)KP>BJd>RZq)f*gwTNU;_6s>Bq~rGk#d( zZ3J-d5Og9kG;8%@!LqQu7~EoiITr>|bfnki{Km=B*WQ+PZ+m$Qb;t_bJeqn4)vDFx zD^!{0AsO>sR#=#r5ct(ttMD$lvO<2#PS6)J_vK>OOArRDYPCG3oHijZ`$YPYh&$ud zAY12_d<13lItq`o+Gi*o%4yAkXTL) z&H8(w!T;ThbdrG(gmXzVc?3#;J)w|OmTzpm z#u|jnraxp3*b<#wc5h&DdKza@*m0VK+^_rSla#A=EIAFk7c zCd=1JY(5J+=-v2R5}JqkGJi=K7)z(`tKgtTik_LTME4ebHNqDR3>12dCLZpq{&AlA{nBpXa zXn|S|Rk;68`-G}ulsU51<1R0;WPGh=wU*i=fu=AMdRo%2_gm$vWKax*F$rE6XHWHV zq>KD4i>`fcBq*wnM3A37s0s&{RtV?K*L)`=hL>(UYJ;JEHRreJg>HKi`?>Udd*4P8 z^9Qk7Rf+g<%;mC%f;d(I7545KB^M75gA zl)cKgYK1)V)jjeeB+`J6%h4@vAZ>tPQcFsVXAh(NyiozIZw%N=X#H%ulaK&-@dl8{ zF1_b^P@q=hEoXVrCvc?*TtQ&#~Mu0tDD! zN00zQ>t0o|?FKsKh$caIaNpEiBZsa52hbW}om%N%5#H2Td(MsCFV|^{?nL(Hft^M*DF=x^i5^n+ zer%x_DvptT`tTfn|KrQ#aB#}{#dEt10>G}Xtqwl~<;uDECi(mpklOoXcvxMuOIYW4 zsl5?3ZT&$iwXs2zkZ%}nX^p{c&dKA76I@2Kx}c~Us6z15U2Q}v+~%ZoiWaa%dN#MHTj{44VExvK(=#pl9_8s}2(@T;MTci*jGOmoLk zJT-#R(ifu~GgnZNFy9;>u>+!LUW#N;UK4~?h(nKIH<sO>^#Rb%`miLdhqO2frc`zz#Kn2 z;>?MX1drUPlktwmeeuibyM|P1D$g`%-^IUTDYpTp)2)^QssnW_U=|Br01!13g*X@mNJd zNj@-TD(J~tf&o45wQNueTNx(A^Ev$_VjpLv!N8<6Av{@x5G>?4>(Ks9o}r;1z_O61 zg;cH*Xnr%e01_GXae<3p4+j(p-dZrgWKmsUIx2I>33ZtsLetWrdB)JZ_z|&hn4zV67QNKkwV3krxCSky-{Qb!jb` z!+ZSeqXjoS&KFgdClx9Z8>nTeyhHO&Yk*wRGcz=wf*x&xLZ6YbGUT(~;Nn)VJKT*6 zEss2>Mg-Y$ z&8t!+GxCk!=eEQY4D^m(I*Y;Fhj^g15>oXwfy0TXR-y+-LMER4YZ>1RO_-Sltc(rq zwI>ztn^XB@Z>=!CRjI8{OuSYO0!mN2!a--oAhp%b>@A2{`kQ`wx`e`x_7jwj(mIn2_O7a_&q z=9t)r?#O3v(0V66Jb!``{G(cex5iO_^t-trqI-d;AZ!?_-AF8b(VILU2bgsDtf+1J{VBnz^I{G-}p$gA!!=@yTNlp?$2f zpg_hc+fm32Wyh;dtb`0|ENlS1*;${aUQe?jsfL(w5(mPvxDS21)DdvAwgMmxY(={z zC~|Q7ve4Ek)u`@Ui2YEWSwLTTgttmStT3i5+@y~!s1S!+67Mx`1(WhJL6`ccPB=xf zfmWXr?1VHW9;?M4x(``0eBvgXBDr#~dTDrI3n(+Bno%8nWh6w5-SgmSVC92X<`|06 zyivBqS%ZW%)`Xf4X0_!~)^Eh!VI4cS%Q+jPmXECS; zEaf{=f_aoMZ9oG&$;VYF5%{#XvWa7$D&@x@=&rq;Ca3edMIKzt4@+NCHZ_;n z`shX2eV)o!@ebnZleXm)F8rK6-3-(dL?Yd*Ame^o7h*?kkXMqN$fD3E@_1;)R$c6Q+nL}dY&nGu41loLK zzodXF$Wp0?7&CGanLG@wmIf3kY#YT)KPYS#>pdBqh)`)qCck?1hE4_g0Bvt{0~=zm zMF==;k(BLn$&9KAn+PoqfPgd$YN+dM=HLWd?W_j|)kGj;t&70@LH`%Y6|snTOHz1+^a&2zBUKJ&ayZ@3pLPQ zf~^Y83A_zF;URRd6o^STk90r!6EpSB(bg6L__?R+P219%1yYA5p_3j~Lay7K&j}S1 z<&Z+@Z~FDHSIT(4=-D8fE8z#m_Bq|p7I`BcpGg?e30;@%>@;6Z3)V@u?VKRgP@_j4 znhVt~DHxX^*me{YfV2?dqD|$gnmJsHY<89T!Cj+?L;$IzmrcIYg_ET5XNi9V;ymnR zs>2#sk+4j8vVWe=2!L@`(A#dW8U-FqOF3D@5n8GnUkn55BYY0ihpmCfIRaLTfq}&_F$a#ImQ2z#Ie)8{1X8kx{9hoeM)j2S$F*!v zb;0}b5WJ;i`1aeqC6+ZT& ziV+jkQyl-n22(RDU-`0TBIgOX+rz(}IPYa+cp8Fz9wsNh0=lN}mCw_pCt>0(q^uh@jB@C5h# z{N}DrncX&r>UYT!emwnxdla(-Nz90=g*N>3cQJUf4vMaKnJgb3@)6GD_DN3-deE~< zQMl%j1oIMN!}?iC(A=)jouNUkA6Vz;RRXyn4_3tB@y0??MzRyl*WPk!9KGWTxI|oa zg|ojl-1dgfyQT0@OVuO}hl!g!kt+d@dqAOQ+~wXJX6|6&`jn+d7-Hx+KJ@kg!1RTp zl5*8$y!)6PZxTfzWlJq@p#~CgU?^Uj1yrm{N_=I-4VG@+ne_k^G(ravOh!^9=%{b0 z_I@=j$aADPET|pO+~0pH~T z;u^hECfLvTsoBtE$MSrATWRN##Vd=QyZNK0!5fY~?thT>{L9~cMVBUraVT8<)J$oM zYW}Xc-~Ra#12R=BU>;}3O93*F_D%_H2;{F?#|_niErEfN5moKqN>I{ZIuT=FW4MA6 zOj&6s1D$PW2g1V5?EvJw86-Fm4V{Pp9lD&Fu(?HrQ^+_rsW#Nn!Yrq2&4B}pDiS*F z1SFTlS&H3H2_3Cv6*U%bHwTI6*Ct^amx-YRKC~!7W9k$F5T}q!L4E~|=|yyHcy*qUL9m$|`(eFPaFLetUgRoglsjdz z!d~LR9(XQKJz`v7C!d~8nDaeMwI+m!p&SSu*Qt!h7(;!6Q{jvATj63Rt}wYAF9Xy& z&2i}fuos-67)oRT)pkCHSI_{DR60^`FYOJd!8Y$V#(by6Xf~vJJE%0RbfddXciA+^ zZ+Ip<6OR?!!#lh+3MFWJ{gA@p2k)SB0lh%k6CchN(NwkGmkvzy?FO<` zKYq4r)S>nC!FRF-a+kixec&@k)JG&}i(So$OP!oOi9>jVLdqo99jWMX2K z2oW;lz)-c8N{=?TO8}eJ0~e$NHgC3<==k9OF-n`rqeGej@dE(KIVNe(Y^ceNI=hI zYH$(A*Tvi^La1!3qun+8Km?C%a<1l$E zoyoIk@SUplO&s1O)5ZB<-jO#$1K&`H=Al#4eVfTQ+nR*hC2_JVXDsyZ>T#S# zi=TcNl%VvNKP-@Bbfd6vGJ3B`h?rBD(B^x#nE)C5NpvBB7{k$&|F}fu5Hp803+jXt zcVL5T!-G-nGJSU0;xHD4_rTXg#r8Xoa;YWNcTst&s;Iwl*E8io?sZx(VfGB z&DgEmjdsbioK-Eaaecj>5*t5OL$+@8ynt$mQq}d&OP0ZA6dBCdCQ<5ZMwm6yl6!k4BQ~ zl7HHwR#%GzRimgnX-{%yJXico6}nH0LsOsW$y43=wXv-GK;Bcro@EboY;jr#Yrfz1yx9(gWuz( zJ(bXkLs8p)Z3C-6(|X$saQFnf5p?rq#WgCf3SlO`HL9ULOfaDjo~X8yx4@lqM0gz~ zsngmdQ{&w0Am{{INsrit!qQb-z8GP5E8YtjxI%AVST{oxXv3J>7Vj!igPKjFK)O3F}n{XJ|$-= zytV+qw^&iZWG9pALi00V=8N5dIl*swJbgt%Y<84zj~#%WvF9>{!!lz)#cGb+N71%FD@Q(BA>H@1gy|ehtU7E-AvoqH`!33=<_>6Y!Msq_ z6*iL(Ap`JQy1GP%x-~6h4uXCgFD#g9S={FX@k{X7E!b+ZD!UAj@Ez&(i>U^_>Dk#~ z1$W@z#Dq;qCV;BTy0$c5ja+MD>s1_d6_s2GN(KrxoPB&@_eaRGXw_W(gh;*HT)e?@S6a5%(NOSa5e!(FOGM;)hO^K z_{gCF-1RBKM;fBuwgd57g6q!i218_ULRZ-l;hr_$OqNL!UDuWS5MoL>$dr=8<|j~b z2x7CEK2T0?Ziruk)7e5zQ$=t3zXv+eNY?2hka%e{hb%k{>-ROfJzNuWB)XdtDYDcCdZqk7Cuf?xWcrIFCg>U|rkR&N05AWb`MqDuzn^V9tt3yhwthQdcD1zj)F{W0D8~&r@89O!wr$> zT~PSEkqk8QyR0Tg9FC~etzdy0q}$TBa1_XYjhM1p0z*v}a4X|L&_rOg$qt6;^!TG| zl1%6#AcTCN$T;`JKDibCDCOPdQ1HwP5O1seS9=Ha+HjukgqeC590x(J##P zGP11@A+ErwF7o=D+R6z1c*m6FQU@lvrB_GO`;}^iZ?;aIO!k)^g71IZL2brOGPkP< z(*&83@%akon#i@0!6ZhD4*{{ot`0Wm7~S6c66LlU_Es}Z1Z)^81OTtAkcMklNo=Gq zzBZLd-&*y!q`K!QUx!Ay8|+KdU?`Eg88cD~={N(|h=@2Z2pt%D7?qvHfkhK-7u&8F06>mr=K(M^2f~O%{1H(IC(Onu=FlGYG6HIo?H8S*E+-sRD-l$GEN`< ze*&YqC2{{e(Wt0P62;b1cX_iUAtf;(CX(Q-0rq<_heVQOHg>a>Y%Qf%-@x?wF)Z8g zz&{UdTP;_yab7@?7K=_OWP39MeYVh(3Vp36SJUyBE&*LHCl~%bFkmuD-z>9r!`oKF zw)qw1);~Ox#A_P}{K$mCxX-wm19V;!Zj^sKI#4>VLduk&-CFqH63&|JW!uV?tMd7Y zjfvvJ0%{%SLl=KZoT?h#sEEx z-1)HpaN0}Xs`1_e#5?}F90gi9j+Cv9?hcr$!-~s62T+}I}Ko0i{Rm3IuwLQj#O zYVuo#TEqy&Gj1!AYAwOY5h>)RNI}DHnj#4u$rZ$>^bhwe{nMi?m@3Fl739FsQd%*n z^Vf*Dop}d2FKVn-Vw+8&cXn4%S+{#2y|8>&vdw$06&thu>l+jDy81S4WU6z)7eM^U z6CjtXNn_u-tG52h!FZYL{s2ooP(#Chdxg0YV_jijZ=yRSgVUx=8)j+5a9z+`PM_a4;4)nGO;c)EfFA3n%WJmFreoR+wY87@xAiQg_$$eS8S(OE-kT= z$wVS|Ot!2GN3RY>=k_N+sUQWrC*-DnWiH z8ZRfj@WDD3!&#xSItJef!OAi5YAXc!prv<9ZFaaCAx|KHw&6r|5CHUW{@Rz1Yl66} zz?{dh(7X2uiDUb3&WN^so6+u&>4}R3i)yCmzbaxa%$AC@0eoCfAA!k3H5k4)J(f_;r? z1qNPjP)=*|F+C2yF#A=p!A3AJNe2}Tj4(E~Ug%BQnPt$uYU(~5&YWvKKmFRte8DtU zbJ&ysOF*>0x||!_a%?-P8-=XU7JA^f(Iq24=e@(8^htNKZ4dVJMzY!RML({Z4EkNO zGTGN1oo8Q3jr=(jBcz=}`TIYcK4#K~(bQl&(>;sPIQaD&q07c4F0k>i0)Ok(fm;SY zf-8Li0#eI=Yz~M696-CkH)0U&X|Zb6`>k&>^K>Z_;MVFaB=9{z7&g#8y8I&`2Bf2U ze}E2jG70aC2zZ_iLo_MXt6vfl&oA^`~!HDq|?(40)SPVa!Ym+QX%7HlQ z9uZ?o9Um$y)ygDb>&Gp0SfTali*dP1PQeP%bIH4fAU4_=z1|FU9oCNO&}WN2thVDu zW(U8wnODpdEmPSB63%cNgVkjiW=Gngi>8xjxr9bz4_GX= zFF@0weY75vBuC9($0k&`M)ZID@pgT+YBAUb=M0^9Gn^c67pf~$0&iBZe>PIlGmIyy zstb!_tdvm0H^$VXbW=+hQj_$jz&7H@c=^6S?`Bq5b)-e`8%J=d)IvxC6=oppPSZ+L zI;YUiqN5Z=P5Nz2$~XwCX~xT_(yzDLm?K#C*|#hy8mr(MNctq`R##F#p;~3IEma&4 zQw{zYCZ0r5yva3d8Y#c80@9yzqD`pL0TQexNVJ`e?-uzaE>#hb^tD}!#M{%}*-d=Z zWjXOJQK~-L`gZmtc2%wI2?#td*IK}!Mov$n@(QEY3o8@yt5BxX+R8JCwQR@;g_B}I zGN;aiv&RxjWv`v1J~RJyq~p5cq*IS~w@}>+(JeLBClenWE+!0xQ)-url!d^l!N*CP zgNRKlh$b1%LFPio&>K%v4T_)$2(h^E24Xyk$)(asi-jZ!$d97j>|jBYmQ&r+jVN+t3yVD5Q&$=jo8POzQjptXg^HL}PvOKH`H^QT0~<6dD~pG=4EkN_|kMy}WE$|8B2GhrL#pL}aX z_F!N^MV3HAjx*{qD8@zdOOU~(Gg$YXW-2Y*%?;P!5fbk5TUrN^WwQPYBXFd$tb%=9b7sPYn35! z^M`6Es5lO`6cQWrW=|HGqM!V#3%Kqgte?*tdTnTQC zGVC{V=aq_cOo67kWKkcl>>_x6BBSjNB4mouGUfdBq;QqC+FGUVqzC&MM#-Q6N`lTP z^)?ak^Xu{LeIX&?Obr8HLZcj-LN;a(VG1++6iw|H+%r0oV#;6HPKtls-jedh#<2#@*tLp!$yU_r?Bp;J9w2$syIzS;mEfmv&(694*?tjWC1+ z5uN@ObB3Mddn`NV1z81wZLr;az>IjPN=W#<*`3ED;-=f-+$BzLYcd}Nd?7}}K;Wt+ zM#7>ucIm!2g=>0aM0`jlU=8Dv$m)!~mcGGFXwVF!IX)w8f*ov4GpQ9!`gcsnl z=AuKkP3-XKltAT@r1ReQR6em|cy@c3J2P7pps0bFI32)a#Xc9_#vk_>`*x}Wr2XmF zpzd0Th z&eU3_h=&yRCLhS&Y)vcEph(uZf$qW(T5S^jur%L^opCIA%>rS4h;h!VHg4~&6F~w- zxdOs8C4;)7oVN7(gQ9rMhGkhB9U-<|lP3xiA_|=mN(Oh=W)3PN4f{|Mr9}5ec>quZ z+eLM6c8Ku2=+=g03NrDJ9W+q7@9nZnLw70YltZs#Y2GG?2}w zg)HO5J-f0K4e8i<=AFUb8qd+Vh1HeL5xkN9drmz7m}{$e)oUrPGX`#$CF1~lbqZx; zV1!@cMa6tNGC^TKz~s-&H!^pPp9~8|w^1rQ4VwLfT}y|HyqJ>*~?3=j3SLb$1TjAmcZbqYwf! z+vf$of>p3kpT~?8%a;u{{HHN)e+{Fw4p>X&n|8;)gEH82DDE12p0C26P1f3BwisIf z!+xjce7Tj?T~q*RYVbQBI`6y;8y;{=#9%wB^@w#$4n|qC4`g;Da{vKB&cZfPiQo|{ z{f|J#fvBHi9_5P##G?xIFtKRwDveC&hh!m}^`Q&7Z;B}c!A6vLO^UGdb4h{{1*Xm^ z^~P!65sAbPTki3f)u}((+vMOnp(H5+2VptW6JQ*Nn?rJ`z|u_pp6N4AGxMPtO=Ab7 z8?`X{_;ilCCeSCF{Q&GJ)5}bE{44ax20I*T=ARVhRuL$GO*W_g#>Trd)2pfqwWPcj zEEpxJt@XH(@MMRi7oNE=a)oP54d-dG{Am0bMvT$Jp7cSf2W$+4(R?`sMQ0B>V@`#g zl76NjTX{hW@@?nSQAj6Nm=}{|@nq_{0&R6Bekg_z>yYLfL*tgO>+QWxZEW-a=f{8z z3v^P|0|mL;u}|(xa;n@n{2Ht~_+9gqp4dL_5_!>1wiI})d!kJjWElBuLIJdpLj!Lf zok`xCct`Q7eTzHP(2~)kNq7sh*lI~6+-6&icLJ}e2#Tg=5R+2O$GuiVYSwfR4ZHOP z97q=lPKP)KDf9k-B_Z8$qCR5wqapFzOn_{M+5QyUuOY)BPcXDFS1c#4h{J87$h?ox zL>^%v!|_0mlaI9~EMxcgH4|zUq~X4x5V`>#ZR$Z-psxhHQ2?bFy51O- zegxe)SC2h}7Pb`i0gQc85T$Jt(on`INPA9uh2A`)MmMmQGPN(~NUQ6TPk`&@15GWw zM2b2o9=z8T@&pmEFcwrAVFfKZ6-JgC5Vk0snL2{-M>}e~c75aR`E3*z9>mBPh$>8l z-4kSC0rR4J_i?jNg3kmGXP#GQgXzxP_Prx(w?)a(o#|E}u5d_(`h&S?6Xo7p>bt*s z-p68+sb$<=I5Zbr%BDSv>GKA36YlKEvk~@XOK4ULV9{d`b*ln+6B5KjN9ejTS__*i zl=lyFB^EjuJrUf2$GTEXuNj1>acWo8BfKaYlk&Efcv74|!#59M8s6Q7OU zu47Y!RG&+mYA3nKGJ&Zeg>8&y{1eA#jKrrNfMBVEtKO|XDa`5$ z1VZg@pHhW0#*C&U)3lKY%%O;XtPj^!Gu}6y1obK`>^KPg=@^>6Z>BdVG*7T&WogVT zLTEu)e=|Yilm=8KiR`*F9H;620Hg3{lU>*W%KNA@gf6fAAyiXIW4xwjF@vb)m$`nqAn>4m#$g9vkkx*$~KWX5#? z;YW}2<6DT9aP~t)e|z`E8UlqHKGhmA9GB}Z6gYHFtZH&dvrh188W9r-GBdBvA%Yfl z34_Z#!2pa$Kw{DlL32QYIRsxuOdfi)FlO`kYWd_5pkwm~H9y%698ciG!A|lJV&U{> za1TzDF*x+Vc1myKmr7FS?p!Kx_uL8!D-#{^lex_!b4iG2dQm?y5>Ris`IOUD z@WvU@OU;iS%gAV&Z8$^wknCqR2PQ*-unfgLH_9Ra50DiZ_vk11{9Qg%Gs0qg$|4BN zCOO!%k2d#w<^CD|Wsfl;^P2oxAWd0-@op&|y$T&IiFlznl`GjxvR%rvEtI{f6iQ?x zinB5v)RgXCA|Yext3hv`M-|^ARg&q(+$ph2{I2{!B~KvsA62z4RuG#C}>Im>C{>_y<0PVHBK zyY_^IaNj8(=Mbie6)YT^?I1!I@lKyqRGo;;uepCe<{sBIDLm2UCAsG3)(K5D^H4l zJv|t=wFN$NGdKq|+6fb?Jnbi>+I4UZ1p3Jk~Htj^nOik#BX0?P%CulOWIHxbDboxRmE!D)N*;V4800DziDg3zomI+8) zwi+21Z7FSMPyfE-E#&4t{kh{U)aE{&vEv_&4TFyP0(+Pm&(>{#ni+Kt5hKKk88K;gm6AC05dx7i9;v!RN>u=#`9uYJ1}M;qhQjb_V>!awG*6%(MUW=) z#i;+hSTZbYbc#=27tZ6(^4DD!2xw-2j_+4Me)gH=*9=T~z7^}jn7568XwAkkU_4Ev zlY`(poYBefIPH_(=9vMy`unCxcS>>wdkPb}@XYW_(oWB`w_Ni7xw+`X9X8EVx;IGs z&krg=vRAS^VG;)u`QkDcY{ZS2#oMb0f z{IsSjx<=lO_oV``z2_q2*AhinpeRc&Pd+c>k29&G!fDkZdZvEwg(;$z{6Zee1Q3i7 zlfH=kOfe`;FtC#ze2tRI!(_WD1sj#!^9(rW2($t(XY#lo*wAO)4K0-Sod9kQUPZ4* zAqL=l)+pvNE?CabSnp8!#Ga7bZT2^r;etiXku^{R-rBjD<8VFoS$B7>2|oED@5N&= zGG#A0KM^lYvfn-&~4_^St#KF*-)+O-u%{?sE~-Z2B+ak5m!Q_CX{xro47^MMI`;6` zwM9+b0pZ@j@TqHs__s7CCaHXJb+NPes(|y`kre2u9SoI1ow+S3CV6zMa!4?yC69S- zK&owSUy?~SV56}cZyms9sXwzDdbu$?*y~gdfSU>xD09{K!|P7;hz`S!Kw?Mp^Qym7 z72=bX%`xLl9=e?6gEyg9%zGw|Md`vdp&8AWl1#W`xCBP=Iu@{AgFE< zLc%hRcWL@xzGMr%^z@48$HZexTgXrI>pb^G$BDFXJ{*E_Q35ITV>6r41w`D(nr735 zB4U$b(})Y*`18$#QxVg2W?uAa;mHhl?oMjSn)9;fOeZsjNQFX2*TSH((6--!j+?u> z;(c6oWQt_pivbiNY$mnt{Yce%`zP^8s6FLk$f5c9O(bxYOfLpN-rdr(q6z z9o_sd8u$dW3aC_)hdm7RmVT^v+do@PoccaME<_l~t$LK`uzLPu09f?V?tz@eghNa) zh;9uo_ayJkh|WkUDsLXM2%+J9UYZcrFDlHA{DVT(iZ0CweBwV$7;s)3j{wM(+!`$f zIWBI6_PS1hE%8kr98-BJ9CAh6k2y7331g8e_Jx2rvQ8w*lSMS3*Nqkfu01q-+$!Tk z+|O4|rl#4v-B$$z?M@+;wD!9fr&5j7P}{1KL`mczWCa&LV566^MS!m=v?1RGMwblo<`%w;+1^RZD-C?#ugr)U>n2m&9^g7XV>V2Ji*c8hC-ga;JvFZ+gA zFZ-khT>26AQeMrGWd59q!B^Ynq1+7=-^4!kaBmPr;HCD4$kPutI@mwumPmJ5tl4G8 z`?~ichjBqdnu8Sv2I!AE+P}cNZ#7-DCza|yI(BkAlPMx5CRvDP$&A{Z)f#FFgtnUJ zYp^*F#ZN)oC<2I)6ZvxI`Qc)&@lopr>~i5=GTOMlGu8Ct&v4X3!(EEDQ$3tChAp(i zsU+quRWtGNQ2IDg$49LOjSn%Rv?#$@%4X1U?et)I^4 zV}e9*rk}@5%yQTfZAHidzDOX^pwR~dgxembDc*ZT-J;-}dM18l$8>r2jGc;X7wMhR zLIG$1USk1RayNHga=U-s-vsZPdPBCW@)O-dw5^E&?UYJ-3?2ur zOi?|;f%hX$xHVxkBREpWX&PwjNoPWJtqL;L#L)6!1 zZ9?{0HB)MM=_?}4QL6hftze%RkLn9~U~EVjd1M0G?LgF`orceugZ2--Gs$MIQ`(2E zM_kBS$SStSK((T4%ku@I&)CnwTv=HkroE6d=K0gynXt&*mQqTwP&CLeRV@z7nteZ| zw-fD)KdlQFP#fZ9I38)t!iFMw(qujK3Y&O;i!96y+z+EW?p@r<3>eB_VTK zdgJ^wSN&M*E^na@l!$Z9q9*%Ys5j$SO;+$s z$MmBJS;&up!46xXRL}bLCNkeWoKW+<%?U&sfQcZ1ZDU(p628r2uK;uu)K43l+0qwv zP0R6O!-f}#!ui;FPt-w5EvUb-`4!NVas|4l_#MuOAk;Oe$*@opv%3CZgktHGov`gpOqiqXn zVTXH>i#55l1TKBNa%tiK-FardB$5Z5 zUEqZ55XN$dfLT#ebviP}<3^BRPA>{j5oQf5cuK0at>i!ia;c74vHvJZ^7#gxfoU?= zBMuRx46(5Z{%f}Z93(9En--cJnlb_)|NfmWAxthd1wNBxS|(7qi3BNZ4ca0USo?y0 z_9Mk&d^d6Zh(eY%D{!UA&;6T7v0e@__H0?x@p|+emo=Hs$h>3oT4a>_&G~_-r zK=mwOpfO1W7mV;yUyJob3(zI%o^~YZ%%BTQN3}%>P9X&c)QR|@eN-u;o}#Ad`;&Hz z47U3u>>&b`296aq3;23Y$Tl`{nPjLmBn$J!pFFYsarwrag5ujg2U0B;&-!-!M;KjY z#&!P`z`1TYExG|+3AIaD< zq#jhe81yUWY{iFqvgwBXOul;t(~e_G2mLs&7_LQW80GJbp(I;uu)X}5KwQGsnaQp( zJRwpLBnnrAY)!JPd7lw)BXL&jYf@TG6>g1soUm1|aZOndDfhcEBb;g!1GNLszgG|lMZnF8qF6Mru} z;x$i2@u)R`M9@MJ;DHwv?o`EA&r47zL*MkhRpWr#TO9yL1&iW53xs#sAf{JmP~J(y z6X8xnDn!9XJ6`xxq(HUP9Swk&ZfjI@m5e0D8T-SS3(2kH7 z1FQyW1f`H`@u8M-I2rci3)g+%YsuV2-Rtnp{EH`#s_&4jR)p9Ju(?0rwWg5eN_S30 zOF8{j715gu1hXc3KQG>rT^NG1`51n2MkTej6;JXUMem|r({XA~_T1?VA3b7HB`;W` zfEm>Q@N>{QuV+p?;I+?AC-sc5tX!>vZRd>ShS_HqiA0u|;5A3?-EMFMfiVOyrXL$3 zP~TKcrfZ%j2Wg(*0ra!XcVHFkab={hp?Y>tH}lFWXonanmQl&tevL35BaU{+Qh@&R z%5F$rHSv!i-*@V*l&Efq#M&n$MlPrd45HjEpxT+=j#$8A>FECDR!EpP1)|l^`-+Js zF138ceDLK(pSyEcWgvX9G~n~asZ%8-AoLf+D<<7|Jry80;OZRQ-|#Kx04fk1W#l1c zk%*sh^U59#EK6tkq^&qRxG^k+sSTq1uSNb0vY3{*R0UdZB^+CteYmccvjZ!- z>(w4t)-*Kjp7J9E;Yty-Wo;{x=Mu>%BqcL>>Mmtd$-SR~@#8S|O?sg$`LaFVQZeH) zvMP^!;hJP-RPQ*9^{+S_{X^BJFo&e${1=HMjw(HenLIw-Z>$`Q>na$RZWcs+* zHd)0~&;^a-VCcn1YeCyEAjWPB;gZ4?+NY9X-pJU!XinuE=n| zk$@tshhPZ&nAh%XAR+~!e1C!n?G0G4gl8ScP|9nU=rVb$;*U^n180V=lLxbNVS)z} zZOJ`5nFz`p#!;n=1TM3TaDGlm&|8V~R37a8Z z7=C{9M6*be)k!MLV0aU;r{PrtM|7x3dIdVzFVW@NOGnDd*CYsMXnjP9Fg0jL>*`NQ zp5vTlu7Fc--|D4DVlJr5sh*V+j7Iv009NI#d#O_a;$7Mz@T|a@xxtax_nGL*tdw=s zOF&3nbwt_*FzzfHDB%Xo`~Tp?h1drWa>eFTv~H~qU{1Rc+aSdX_B0a6`y6^Q1%8yA zE(VCwKr?+Kp%p&P$bb2Ywr$KHDV{b3U&&f0;7i)W=Ix2wky_mb?-UCYPg@h=;RSJt zN8f_4{glkjb?k(MVL3ORjGBS{_m=cCY0;2|!`zmcyM0{J-HKl)xpx5ES=BsW0Qc>i zDo$BUC4rr6N0G2ty6+SL0#mBj5-9;hdZ%$;yY(sk3vNA0%5;z=&j@t@+U@4*OFkP! zy3qfI?WW{^D0Dz@=%MtZZ{x_D>)Ba9bu&30L7I&uFSN2D$MI?^mC4Lj;#)k?NuP7R z#Ej@GWZ!??0MU6_c~UaT2+h3Dw?OjeyhsCM`Mas-11>P;y||i7cv(Q#e$Wcqr}8&x zmCyo%KL-9ZD8s#F&UPX9N`uF0QQk+cK1($yU}R| z=Wd(Y{xrt+Q^p)BRp$b|}jssR1 z23JL}JdECJ@H%x5HPXzzI?vrg&-}v(66#z$8f&mDQCx94pPQD(gLLqqD#-jEQfzL} zVVf#C6K2)u;b=J~IMHsW;!K}VQgnMTT!3Uoc_&P-g-C-6z3^bFNOK!z@Irm+a1VS^ zy`7*Ry^r16SgJ9d;CpV?a(XT!0-kiRQ4>f^Bl{$m4IO|hXnNv{ppRlTZ=LuG*+PCW zOkgQX1GmV__uN~+QfqkZVybx}N`^z{%y@q(Tgo~=pBPQsv`5pvp zR3nt!@X-KC!FlY5=PWpl3qAvjj_`Xf6cx@ayiYQ5DRJO=<}u_PJF6_P#6lW$Qou(~ zcSLwHRT!uk*p--MCoV|h6(1b)_qxG3cX|CICKc`0IYGWPHI7afi!+HDqPTF=_vb!g zgLfSC=lc&~Sb6Z7_Oi0ib<2h3Olw(FPLIuKLnCFha%L^Yrt(tRw7=`~lFPV|HR}yN z`}-}=lI_iJOb8y-6$OuqKjqJH|3n{FL7HZmYHyUHWnKlkINYBc+oDKD!06ub5L)O3 zHMi;Hm-9MT4Mu9B^yxw4r(b95w0==b^3Su#w!Xxf_lT z+7(P;^?l=c7MU^7xN-dWHKXaLe(~L{*D{!*6)EAl3V-@nZCOEHr;e08+D$KAe@}*y z2^qYN-kTG3YAj`taew4OvaK#j3NR4lWS(28!MXyh-i1T^qjBN|xX9rLo&DPDjLra8 zb%Y~RHcmrNwpJPA?|Owz6SJ9ia&?Qr%Wm|F-Z)L)V&T8xy|D7Q01Zpuf7rb0D@odJGXnJ`|mHLK@7hwSU0A@VNTt%GKgzz_T9A1XI*$xV7Jv}r1 zyb~+n@v*+7Qy9>Uw{o8batL09*P*jxdS@Hpokqq1-+-6l=@?dS!_a8p&}%$jQY(7H ztC*6){8?VY{9THNs&2lKzmAA`ved3nVDhQFNR49+Mwz-IM z4&S5QMc2B812FV!*!HNy1FhK2Lm2yy^jJOr0bYdvEG!!Nkh{SI-Mu&XRD0)G@fDNQ zpm*}*k-0%%1=vdl=gJ=+5X&r^3KC}nV#<5+aDl1@eS)XDm?)qW6&~_&q3&o7MsCUE z2fajYbC8fdKQ`geU+Ct&%%KY~zRtZ;=WNs*<1DCdP=m_r#kv9?yqBwS8Fg`IgB#-` z`paunn@Iw-V{rhK8=873YSH@i_X?nMSl;#uYrDR%40{*tot&}`1whe89Vq?^maLOU zIPK9eN1j~%k{5%BsG?|GwZtSO2iB7-wZ6WlK16l=4zT< zV}nu(_=Fv*#G@$JN?2gmEM?9t==3|Lfn^NYVjM=|`ar8sACokQ`x3u@IQ;i5FkZ06 zx;7G@O>K=mSXD1a*^IWDELXY7AO+ncM+r+TaH7ryn_IZ#kOeB?tFb|JFB%>b!~Z}0 z`xhcM=@l9_f(dKFzv&xaAkYgN9!}sB(&09JNKZY~#0z3=fg)S8+O#Bvp2oJG^ ziTDWE9NBh~Sxq^t2Ib%20DD1S`pgdrJPjzX2+u2UxXirzZ z5FYjj{kVaGd!6Zm1|tNXmf%$pSYU_AVV0{9T1&O4&eOMKi>P{-q6R4H`K0{k@Nb6g zWrz&fjH(EZISQ7F<0iZ!49DSq)dFdhq(~5~n|IqK0A41Zrb#J)r*L{drya_OL1Oj^ zE+Yh`GU}Dns!WN@WfMNPdeXC2RJXOJlDk9-oy8oPHr_z&_u8r=fEIEeg{TPW2Q$kt z2zvd{nj!nRLP*LzX@1ELxFQfOC!|n+m9{oBi;d4o`=34%%TKfmJoOj8|3Nq9ulv#|XOqMi+Uf zB2$+$?n$>Gf{x-*JH+bkeS zYBLN#P)icO!?1zEG#bvb29Gy9!|N7j!u0#tAec2BfT76=XJ9~2+VgVGlW5!P%%37w z#Y7f2HKL%2CqpM5E^@!<0{dmY+t>_U7XzI`^$|i9lImn&6Cy?Y?4xHLJsRT@&neN< z{S+q&j!X<{DA9wZQ`XgIPy8-8CeU<4#-VTlVXsjdw)B09L?n4#vm<@(+#`M=yR74! zM06WH+#{K_9aDdgIgx#p!dS*dw-Dy>w@xMk-Z!LlX*E<>q-@&ttD)8R#-@% zlH@`(?_xA`5hK9vc=?BC-KkIZZrA}j=|VqGZQ18o8g{DO-b7+a?zKe1JK`Gg6FYS= z0NzMN24#lO`W+=L;SIZc798dlA-0o#6GVUn1_l{&2@md_CcSM$_ozav=`#qin8p~p)T(6iZ- zn)()H`55dz`T;!mx6tbwtUAg-?H6)<=IZ^NY1Qy5wH@9mt;oyg?G|^;1mYEGx6!7w z5y@1dQv?MzRu!4mz;Hk!b$Ip-SxCpsc0C(!#E`@^pDdh+huB!2cs%JG-$@5{SzIf{ zefaxbhtw_03{Z$}uE9L7!9{ri)3{fWqzTyOE#k9Z4i_o#fvDi;G*iP@`6B<0UTgd> zusji|1d~H-m5hyrf?|mF(9pHs;8mO3ox_+>M>f1ZOFS{{Jyw*xjlAD$6BVRKiZnco zi;z?(n`3oParb`X4~_0v{cNg)2GsWveGRoJfN!y5?UMhSsB} zxy-0K2k)z)1QiP?^8TD^>*Smnb7X@1Qmv)ih_cv+Vs?}-~I!& zMM?*6w}C8B*;SO7lqNSM*8u|nt|>%vJ!DdlSrI?lJ@%jP7zneEgaTP8I}ZLm*XgP# zm>1aGq%%8dDrKYpi?3GMCiq41nGg`jXn=)efChsg4xB%6w9mlupwN+}znIbah(+n!@z8e(MST>ej`5W@eWNK z7wVW6?kLv*B}~0=8w!|I!s5TD&>mwRZtq}`Z6E#_bdU=v8Be^$XGpl2G1zDS&6`0M z3NEe?dd?bql3lzTi=Fu_Wo1U zhbpJc=fB;BokmG!f0K~Dt^z{*^zaY-m@-uk4m8fy)z(l`Q|p2b2L5jA?T7#2aFkFf zPpneeL%}DTw`w{MPiQFS(G0QCAX*%(hc&%;27@zn()ALbbml%RE?#Q0(V~6OLjNJr zVyKHWOVx+CRC8j)2gh~xYyQf9H0~atU5k~J*AkK=oAPdm20{e^Q6x)K1dOb)FAFcO z3atlF(e{7V%!hoj$@Q=aCvQ6|QD{9|*hw}cD))8G7E`2l&G9>Ab;R8#{n_pG2lqKF z;Pp$=(N6&;zg(#6PVWkHK#9|!UHdqm-0+N;$)}QW(=`?*m*hh)!x5D44-jjM7o`NME9dCqn~E^6@^}zWlw$B-&bVU>q`$}#O~c? zCq?F$w(=K3p%&eRp;fSGDOY@+*+pZ)dml(^ZH+bXpj10#+g)M!q67H?m-xkVD-pqj zNb`n6o-@^HGpPZu>3z#u4aaOUR(hY&B%F&~r$!Sgizp$}pMzf34ZZBG{U}bi0yXjZ zy}lC7YM>Le$se_d5}I}aRDx}|8+TAXgf z)oL!(@gs@?cAYIwc{&FMC^BCYlA%XGnh&+Qo+`YN5O)Gx2AE@z0U0p{BXRijzGe^j zJP)7M6g&OAlp$aGN$R4lh`I*ot9GTQnOBZL(oX`=lMb~L+Hqq(bE=S56IEjw(S@4> z??sgg!c8aEc&p)+kvFX1IvL(`bmZ>YXn0~Q1WFAuJz?~G<;@O9eYK_8kU}sOMykSd zzUayRN1ZT;(n=hC>jS+znx$$VC~>tL;JfYGX>f(Xu z^r4IT{OU;D$JpArnrkM~T#;xx>6q05c&{e-}|*5 ze;W3DI>P$-6>U^FmeE)>Sok zmj!{**E5>wsFg14J!?LVZSj84F&qj#Kae_h$|T5I_pRU3=3X5)N{I$^#vD@{q(IR; z^OsP#O)S?sa<;K6Z)um#q(8}k^11jUb|%b8A|dY6Z^C zWQitTw7+^cl&4HahuYqiKXf0b!Tkuzf!xmVC4(*kNw?8t7AcveSS{aPGjtLUBh8di z4a1e%dX#NMElVJ-x05%bOt2b8-&lC0T+Cp!cSW0tm`-*Ryf=Oa>k=sEo93MeA5*f3 zW}+y&F0RHWclRVYcXs5?rk#`7-|@$7H#~LcU-s4Qz0Rj)$yNnZ91K=a`(d2y=oQAy zJ1Q0Xg4%8_WtiRd+}8D9c3dbzctk5A;mwvUY9UE9xq{V_Ahj9Z7eG>W_;Tm5Np-nM zT6F{xi`|UXI_1amN@7AXLxWGU5qLF>`vUX@^|G&Z{F_H3Js~X>WXyEuUt18mzO~?S zy(|4X^1^1Ue&%UM8!ohCTcS62*tgQ>QM?k~j8jsBasptINo$&p3j(dh=aAGG(AqY+ z(_T0WN4Oz5L5DNZcJ@!J0qF1N9oR< zec1!d`ULbRUC|EQVlach3^}&S4AABDl~q@SWlVmT>G1PF2kRsQ#pH?kOn zqt7@8SI8tsMzP74QnJmvCzX@1@M@EJ8heM2w1g-W70k!L;hAenh$J{uCPC~z-rdjv zJz;oU-}^cVhSYgo1b?Zng*P1A!VOcMa!;A79u%$sTqF8d+cI2F{1ICku z4=#SXH6#-E{PKp4Gl$VNo8Ok*bJiUu!uSm=cjJ#t>r~$C+SC-D~-{r!_PDE{$Dr@#zdw0#Cw`TFgr8}vnYKk%1p&i^6v8`(2 zLTkc9LGF=-V~DXgtyoKzL8rW<7b=)hhGctFDtg#^>>|9d@hV-DHz2j5%O`m9qN)Z> zEqdI(DxEu@&27HkYOx_E^6mSa)j3OHxfj&4Qf82{Qz(q((`$NPH>U+|lGeeq;JE5V zS~(@VP5hD{7Wo!W3sTg3bVwo#`9(z-MU~q{PVsQPk25HJ)%Q{|d*Qv^A!Vu2Y^u|k zow_0Av%TIj|NNQZVRU6;rei*N?2#-M3NlS|r!!wnPQ6I=D}MVX=^x`i9R=dp5gwY) zMGB!~BjbXRAj?F=Nb5&t3uM6+m-oi126a?x$Cb9wG4@n5vkI!q^^Gp{XEQBh^F)Z* zS7}C8?A~8n%-G3nxmBYCw&}FR8tFCWY!rbVqPX@vZN?|fyq+$`8eixhe>9?Ko?}K< zJ24k;sbIDyV@)pp zj17Soa##2(cRQq^p(3a)S%%jPd?VkqV)pib=$cRz<;}b=kfZhe%c^FL!rP-QqnP=K zOsbwpasOETDr5k9sA}`K%$8A??lHN`GQ6DJBDdDPw&06z{)`)iAX7Qts6V3fUP)7y zvVp_ONvD02f-RM-*wvRm)Aa2@x4OIc%chp3#W|8IVMTOd{P>*F6B4xn2##6x_UTha zdmel0F_iQK8S-gLVs6DwOJM6-E4cqI|7ZvlSNPW>p#^%0cCYQMXZFwAHoJ9Iy6%!t zLNqwWumSC__DYRmLY{Wf;+X4PLg;vLd3a*9t;gq*Q}3v^9mlW*4IB_n@AM0~1nMSF zBrLDq_(D4z#i3+6z9~?10S&Jl?X_((k}!`CLnR+1D8MCZY?09rC}{XI7F z20321fn-8$9Bk`+{hq3t`hhOeh=lX$kQaQ~vCxsJ_kexVd$98I~!XnV4=@3xcX1 z$9f1Rl~pN>OkgDN*BD0Co^T5;7$rM<_KwZ1j`|cmDL*FN9pAp_LK)q-)CT{IoH zi;Y`t`*t()X+^N7qWveHJuMiWtIB<&06x&4@AwwOu!WFSHuwJ-!xna%YopfLU1gP{ zryadg_tUNpomeO2ywvc|r3^G$ z16@HbV?j93rFG+cvb-mb^7-Wa7jb@3Zuihj?RT49UyDc*{8Tw z?`p+c{d=?Ls(!gWn;VITg-D09xLH(HoZ_f59JwIXd$=4?LzO^v7%7{`M#?EitccJ^ zE6t9nZ%}ws>_gQ$er6p2EPAR+>pp-zQnNr*+10b(GxpvvBu?WZNp}=`6W>hPn^98PGb0pSR}he} zN*CBp%$&pm3@CT%WFmG)f)3;duJ%H+ATDCs!9M2trxyI&qTh?n#r0BZ1yrhGgXOLm zsq?{{Qly0RO%u_%#Lz}e)MnkZ_82RR?MGPf?|^bo{g?w04(-Jhfj~_I1uK8BcrM(< zlS$~R$5>WQ@4QNDj9KS2P*ow=AzKY#O=ut>wvdK!>=lqeLSe}W7_`grQ1%6?h_^UYB4H ztlq7qsz7Jg9As!T=kxjao;r`@Mtuo)IXEByN0gGND2nP~_b33vZ?sQ0y)HF2*DP#R%iszz+i zPaH-I!q)>aADE}zHMFoLwG}E~=cjOB=v3+SF%byTjwT;Z-J29$T|bb`pnXChExP9L zSEf2(iFWWtgb|Y7L#a2mw6`UPPaEK1J9;5N(CZq1O~tDd85g&uk_pFXDxYy|>1_UD zn@ovq08W=*{_%rgU&8ff!*%#tQV@Tf0ST*vrrE?M4jjDk@~;|?OPJ{1^y;S9E?<;) zUhK+r4lh?DGhgi$#JavSGhvqw@GT^jxDkyy`|58NCz+#cO-mKFAv<-x0Z2}D4ttJ7 zNCdxw4+?d)d=UN78DkUa(s(NEK|~}NO9)b z{wwY|qRw?NGmNZrn%n5@%*Q2eba(vKwQXy&$RbfZH1>$DnQg6xpq#&q6$nKkmN&FE z0P5r6$EXJtBqq}sJl1%7`f6U=v`I~xdEjZ$7tpqrPC)V#k-}${c0CS4nl0?!bo^%~ zpc{Sz=ZZguSD+n^!x2g3R+Sq^3TYyfG5xXdpXgx|Qe1Mnr)o4L$@m(f!xC~swb%gU zi}qZ>|X03agC83mj_-S=}8f29*aArnHrRl4R)pB2fuEJ z(K7Mess19=_KSwMX~G{n{j^xgQu9NX988C#L%X3|;sSP?K7!5`|H%|=#n~sd-q^6e zt+r!dv5VhrPkq>PBeFg={;6qdp}sZiPvkZ#b0fOh&dNOdn^%RwKG;3dh~xu&Au~nM zSX1LHh@C`VRNFV_hUV1RrX%ezd}l(5NMq|a#5uUV!$m!s`7yAI^RW^oz*o7xxh@-6x2p~h%h`Fy^^mR(00IvYqTaQ zH+Uo)esUV^1%C5-tqF3%Yw9R_uI`tNCOK`?)TV@l3(bhzaavwBpo7GNQ0?UG!+=wf z(w+fKx7T?>kle%2-c4fSOJc!?wKtGf$YvXt`<}bgb>tkU=pumfQ3rb9`F!9HqPbaM z{(%c(K?{N-{mj|k_&GMq4L92s`xc$_$@;Q2h2-<%J6vl2r<3_p%N(k@^&i#)9M5y$ zo%Cv3QB(CY!S)YE(Uv$OgV-6@>JJ$_x;~-5cXy-&r+ZA{y4Y?ic6)6892W=qQE-68 z@5;VdQ3_G-7Zdy#6WFbwyLcCI8uD;t8Cb4M6ffcivl&?yz`S?H=k$Z6wX(#OqxpRF zm@k2WTi@W#-*o97!7K)abqHGP4CM}Cjvf4hm(~=z<^}x*?}>yIWs_xq!nLisHB^jF znb2f_TZ`|Z>j7zDakGcSE^bTAk3rzjICN5mvHD4>nvhiMp|ey`zk<%7YC&RERcAVq zffD*l?r`+(2NlhH9fd>cyjI6+BTGtar;ZV+=bDHek`9#ZhW4ib{-lk|D0a?MkeKJS zt)^>s?h|l6tg+rY0vQf^`uZ(XoBsTjR;PIKnPw1^s8?J)C`w+&e|G zp>u-q&=+*|^rwlXH1gzWuaG(kxdq9nF6dg&LpYd7>y1?|P8X*0L-VgJN!+!|wv3_(o=!)*=t@LjCkYswY)PM7AWrK@uHb!nd9 zKKqdONV3Z=Kky>Bg3ygJwqe@;mzsVvImgGq`oT?F=lJRGzw1>q1{(l!g5nuQ7kGGz z5BeGm`)Z|nFD=(ADpPIpwY8Ws8%!pn>r4InMz7fUZIb5+@KyXotG|W*X48CMNYd&H z7bo_oe9A6N9_T*ovduCWgFg&l=B3we`BHY3L}FYdt_Gu~1%aC#umy~0a?SDzZUt#f zMne4@sX*F%gqghUD+O%(|9xr(rWA`4VhVpqDqrl4<=<$2Vwct)_D5jDq)e zpIOv2&e%R5x$;C3c%y#gO83UTufS#$I*!8$_(%9D^tX3H2eiRWa5UB=s~(E6B9~=6 zz!5kKFThq+GgnLYuiio4lrY-3=Q*+9*$1*HHnD0j0_l~;x)?=sVdrC5+P{()+AcVp zHae4gRU1A$<81Ss3K$qunlph?&Cu6MU(+68f*+)$jq1M`*^pe@(?7n42%}o+vCuvb zezQ2`SzvmK3Pbo`m=3@ofPfHc-67*3kM z=i(}8OD4bqQ-$H{UTY*xO+`T1Pxerd*>82W(+dU27xsfCqd!D`9-V`gJU5&QbkZ|s zgkL|fO~1COExMBLu=9n;u$)up7v4k>g5irGrc{_aeEY|3!QopA!b+~o>JiPVhN{qo z4LUvK#nZgXGy6Ef*kduB3=mV?EPdWSppPQODE@EP9ojfK8=Kx&gBsiXqV^nOpSP@| zX^((gEd68^*oMRq@|Z`>AK_s4FdK~}*hs6n#XEIT)b$6^YL2(-aAY=RdQ6j9f)vxp zvkAIV&Rqfyhne|6BisLuDQzumpn@$uj6cBZtcN&xpNj=95Uq{+o37jg@m@aNI=}wz zP;xEtTE!RBgZ{RWYP4Dotq3O+m9r*f=}4v|%ua)U#Y} z^{gkKB zBHmydPH+t_B+4WFhpbJl>&a-ap`p2z#&L8o7f~^|a(lU4ZULh#-c|wYK;o_tdamhD zMSU`o{uMr{%Fnrix^S{WCn_#eQCNR9M#yC{ z5y<_0^Tdv~GZ;p{^rU^#Q%U@3%hVehc@}K_ck6GjM&);)dR|wv3%AeD)lY&U z6qzw|O+G5%2IdWlCVneLNu!(~9EC+y$==rRBu)#llVvwiQy}O9gUzC@+8kLz);TNS z0E-?id|qpB7fs{iGN(imW2?7ul&t}@B+w@`=ZYv}ju_mVKV?HeSkj;&0Ar6b;g_v+ z-;Af9c1K-j1AQSV+0YB;+@4PE@EFSxdtin@{}WN5td8nDF+x#|vGh)2uZA|lO;1+f zBb}H-jygnx{KdwoYV4Y@V+ib84Dx9E1?>a&m2mr;w^UVhK(^m6?w{C<*D^iqgU3(# zQ(WydSK1C2hyk93Q?TGK;2PX&%I0%%G|6C_PnktGOQ>A9jW5KovJ9MuJyD-_0iK>j zi4`akb<29Xl;z1_qgSAWNBD4-9}!v(dia~V*DTs5TLW1p)Zlf?Bf8CZnG7K{w+ts) zM6kTxm(FmEFi1wH{66C1TSP}F@I5g4YFpfGTV zY=@x|v%Y;;THwxO?14QlgwH|QPVsXJ*I&Zf%?+P|rU%SxAwfobL?(0}VO|OPITZwH zTJ2zpy}Hn;T%w6^CDC&GMIxegs~KU#O+XKCHU$;@f3nB441nom5h6Wd-KK4~Wk?7M z%y?wO-jZyGuwlu|LOzKS1$ZDTgP_1WQ<69FdqkGPwQC-)6eouI*X@ufA(Z!=h4b!; z3#G2dzSrme*eKPNevA^thq|SnFxnWCEB-qCP+j|kBI9%4eg^D%6Y~f*$l5s1dBz7q zD24F=NQ$Kjg`xfo_DHB6wU-2TW$m5eCNxmWrbw5SFqqEkCGpfTp%LE|)KvN-nA#Qg z3{khTu?IQ{Ma^35q=2QxAx~pE4E#FaCFx=@>mW^_?S!wtlLeM$4+tcgN>N73SUkET zdKHaR84Q9M8<%_G$(S%_Xdnj_S9YMTCr@V|5tL`6Fe`~os0$Ef2di1rNZMNz0HUzq z*#sX3$AWs-9b0sUmUPV1TSt&|b%R3A`uv$rM*JY4e67$_PW%;tK)s!C8e{N%6v2jb zXrGzGAyyD*JNCoEH}QSsn5`4)@5UP3QxZBKBw@sz>|g^+%3ke|zcR?vP3dp14mH0Y z8h9mN9vw)U&2{N4nZoee?7mmfz_+JdOW*_?VXfDv$(6HSbO;=1(|6 z540dIbKI#oVFg?tCJtbnf`$B@a!vy0OAvh4)Ecj_otI)b$!iFv zM!3FAwn`az+JO6e&kG~DRTTe#SbY5ZFZX5T`<4y8H7_aiw}~)%ME;&F<-AEdG0tfE zF7J2xwbSUBsA#jbe_SX!peJF-+`hjf`-QDQdZUiR!$4aU|DMbXM$*w8YLVSUC;+3Vt2a)7$+Rzog6aS=Z*6;`QsY(nAxsv2)i==;N!c zH|>oyrne&@fPZU?$gz^{r#*8oU9XitZM}%&bA5X&HQJl8T0ntaZ|d~aL@;V9;^w$7 z1Curb4O6v*;ZN2@`_P%iuuJ09*xp6J5i#qjWiNE>q?bSDw}~NWMD+Cqb~vwd)1kPE zDa2*RDk9tu#0cw+3PN7egTuMW^Q20JejWTS4KhsRLGX_{gZkN@k1Pu znt%c3kQUC-cp3Tc{BS08<)b@j`;e}jsUeICW65Mfvo*$|y3b!XzVJKY^&1Hvo*3~=N^!?CNn@>S(^|rs65$l}Nd3A%W28^yXze8Z#R~Vw_m`~w|g~QRQ zncueG&OLrqT?@VXb^h7d$g}nL!kha3{zFO>n!x_*+8X!AKQCsV&CIQ=$!ib=t_>*G zLOKHfA%L-Wuy=KEP-+rq1^C{u`B0B)3$;e5kdbWv?n1>U6v#VdTfd;vmQ}*SOZWie z)swsHp$W*)UP zk}2SgpKz@MgfFvcM1Aa};DydUQ9IdUSG=2m@e1U;S(3!I8}wM0q%NaOB8X#^jC} z-Tt-j`Q1o&OM3?+0dZ}s#}^M3(Q;h!=6Qx41Q_i2bZ9KsYTF!Cx*NN@)8jLCnw^~N zxao1$H0k&E`EAa4&CNeX%UZWe6cDR{+&JgrsM-38j85b_jBk{fgr=vq^A)_qdPjsj3G!+s8UT90_lTP(GNP z&HY%ARW+JS; zz0~~hT&YVWH8t>n{zc2Gah7!$#aJr1#+oM}hsJQ-61a@ZtMsJWb`*?6)v7$Ag>!IT zu6u94c=Khoy%vf#%c20O+0d?Vfk`fLp4)m8!d3=O*Bg-?nd~T9uQ_<1IJ_U9v>+Hs zUcj=}5wKAsd)Jad7U9;5;oZcXZmKACq3e5S`W0&l?U4Va#BrtDc|ztWk~Q4t#P zLilt7VB9gioGKCzmkfehYmGM8qe0Pvg`8t-Poo2kjj{219Q9tXFIM}VTP7kobU%@k zT3T7Oj7d0)e9;CP5I=CYi;X7i>#UoRi<&>;zwrC#^oM4w5RBvP&EjyG}94=W@|1cGywkA;odn-KRzHO?U_|3`rO@UPoj>TH)5U zBQm^br`Euw2GRV-mxi0eL|lbtC3J(Ct)==Jwhs3XV$0LfTmm8F6Ds6jT4Vke9KJFw zDU;Y9ILwznB9XF*`HePI#@y$OytZfGqc65b7#g@P>C=1<2BE+l&tA;Udb0!f9jg4q zOo#)5cI+Z-<2a|3hCkP7GO6KfoPg(GEipB6vYMUjW&+wb2JgX7;Qzq0daQ^tXi3SK z_n?=4Fky70LQ)P=Sfe3u?-Xm)zV;6HoIbF{Pz!JrUedKr^J|`(+(`DCTX(SKKP1m0 z=jFVgW^VM}oZHs6Ft@+tJK};!qedx=W& z!j#fWVpAZ5rJBS>K;Pl~N|{{WZ@HnycH2{uE%&iYaDKyE*}<4y*#Fqo&7p$-|518$ zQWv+#1IDe1M4!z)T)M6Hy7D0v$?v?-Q=XSJv2@8)ID+c47nIcA8{vB(N3edZw0s&} z1r?&6QU9Y1#b2=1J65YjWyJ=#beo_Psz_nn2=aCG1Ym{obZrGeY*u}p7*U=`mmFAPY6`GUf`lWnrPgNb_VhgG11GQMcaeTlgc(Y0HI41rnBz=@?j8wm*twryH| z@D+zCqnzIb-gNCRR62t(+duvNlG{%8o1u4$x7}mWhd_u)i5|GFy$u@$VbjN=Fc^hB zQy1~Xc^7$5)1^u>qO6^gH>X}jdb2+voQ&EA0@8QqCYs_We4PV}ummy;b01;WEL~ju zzY|WftgL)y322wZ6Y3)^>~;yrKjD4y3Q6w1&s2%_IG5H^>j!fO_HD5~v$cD3_F1MD z_@gxuI8|5U;(kd`dbd`}y5zE*59cn_jahko$PsWiRFBVuWCfUdQ6N!?L#nJLBkM+K z2mi}Gxb1vxIm8P znzoeSgf7&k$7V|6luu{kh6oz*C8-cY^C&#`&4Mf9anvg7FA+`~ioDVB5*-$pFgE97 z&DFgfldJ6y{Pz#3S*K%AFhNa0m9AK*-6?rf{ld;JwLtd%{T3rsSbW`qKFt4qOSWEV zP3t1g8VGfO)t_BM=JYDi<|sh$Pd@6d-lTfqQ zQ7Db%h*=!+K}hZc{P17-D>OyN{X_1#rDoI>379~gh&X6AHUKw2RxT} zB~eN`B_g2T_!0OYxqdxY=@36`xKT*GrU;83yQkPt^~y(AXp#Jd6)_ z$uMq@uioDK*l0TLH4-@wy{&%0{aPjOm8__QiXp|4WFakvE6O{`V>=~kl$gEszT%@{ za|krB0g+Mzk%ljRw&3k37Cz$|He$YY2?Mz-`gYHzBiy^+!{IuGFnp5|%a>DOQrPyuFb z9mM9)>sz%8d!QrDmc*WZz9@@H1}wmP7v3N{11cFNxIfu1sReKBltOl}B{utkt=tax z>kG$b{x(L+6+4z8xO9#ez0N6?ZRsgKndmS$H1rt>!dmYB`FSTfUhalx0iA^OA#voE ztD~u5ix?r>JJ=3Hf3rlZH7pKr#V7JB%4aCv>oZ7{MDuD#LvWW;Vxdq>Q=R!Dg9v!p zSo|35*w^I9D-cPy0?uvi6s4#W?eQ#WGC5ong+|jm6;j@4_9hZ}jAB25=6qoq&5gttU2wR)CdXSR4d&cAiac4 zb`A4oi!QJuc|4U;78K~3KKLiqLlY9{tqeGpp@*jc4iBfmTD-xPB()VyiQZpE(>d)O zznjiT`StgoS35aQGfPS>a~jK{v_o@lK*!L9qJi1rG{g7^73Q~0V$Oq=mSg376THJ9 z;QLcoMK^1|9C^-Su(&oltrR$2r74>)d zqq$y+Vw{&%5_Gu1qo$?`PU;f9F|2Hcb@ZW^LU%M`r{wwyjg_^2QIKe7HuystL7PAi z*-EcF?6A(0cUzP8mJt##+BTeoU-M0-{v~UC8kxrw-AghwSgA%^mNE2#GcG5>)3`u6 z!&JuIP*#o5ON9EB-b9^&*&q;e{<~r>eVfXU*g7&YeCVV3m#JIucW@L2H2jlQybgE~ ztk!>JFRww53Kgpb!22IgGp?N0Yl_nXG45_8Fxk!3@6e3f!p|G<)?)HeB}OBI>4SXg z>k5(rqOGa4V_D}x5A?=3_aiF8*$V*Ct#~tT+7UdiMC%_o>C$%;1AFu1`*LzFF$e;? zzNQ@j=Pfn>SD2?-cv_#Yjd?mrFdMr-dAcKR8Xh@2GxsIgkUNu!o0RPKSc5(76}sZ> z=*~gZC4HXr5d1#=3|{Psyezu*Z3^XNfyyejltI#a))O*XWe=&Si=&ng+8}L|>f8W< zjE6FkwL5GOEh5T!**^ut)=WO|CB&}n64nTU8^NYKh^)X2gUbkJP-fbzZS2;z^l_IO zN-&x~AiEe|_sNA(vlc$k$sFNF-Pv~^U=qS09zdo9Pm9v&$Szb4M7!&+R^rK+3dw=_uAd+ zn2GEUWLS(^#PbX(tZ?QaFxV0tWz)H=FX5J1$gpD=GJD%1;+~jLY|nzI6bxcTVd354 zQWr1>Ul!u!S9wyCU1`#2MSFLWii<`NDU9)Am zwk=v4T9Wig%+IG4(LR%-eq!3;qD62h=IJsf6Bo)QirJwV&LW6M{!-**1jkB+jnSg<8h4?KA3FT-_Xm zu&o)I!Pa>U?!)~X_rs(SsODho$8!cVz-ezgvklV$c$d1c8+N->`i^*R($a`;WoD%bqBv~h zC~N_6C?f;CFqh!&5A%WBG)-lQBO)V&twurZWk;O^4^4xY5L;(dqarVEyvhrph1?D= z3FC0ZY!q#!$&i_$uR9=z3_O(ZsQ6VTgrThumaee^N{G^=l4` zc2N+?aq#3OMXp^qWM}-3M5885@%9Z2_uNiXILf)+08M{&l?BzJcd=f07j^cpI0aN` zRkJT`sq<<)GSZ+TZqcr+s!ExM3noD%1W#ER9ZGa0T(_z|5{;_gkp$M}lA%6}l?Frb z^hI;Q3r4GHB7!f&J#+!y=^B+^g?Ci|AGyjZjzfRGbQ2wvH-xbalKfE`R7+$d*4Uw&0?o1WD zx^zDTZx{J|mB|gHFcwvs;l1{d{SA0A!iRwAv!`NP( z0?+i;LwXZ~c_)}-0E78)p;75fFoIKBevo+-ZCZRzwJZLLjaYwWRu~R*$w{3YQsIz@`A#KiDRMOHq zc%mq8FfMt#koK{*uYcfhA|;4K-&Xl?cXXtRz;xlHG|oh^fl0ZAGLyizYoa<38D3yJ^Sj|<9Fi>W?@ z)^P>w?X7>_YhR8zJ{q%)vVU)jX++V?2k-r>FoD$ckb zS@W<{Ut2NRxDvpM8V(0xHD5eWhvAQ0Wd6IT@|U5^sklB7*&(c@9e&?JH93dnHhk<* zJ1UK0Jlx)O6h5)$xDo?xTSl$_0m3kVR$c_xt94QK6M zJn2@e`;Nv+Cam=kgZRMszO>a|c!Qmqd6%*s)|U}!Y7UIh7T_Hm@RWa8xTLB(-4x_R z&b~M2;{;XOJM|PdD-^xXtd&P-YITJd;sF_lr4}Qm#(9$9-Yk*qo~c9|vkc(CpFD#L z=7*=_oLoge6P+S9S?+lJzmx-$kLHP`BZcuuFC~drO0bu>s!2k``uNOsz)yl)L&jP{ zN31r}$*(=ik}=VG#>OS#&09qsnY9Hu5=_E_j`#g*t@S;Ccd|ES`?YMmOy%R!kl7`E zhz|V_mB>sbv-q>ulpI~sI%N=b3p0QeeauN;$5XoUg-G2A!Y7aM^*pAe=mY9O zpz5LHU27(Y2sT4A%o*Q-plytyQ_Ov2;vL=INTzobwI`JBl2vAqO+zGdS}>;9bb8Qg zdbQ6NJA=Xj-@!8onCi~aADi6#O8hfPWq@*qA?jJS5LQID2-tDu771lOGg%IAF`?3L zCz&OS*|1?kwm6_TvL%O0a*LA<=WuQr4_jO?%3Ja{Lbl{XS+b=7QNCPdB!tBNwcu9E1j znyqzXh(|%GYX8@;8n!Diw+%j}*(ko4?En8iH>t>2rPE8&4hEu#uc{v?XBAw%3)76D zu`DcbWr4;;*d&8jPIO4zymv+4ug2w+MTJcb)q~Rn;f6j=)Ze>jSi|w=NRk6x zq<#cfC?=|AB-r-^vr&HAoI|(4!W8KKLMD{hg8O_gh5v%TOIX141p|cf6?C!gT)~6j zv-M)L*nWa7veAEMD@>oTvnd7=1W(Gy5pDQ9TiC-kG02enBP3xj;Sha4!XQRJT0Ec? z3Z@pL@+H8OOSS`UB}fUw^xWhj~3q0?l5=GNWqZg)GziWOswF<3ChfH9(nM45=Fh?QV~jTl&;lQ{KY0Tc8xasj^k8FSQFp^b-u~HUq=i_HlH*Q}E9n;II%n<~hHd7aZNywN40DY; zIX5A>jvOJCVuiXsJx74^Pw8zf>p`maY`mG?Bm^B@sZFUP?w6VFhRe*wpiXt2pBCUjAQ6&l%h|%a~_x3Xu zI_F&Vzh6}l@%}yj%*JY2C7q25s!}Eucq6)mzVHqeuoh(X>^=Yq_ZHcrLk?>;A_^R_ zMi(C!BVuE7KaZQ$3sCUn$CQu|A()mL)p1*~6Y-_=_Dp@xd`)L{I=-V)hktl}zxC@} z${GnV`ix9e(34SY?wem7porZM^BIjJF$G8+DW25&fXH}+T>P&&%K13+6 zte$q0+YLi*R4G5!+|Q2tEg~51cnNZ}Fcv1TceO9gYgeI70}uaBzkhX(B>UR8{8Cza z0Vsfk(1rq~@gxBR1!eIpK6&0y*51#4|1_iBd`^J_BbNyv##)@t$_e4oDD0j(|C6+Z zDGtwnzt=w3x#8(4beNP?gPgJ1gh=7tt*+088AX5$u*=Zg*v!-b3vR$#FZ?_$=l?n9 z>Wr^OHVPDiSWRi4n$FBto|^w(al}KALP)a7ijDpJH|PJaEhCnR5<&tbK)}lp^coZ3 z^qT6|d$SX)b;Pv+Dr!f>D#qcvvaclD-EPQG2p$l8C5MEO-GL*bT=p?$1H0iFZZ=C6 zlq67g4~kO$@4mUuZ0@d%p4bt3;N71|%eGZ0Bmf9i1(=!n1pItiTU#+$Wybi(!Zq>B zV8%B{HyGMNE5E2K3kn-#bJ)SlJpc~#Z-s4aiHb4wK41Yz=u91uLl=?-1Y@goC9qPh zaKD6$6W!x5FpRK^LbwS;vjOQx7vPAn|36Kw-@aQCZBXqQ7v(-@Ky?D`36Jsw*#2QF zxhJH&YM=kN{~XjqQA7cxgaRoUg_7JLD7nF+q<&Qt-5`o`Q?jI{WVJ??v%aPFbc(h+ zO!hpWB+sj&)gLU%o)Ybzk)`fQ!4s3)lVV!_?JWQDFK1S}pW|--H_O?r|6&=^|LW4! zKfgRh!T-83j9ZsUk}t93AMn)$`L0CH6)ax>_f8#WT@gmu2#BYa{p{_uxw=(L7Lvju zObXI5_m6^oKLA4r!G#b#Mk6$Z&<>*Lrd9Gk5JZO(W?mL=5(b)PpU&!2S}lrs=YjK) z^Fh9KX~asirGbY^H^X{{^X400`PK%}|36dBb_WaShO0!762nEZvd$^Cl#cINCx?)# z7-s+9!C+^xBnU8o04YIBN=yo*f|VSwiv|?kTQ|*w8)~%}$JD25MQTnPY zUDqzE((v@H^{>5ET{CC4=0mnWg8DIT_XSz`$D2(01EE3}oVU{f02w6!ZCoOw910od zql5^QGI09#!ICtUX2ODVV{?}Z^_#Ef=7e*ItO{C{YI?OV&!XNSs4fCw3rTp-&1>9@WA z;hr9lU%BiT-3&*qa1$Q5?Rz1rywog&5`Y1UpbtJgUcG-fs|OQlloV{-4JJ>&E+gtv!a=snz5QIhgz`H&4LgbCu7+S?S^4qZ%(7gtLyqq3Khr)6g5iC343;;j?Kzt5#yik5)(Z3y>NoIa?_DzweR-En6 z#QgroTk*|*SZeC=y+6FHJzM&!*R>~0pLyjm@!aMc-@7jszn?hGpFYSq_tNNF8K=&O za1m$jog${T}K}-0Yv9e-AYKm#5!K+a~ka{+H+9ifsSK z=!Uf)H6DSO^iT{xzNB6|cS5=J zx;rjBg3p5a`-eNu%(r*$dM?J0ys;CSDu<}?&#x#jEzU1B;R5AKvz?`yl-X2ZShP=l@_29i_iK0Dm2ad}R39Zv1`sXS&Hfz!GGf`y(!_JixY|G2Su! zBzg+}!0>#x^MQWNqvB+@|M>7@K##+d4T498pY5)f4nErh--HSA<&lOwbsX-<`R97N z4_)^FmO9?kn|YkHHUn zkDyuaCyyOD@Yk(28|yi}qMQqjXSiAYDbqV!ewWF9s^?w(qemBx3~awSIDaVlor99Y zT5q>{_zB6W2M3qX0e1T0Q)AO3e}ZGI)$db^$HVET1C1R%&=h-zXW_}tw~zm+J{2DQ zo}uQF6}*kM)ajmMPS1AE<4e!{e2aTV_;5#K**o&Eg}C-|c;s$-ML4x(RT{2chNm{H zt;Wwxf7Vi+z2A_yW}{)=(OjMUXvw0)E!CEOG%VF0cywYcj04;CIMZXc&A1*diS)9k ztf%dNV`}Y053KIOpXFYiH5b&*Z`?w6|GOsVT;oS4kDGD`&mSF~^N?Y64%Rc~$7r$o zz$Q~#A6Q~j)A#=Ete$Fq+KiUQso%ek|Loh{k8PLbsK@bczq^>lwg1ReANJ59n>ut# zS4O5bH~J?tOAner?V(GbcH0k)hn?T(@66*tzHb1PFk= z)EGW{?Q3Jx)7FXQ%TAJwWoWtn9J#YB?pi#UJbrz0?%l-5caKZ~fW)R@+}+Mzo&Nk+ z>IC?M7aQN?fOZr1Y~4=8Hd0ALWrjxc%LO^EAik<14dTAQE>u@1ldSWSHHbK zGoyQY^8=*%k5ZTJe**%P&A|350D@>Ixn7eaK#ihf>>LzV?z{v^Q`j}HpVO+t5FLkv zl)QqHw+tFGQD#cZu;#{+w@&Je{FS5>rOHw^a+Rk-l%OMO){E&qn5{GV0@;S_L=Nhz z+I3eQ>eN$psax;p1AVBE(kB4B`g9xgnLgJS`Z|3Ntqpv!&3nf{ zo@i@+ef-Vb2~YxawnR3H4l?9Jb5u>kCcHlGOfOg>gYj{7bq6OZqGhM%>d9D)=du0i z0lhHrM+iYnNy$m-(${GxSWBu{MT+rp25)mzp$2+)>xSkG6I|7X-X`;F+y{=dmsLw+ zTiS^a339BH%sTQebDd}1>EVr{wVue3`>l#^3De6|(>N^?ot(sHWHM4B@6+~Bch-tq zhP#n7rAQa7@oWxle9Wf?g0Lwz{YGzQ&90#vRyLAjvs*=LX*XIo%<+w0KK>*<+eACM z&M&-F@m;E`cm0aRW@tFOjwa#LDV^E5y{UKfu|D4)_BVZZ2#d%J<)J-HhSeY^i^*$~ zM&76yywS&7{eiWtcg#PnIFZ_7ig& zPz0XOFUxrTSz0SjYANm#g^WM_<5@2B!haT)hoCIR$|h8?8dmqZv6ast*;-_;^?ZF< zf0|pOY*YT+N*I=Bx7%)FN7D}4WS_cIH+yrl-@B)e{9cxOx_41d-_+x7>=9^N-LU)+4}L*Ji@_;0k;+KfGuXB7%E-K%E1*%rlc5Dk}dHwhne z#@}wG2fva!St8ry+W3T&dMAdRg=peVIGJLGMx||+OO*KAeV8gyQ^m}JS{5Ot$X?TE zyE~yK((>=V>bK}4`J2wsgY zI(2%Ocl`!y`nMg`r&wko8j0W~A=zIeIo-5=Zm7gJ@&T|hfx%{5(5=Z3LiDXe);u#U zN<~Gt!jq=@W;QvXzZ4T-nmsJkfnyd8qtTj zJ3A;Ui;<h4|5)=?~P zQH|(BLlwg~j64P*t*Kb*M7SQE>Su$*oUB(+Mb8v21l^R7VL2tHo1BHjr0a6FkTmp_ zsWcJ)GP)t7iF;^Wf|jm?p*Pv#`IHpIiz;jFO~9c|0i$gu{&r?RHG9pNV_&T&#i8e# zWQUv86Zcd&Go0mh6;B3D)3xJ<&8r-+LGwZoj>&FD6Z^*`?U^PmA;_JVou)V~{HX8s z3^#VOnl=$}M(Dsz$4}Nou9cxkOg1Vmb3zMKAUc&`YO8xQcTRN>PkTOySqhPqO;pDcJgI!(797B&UkOLX-lZDM%&WyTkFF%Kjd(n zlS_wkGD9$E2_a;{{$oBTn+?lmZ$hy?HrNa7^3cyzMjIz&G%>~&AM8xXpu-^`W1!?z z2K{;<*{sgx{U(*o^Vbb))~{_BDY}}-$_7l@a9<2UM6N?tJs~|Klo^3M_A1j5sq6-G zY6@oeDpIQu&z|4wS_%hk2jEl&e`mUudI746=L z#UNKqqn2(l2!YQmC4N_hCPh(VIxcISM}NaUQ3(tp8T3=|mmz_rEiSP?U@27nOP8bg zVQ4$%QX6%^q@h~bw;|ZK4yo~+mJCGd0Mq%FvJ4vN)nrqLUAJTR31LYU_$~~+#Y)p7 zUA1;>r^Px7d;*Qc(v9k6v9kCwFjJrA&azM3Hd9%F$Hx5!^|w^kp0@Uy8@es@jKRXV zO|-{mh-_)KN38p4$s2iI9xIjd>YLexxmd3!qxHIm z2j8r^f3g?%yi5*O$fxCAZ?#iULMa*_gcLBv0%kWyLYYLT2Nb#Kd$D%!<@Z8u;dQogIcvDpL z7IY9dmn?^43OX+tdef@yc#s>B|JU_@YK@^7iin= zB1GTDYXB6V*rrihsM1m40MZB!(iV%>q=3mhC-&M@3vX(mE85N&#o19uH^El+xj2Zu zL3ur93AZHcPV!2Z3aMDHM|Lg)D2yqsh!6-SZxAPe7txbc9;g=Y_w}AZg#MWvPLU%x z-&eQJ4TuO!&CwOu{=xhqi4OQ1IuY)It;?3e&Yg6ncCS?>GHURMKxc^Q;6*(xsO4F` zkQl-=;Dyf&LiFW+D?`BQs#7yB@b<9lqV1!ud#fFNNbC-Tokp5!0AJ8t!Dh%Y2bu&ChS zcZJY#pWFiZOk02u7ov1bEL4n1FerribCJX6SON44!Je$n?P0Pq&D_}2y;`oAjvluZ zI8j#ui*X(*Gfoi(RqC<h`j8ycArd5a)kM$c=Dm0D;{P_3ZWEt z$@rTVG zePJD$Uj9>`;zN3Vqv!U0_Vt{}%KUHiSx&OWHO8RVX zcmfe<`mMy!Q0ohNJZd6t98&F>vh(g?172x|XNT*fZ>?dZDrk>Kw;3OQDYLxCL?X0m zGW#?9!2qPEEJ2z)oleby{bs4N!P&!HaAR?oXqmG6DH79&tP1^OU@olhvyGUk8feAV zcX;ua4S|BCKb0E+yFgg*CPj>+7PDmN_a-05WI0y{Rq}Aya(?8j`dUQ>36xL+4cPR}Nby6R;+Niu z;LGAoue#s%D+DXwgWwj}@wza3JDJ43&J^Row~)l~E|SDLVzvD>bGh!Wn#&aEeBh!0);w;A@6K^?}Lv%`Rt3YzWHv)54(Q)<+nfn zFMIt?vEw+wUjnqXA@{FG({upXxQ}n#-i)+kyQDzXtypbTD+A-CVN2bcq47raICkcA za`L!Y;%db15+_yOR=+MPS^NRwkEPcWe0hn8w6%KejsLv$&bIeH1g5wsYZA<+!oSg- zAJd}c^#?UwS`tRBKjn3qOx`SV>lZSp`Zr<0000000000AC=~8IXeY&YSOI52qTR$x*M~o+aZaa z5?k^8Y?E%x^2qA_FX~pyDd+nBZs)pl^%SL*G8L*t?K(h0KgVj7{E;TneE51=JyG$s z)%Dj;#;1iw7-^Kz-IzK*y7*5i+wW(!B6De3w-Y*#hoFM(0^|1UUqt@@oMj;|Uz*87 zv$4jRXx7}M$<-Vm;!KZ!iZt6_`dIDnz*OF{%2m^wGUtSJh!iEtRH#z(P1qc+3{Os8 zK~YIrMO95*LsLut zAPQo{9dyolj+{7i8PVmK320VH3=EFCBDU%Zs5hFg4M0z9_47cz!+1?(1%%WI{QZ{yF%2lWwssI=VIQ8i_VAzOJW5!LGG-cY1%fnTW zlNDHX&6?}h-LO$^zOuy=fbEk42hg_chXW2eBozu34IM)kHV!TxJ^|s8(cU$xw${ z8ZyMJG9xr<+>~jz%((52yJp=hbAgO;+e!lJMFYs0N*$Qqu$uAm(ZIfUUfI%``r@a9 z9_#@I|2FpLe6{MDHP@}XVWZrfZS80GIzy~eKI{=azx;m}Y$2fI2JM=quU4G~yUUr` zPBrjD@nVV*vBP-pWhQM>j$ohHkyUM{>TQs^2}K7Yw#%NEFZJ8(07vMS&L5* zT1x$*H8EM0Q2h32JK-k@!2DG|#ZQllMWOly{JK|@IoL5^MJ)4!Fav$Ef=qxDAl59% zMw6;xA5E$zRg=0A`ZcMV)RlcF_c*!R>Qn&^UkMmiY}rI#Zt8fihT=Snpst$vf|~Di zultLKA&0wJ)d2K$LJgpg9=&+TTzWAK=mV&QVhHpXY80eXFH^5+z6rrrkZO&-ChJ(r>_^A;U(D8Y|Y3+WcWIzaWZjQvSuK%Np{QBSvI z=~X=d00904bwJ8r;`}fx%kg3YaS2H&X&K?RMWIJcANW|j1RUX8yb2tr#}~YwobD%e zy@>>&^sZDV%<$-Lt<DU;1!k{9`WD3Hyp zG<$tBt6E<*&{rG6$`7hKq-4nSa!^9CMZ;(+8t<)1wlv`^Fo5Nws=^w4%BtaMeAN3Q z5sMz8DNf9Ar?cXW;+b%5MZ=lra<_?#IkCG?sq9%swtRA4Mlu1G z%U^TLDQEM!7lzNbiXqoC5XvB61zme|3FY|nzt`dS4zZKNIB@C>Y-b(y!;URsq#3*& zUU+P1Iodl?-}nfHznK3-52%J#yyjn@;qAhlWdps#Oc3#To}1EKPsJ8vpk`WS43VnL zLw=s{l-+;%TAcq|^a?w3mp!)%PHyMaQw`ksA1|c(iqL6xM7f|UV!i>+gXDkE3(Hh@ zEPALxw%lhQCQ;mO2|%6rWgB0lX_N5s*Ap={U=gi<{sZQdKfI*uJn*qtik9hByNRZ_ zkiB5KtU;33&sTmKSP%fp7U*x`mfI0h_mqyv&PG%!9!q7jV$quat5uB6Rr}ry7UOrz zRPihB=MS~9I!9v0N079BYcCvxlCDygoB z^V@bT?%Z3XM{JD(l#n%w1jXP#Ir@2mso6!GWENcnu=+s;nw zXNud?&%dRc*RAJbRVon{_;Q)jXY7`@lBvrc ze#Ub8i#G;LFmt%GNeaHFGblD6el$*y)ihTw0Ts zzUV@mQd6#;XQ_oEZU&!Yb$lag;j=$iF#a%}ahmOZW1jF_qW4kkSKLf)nbfCB<<1xI z?D0DrS{~+22hZUf;BW{(o5U-)47pfnbzfOBo2!PV)4|})Awk?>xm@W#V&lB!nvg8iR7ca*}TP_y5skScgnwCp#){qtCNIJJlo;f z%+GC$gy);jyP~`Qr`0=_?i!R!+m^$qmqKp7mbNF4^S4(Kw%B@v@-G*k$&cEfmfR*A zFFj)S;l3*o;`0-Jp9Je(@6QT(Voh@Ds2(KOP@Y}Wck*Yrf889)Z@qf>k@A~0_2lo? zXxy5KHPL-$sER@t(D2RF)uJ>C>+)Bf-?OczVBwCMGW_>9)hxt-ffeb-oj!bWbSjne*cTWDwKS?RE3=aU`T79i)v^LCc>2qawu)^06P^p z0yQridY~_c@ZWR*@jt*AG{6GhU=#(Ku@$q}A$q`R=o?&P3?Jiv_|ARqP!mtYon!@1 z(p0>ffItz3yacJkVN<8upFMo#HJ-+*f8Z-C4di#*QcxaV0T3e~t=C+qo3E?4du;eQ z{=|oi+wd44*Z#w^a985Grke7GO5AXmN4oCOo_u8ka%DSjdUn0c@(l1A+(fM#j6uF z{B>;NK0ubS4%;1s2uBHCjyYD_Y2(;AU$AolbE!NQNQG?Us`h4zJP2Hwu0Dt98`83;t2)i9GE z$q@;WYH@5}3{VLw(=4t4`6?5FNUSu4M=c+9lCJfR)gEKh}(XFR5a z^Da&P#mM#)#&L3X%meQ0_ySTu%MDtT<;Ui)I7jv1OSW(wp2ATM&lgEmAjtE12FX+a z6$k*)f&VX3r{*sUs?!282r(7`LR3H+$)k!YtuCC_1Wgz4$gBl|Zrtanpq)SglY4P^dqjAiBi(+0R_z#}&}I@w2PI2~ zalwf7tYihN7^ArqlLHFTM^(sJAOr%3W;Er7f<_lxf?o&X_PFE0r!d0?X4tSXgNBx{ zSP-Xy7W~n0n@mn3+Ni=o>=S3+>cEc$N?9w6Lh4)uW-KHa1u$bd2LE5@r1ELN*dahM z^m+Ih!GKStQ3E?Y4N`Nc|G!57GLx)h9co8e_9G0zQ4J|qrQTqv zDGaFmA~&dR3<2H>G^9BqK99&Xi96+AL-MSGf|{|I$pRWDi3nH^YDe*xDuaAO3P`GP za*(r9xN$0|-ZVJ!wBZ8YhaZCYJo;^Y)+Dx9^(iK@mvzv05%$@>fmveB&b+On+3HSGHS+Wv>KDx zPo=F)5N87Tqfc|vAe@+$Lb48g(HO#nmueew`i&U$a%pT*@$}+#Wqq^2e6{95UgkM3 znj&at6yBvGSh(c({AjGAf*FTgw&m1)5_aGAQ z*@^?uX$fAZm>oYVR)GB4EAay4U2T#CGbweZ0;8(ahL?_Akrj?*M$&C z-rH?Tla9b~XJi$mK1vc(tS=Q$s-A)9{_w|-V>}#7z>2XZe%Z|}HUMIOSOka#U>TtV zxVF-1544}4CkXl$W_}0k?7VM_um*}BwGYl7V~D$loo4Rf+N!y4Ugcy|7z0X_w|3cXX~H- zH}UhYs=?^f=Eny2R`r2{l@-z7zr(n3EZn+v>`?7TUz9_WE_~KL{{ekqJoA_Tzm!B^ zOKV%_ehdo-NEBV?n<)2K58Y6u|v+ei<8LM^v;H_1Woy(th zN;@}y+o|u&{%)V=PN7};aC!jU<}>qQj~CuJ|L4csKJF+n{sVe2O&a>MvCy@{?@YC1 zlkfgtz_iQt#@A2(-XFWq7B7A{cJ8cyf6u}=_m_XFT=?v_dZT$^PK?e^1^C#24{v?BE-x)r4M1AQ87tTHYoj*{f*w^_&iO#y&Hx|SGu6gnQZOqU6zCSMMyYhF2K!HGh_$>PG z?dBi8(V;%*BlDdeU058QvXkZ=@^xYC+TYZ=RkB>%J9Vb-_)(L)%MNZXcJBubMb1BW zXa{@G9q3$(A^NV2QAdC#R9$jd54-a+m=F6Ty4F#_W;z@Gj?GN&GdU@n^6zsDfmx4Y z>ZU*11N~)lp=0?Q1k{~}$?K_q<^vuCO!U0+ot>ez`*Pj$ zV0`gqc!^+x{b_{t>7zrlWdH8zxlj9i^j8n|M;H(Y0?38=!T#%5NMqj(U=1MAZLg(*nOWt&ro ztyr&~jm)+L&UI61&hz{CD>AZ|6a21@6sxJaG4MDUgZ!5VCE2Mc&F&|f2-l$L1D*$l z6Z~Mfc;Ie)wk}W(wrjl|8l1&k5RG}9SE0c;Z-zge#u<9kp8WQ~>E?XZ`j@^vO_JzaHaV&hi#7P<#j~H((!MwLukMDNF~Xv)Ig=#j%jSI02`A6N@%6lVrHm{=eKwJR~lgACgYDM!Qd_ z6EjWDL!D7>lj$t(62k}*+hLTs!>pQ7TOjX|e?9h_x@7M8mgfwy##wwdoKCAlWhJ=R z%ywVm1@KAJ?;Zc^;qvpcTPHex&)%Z>_W3eJx*dYEiOlwXijW+$j$Fl=%)65J=3zwE zXXn#BrNjK;{=tYp<9_OYKmY`SfB;%?fBW$sF8qB31mMU|kL?Cv5R6H^ffJArLoT5F zgJ4+j1q>bLC~&fY_VQbldI)(Bsbm@;z2PGmY8(5=PyI5!jHM5so?kjWe_-ztBMV%Q zZ|dT_5-$LL^MNnQ(IMn~cbQ2(u-JOvVzCh88hy;l0tJ z{{tC|XCS&aLsD7>7wXpL=Db#h+1^DHSri9-fI=M@tx*#BpPo#yg?75&{XFOlr_EJ;4Ja;6VMwqA{dX8clDK zLLQ9D6cJ%uXAptQGpn{4rkixF^N1u~+hmMHL{i#k6Ev7@0{p2I6|^bS*T-G)y(Geo)(4RzmQ}vL(;6 zIK4d;jLFDn@gRaiW-52CV_>zMkWybj%S*5U{BzlE3Ee(UdUhUn(`n1Q+7D;OhTX!b zcC82i0gfq;y=MpjNl^E6-)|(`oPi2YI^gqkqX}fB-hb3~HE;H0>#=>~hjT0f?$;G> zBj@FRpY@9?FsIb(IKWLl?*LqQ(6kfoATOb3wo2_XU?n8fJ$KVLEDlTrTzgs1|Gx?V z^XjJK?_*bAvB?E!fguR#%JE`^&Riyf_V`v^BEkXtf0k(whk^fYG)Lr)n_AHlWGR7$ z7cEJ)Q48u5WjsdDljqh>ASF^?V?%wN8{vjD#5AcW^m>mz=-$%YtgIigWyPcX^|k@#&}y`^QS(P9#x-iwp(1hGBQ*k7F(= zn5Ig)y~-8MIP+|)SoJt7T-9pVwCe|qjhp$28uea``j59xyQ3Lv)DwJKVG#ImeuXWb|*?`fNFi!QOCAoUP~W^B(oTOpFj% zhD{4aT|A=r!V(ZCBulyt9j7TyTw2=V#g`zVM0sJE2eJsqGCaH3T*`t;!ZSIq@_1Lk zr|hZI!etO#@p@(Fl2eV`Y8O?tqRJ)ItGYfl^=qz7d(ArH>5Olx0SlUD?iNckT3g`h z0dI?ZEs6D9yccWeLxm=FHLW{~o~*LX$YsNiim%2o>dK^M7RfeQ+0jwGb?u`io4_KB zOC@p}JGB$6w`KXxPS3Eg7Q#X!WT|3(qe`pNq_&zCvjKArEnZ*i+q~Ky%dXJ@otdZH z9yb>Al)D19ceex}iF~ zSV$)-?`gH0-cvgA^vlq$6}X{F09S8*f`aXH506rXKW&Ix!V<(^1LB|<9|mQ6%; z@~c-+gTfk>Fddd)O!wh>Fa%h4=n_qdu9XhmDA zf~^VlP`F2uy^?B6y4NzjF_IUS51t=U02zT9i1!BJ!=dS+~qHEsY_nz;#WQ@0U!jSL}*m}+);?)k+h_ds-Hdwc;IKL${f8D zsZQVrSAT7x26=W(ePL84LIH9~PG8$p1o>l4OOaK&_1cj|kq6g|PF`hN){ad{j;?M6 zQ2pt(zrVof)2{u+? z0PdP{5AO4EGY!)MYBBY}I;=UnG1(VTTs}RyZ7giC2@?GKpa(}`5)G<{oXo;e4Ka!^ z_$h9|xF2WCXdlcmxN-iIU|f9_lrLWLx_O$~^}{4mhgZv*F_VPcqpIi@xF%ONG4b`1 zn+T&uVFg4KZZ0j)kE^H~&pK)Z3lo7O1}CBys@H*6RRe}gc-r<1kZOm+ugO4wG*yGE zBqHSnrzt<YC`hLbC3c9X3_n2qWEche2f7477Izl)%&~NLtvC$0p`0 z2B3irW(~&p%aAtnsC~d#HKw9;#lAqbNS67--QhBKC=tQ8m76Bbn$M0+(et*~+v=T^xF@pVn8DAwiQ( zQ#_>p4e4~Z?{}^CZKx0R)h99wJIbfT@OYuhQj9?|dhmVTn(Y~D5_$2lzy1N)6XFq0 zU{H=i!tq1WN;slekSPV|V9fCML$ILCKtlj{4}Pc{e*cBV^(OD!I?*)c!8C+_z~D7u zFoZ3Sv*H(YJleb+&X8(8aW6w$56i;Y>U#X>^G_JC*G`fQguV?t&cCsEZyCdiW>!qu zaKOWWUo>|lz4iy#!qVUsXce!RdyA`w*pH3^@>7&rc)7@5e4@|Z0BG2z&O$gF#h(Wl zw>g<>fr;|Q1%AFah@*j<83?{!Ou$Z)`$+bOM{xejcUsLYI4m0m{a z5B~B(pa`3g)p7Ne>1K|>ZfcRCqMa&W1<31!)Q_@%&KkS#_3r#6m(|N+joP~FMa=rg zpEH=brV=4tXBz88Jk8l36SE~^*P*xF&jF@i)P~`W!!iTkxS)EN1^6x{{p1X&i|z)w zsb+Vg>9Vi(m`?jisM1D5IA#6*CG^4_=qFeYK97DH`*Dqsu41{UP-swN=Q9N41g&dp zgT;H7x$a^bWaR|4_j`_^+}4yJSjCL03&a+uNbQ6Ax+lU}uTsK(G1KA}=j~kK7LHQu ztU)lxj8GGv1sY%iJ9R>)L4Ntjkq8@Eub3?G!#=Snzi~(X+^5!zl>unx4CEvRnkZ-( z=L^KpY5UFI6a82MqyK8F2pk=AGq6I%tpzE7ipx2u!Xkto6kg314K%E9CpMsd&pBb= z>X%}3E;{{jb%x5^T&M{|=#K2&ACl=$?A2c^WZx$96;g~2PSaYH{Nz&*oWY5y{T7T{ z=j#E6pRDb;C`MGqphV@OjA!Rjz?8xQLt_jr#sK;VK~c7M$5);WC_W={pQMu)uZNTN-3 zAgNpznqYix2OV-IE$Vrqzo|kZT&z)$-Rfm!8Dm*l5Y66o8Su!~ki*y``=#Ui6zK#i zrqR7pBf}Grx%W%V_i37(&tAnC+bR|5_(oCCgYa@E)KfApXGp0Nm2fJCl(7tv5a5F0 z_g>wy(o=zY*eu>fB9m%21>3zUZM&KV)ERVCc1uBFYTL5OkUy+(Hvm9DzrQ5|1bfz6 zd#h^*|8e|djh@(jg%I{URbE2IBGKJm_1o}F`AI1yxom95IG2+~s4p!7&r#S^|$LZ2sA*#&B%$3K?>~u|s5MigEWskX#M2#i@*K)>B;iZ82uz!48nDdcY zh0@t3juw|KjSD0pKV6(Y3}n=vme8Hq+8t^ax3*F~0>Hd~CaFfiZQI*(_ zPdef5gCX3Qj8n4txCvg{{yMocD|u<59^ARK`o!e6+(R>@kYN;v1`tm=MQV?pMZ>}| z06W>&T4T%zfY3dgr`2VpZ|J;SOmtg#@ z4=%<=JH=&j&4(|d#4H@MV4F)gFl z&^SNfgp#=!S&$#KHnNy&rJiE-@H-11IQ59JR>Z$y%M)ffoWx`CLK0z| z+$p9t;2(`pRQ(=zU{-$H?1g2CHeuyqj$5hGTnzKUW85`M`1hB0iUsRM&K5Qy#RBUR z5br%w^WAsd>GPpGur5)dM=2>q$Qm=sDQ@xG`DSsdIwNC!WCGl&urbQKmy=@ye#p+E z3o`f0xReyI0zw+;-X$T-RS-aUe=0q)ifA6o&xA?HLc0EP zpiD{XTTm@9Geqi)l}BqN%B8xUgH?Gzmk>Q$WFA@hI?myOF0F93jv1Xe-3^X&H}Hps zB7rqnuoh(hY!0ydiQ=mEDi*CUQ}nsh&A6LdE9G|YrmJob8GBUKU|Gas6*bQqzzUr0Omog!oQG${%ZCSTKt1%@ zWiGY0P>K@6x1=!hb#;aBjJjP?IA$#44%)CYT(Q{tLl+p#LMbP)SV$Jv4=uydB;}TD zYTBHT0HO><_IcqM8tU(Iauc3^nn&6PTjO?!SVL}K;a*QOT1ZNNm8P#83`G)|7G|-S zN)}j5GPx;Y>)3}|j7^xoW^nr_l9DfPxje3pP1pm|*9`lJPvvRcOoAw_*W$tI0(H7A zIw{W965z6LG28Z9&rTlNR0%32o|x}K+x*6VTJDs{e?)nWY|m9kqHuLY+c$YO6bZX~ z(;{kK*+w;@NOgrPIPVTfIW>n*>I+hqE5} z&D^ldv)gkKjvG<~%w1jyL`KoWUE{KL?i59lQV^g<;+IKF#P*AMH7RP{OrU}Ac8$k- zdkkk$H>_LZnns_(#9pzlDq|Y^BgGZz7?0~Fkd2$T2*Y!x@;f@ii!2c6@MU)zgE;s1 zb4=N#_2tg4``B=%Bt&(Df*9)IZ`Tme;S>*i`Qcit^=sBAzINMP9=DMcJJ0Flm{Szz z`~s$nmwCobaB+bwMJRY!eiv4ez7WOE?=P#BSIFgYiPdW`F}Ce}KVhzaTqJ_7SJ)~I zP9Cx%_Ti<`XK|y#dNdvsUTow>GXJRuDYWX1$A(yD!h^|BB+q%n3 zPS2JA2}b5&Iz{^{kkR>qPj?00V$SzYJ@OA3s(as_1HAWSq0A+V)0qnaO1)-nX&apS zFCmEZp1!e1$h~ac?hCF$CSQpJU^a?WVXm?5m!G`rw7Gj^?gWr*4$JooQ{2{zo;dCN ztk2#Tj_}8#{XX0p1`Ktn=Mj+VDNQcJW)HwQ(1Z=(wMOu$!diB}gm}93( z$LmGk)B=<#rdS!L*{u#rE+y4KyR_d<>^8B0)|7ejo$!IV&3(!ZE6|z>aB|=i_VUK; z43}Qw&EU)Fw9=o_Go2U$buazp%-x~AbJ_hR79l`kj|_HKu4dUS)*KGXxztL4!V^c+ z4O1)-b5Bos_kvIl3+r75KlUq}IV_`Z@@SxHKVU*XWK@m>(S*g%AcgB{S-ZScf!)PA z1aOnPs2c^%9;FOYl2Pnn>Sb#B2c@i9w3uj(_TT1$U9+OL$xdWKniGELC||| zG+I^z_1Dauc^7zZ7`YI))Xa1M@(?4;1C0Rug&v{oI8nL9ESXI;-9Q?ZZU*9bJp8<} zTsUm}8nF>MCrf&EZa4(5=0=W#2%VMLPjdH=3uB9eY(05e!juyrBib^wsNI0MVqO~h z?JGOjXU~1C3v7LO{JA7K5h@HXNdTOrZZ{xMT;lH=ee$lWK(M}z)G#Oj#P-8#x%70U z>98v8Wp)bPD_Je_1?ekYXRECA5JdX_J)R;xH6 zlI>s&QEk+gao5pC^eM>TP|5airI6H1f1p3B9|C~+*9}7H)y2oksLeZ)QYl!KG_M@O|Prng!bpF!Ygp0X+QAc}bpgp;)fs890 zCb(3g>h3A6^5Y9F($ILqzL!3f7_d*=ajn5t%=UZzQ-xY9<1u$G z4waLZy<^u8I5-$JbXTZt&Ffjo@bNJQe2tZ9n;8~KqnHlZk9ox?mWER9m;>a-e=Czp z92_O)i_*^zD$$NGM2{NxAi*-`Xm}W95;x-E86s<=O1EmiC)=%_@7~_Q^aREkf~zdn zBfVpa9vBy)CAH^X%}(c*6hbxuvN@*P7s+9X_@%lY z(S#phc`fr>ms>7>TXO;QsQ+z;aeuyp(e=e9XJ|@i!`sm2v7EYNU$P?Hztc%9^Y%WI7|9ov*Tz z;S*yF!ADs+jBy3&4vRg)JKH#PSxkZp$Y1Y`%lLWLsm7EfNBUkGV~R4z_TP~_Q69*# z?C$nd1kMOCD~{L9|5R7x}G1PF!r9PqyZm=IYLCkbL!?Axd6RRAO8E;OC{5Hu zQVa1jdFAl;y|S?22G;J^6A7y-q*;Azp5(u_ji-aX_@f&dP=l?%t-->-h3kPwM7JDf zFDmu*+=OCKkkQ|;q4h*5I>_XocT=jdT`Yf^N8ELRy^u6Wrl>d)3u)12YDBz@TymfA zRbg$ak)j-Wg)%l?N4BO3Fa;6~SfrZTPeT* zl3hHDOAg!~DKrAh)pQg6E^U6$RD)4`SPeIM*opz}1lm$<^!Tx%R?PeD$U1g)?0V)Z zivb^-5G9G3thFq0e2gLZGhP6@MY1PjJsgB`1XCou)?52M+_N~L8G8c6YW54QFlgO* z8B?ZpU|7+D(kO6bT4%V`>FK7ibylVoTNDc)dg&DI8yojq$a%*RjD+y_%Ux zUVD~up@=V`wld6`cwXrZZO*iK*^5YLy_0pUs%91b^40qeVVd|wR(bC0=&5JE$7gvy zhozp3mXlv)BvguI5oW*o);{KHAZ0^X_|~s<7JEA_jp-l+P$K#(+t%`nFzGM%G4&iknf>fUF zQ$k6s)pudQ@{@ML>-&^$Wqf#vU(ExMwXw~?GI)RxGh!+uWyHCSspwB==hM40|T0K8qiBkwNo|K}GVvJ?rD zi`vAHc3P)>Q=(XVKKE;0OdG7O)GoU_SC3E0i#HQ%{(Y(y@4!xYPQk~@wXr+lqRAHm z5=$?L{U?=o#?~t9r-J1GLP$p2vauXOu&x0-rVigYqR()@4DT5c+9I=OTn9TV1 zi6ONU>(1{IKT>+N2-*gRY)*Kg_wl=iSF zN|>H{7UB^6!N2t{t#g5q-^!{1%_|QZZ`ww{n3b#|Pg|v!ZjAp?ZDURFm<+I0hw11I za6m0+n8XP>SjQTlX`AQO#9pKdJ%%8D`&$s%$Dse{St*(kmN(S@B+(WC^O%op9BaD) z3YzQv_a=1OvSTVLKG&!%&pnIs)4F25eXZVt$TGxV5Q@9);ze?aFf%7M?!+hADtz`B zcx^Cgo*vSp!I6v0u|58dyMhtP2W}pNTNz0T;53Fl21hzPZ>p8&He82d5?c;4oiY8+ z&8`ZBx_hQ8;ldz3hiYxd_RZTOMF+e@ip_+g)iI=WWHPlN6i`#Fgl7}9pCLM-1xFc4 z3*l6z4u&Ut$|cC%#tx{bT*IANlW=}8n0>YleDfEDqtr0uwBaX%N#_xlUC~J5pK;4# zq4tq4o^KA}AE4d2j)TGwJA1CjI|QQ)rcnqNqGYpdl~-&ir5mm`w@<(+L=e+dJeZE> z&mnWu-BzmYN9e3DH&!~=!Nbezs8)8Y7>t$X5B|Z5?g~gJDJTM_kfN?`MpV5D$dztb z&Zk4WyAmL)xw+&N97cHZKu-_0`@Fb3E~g6bFr1&Ou)c0j!d-0)3sW?!tX9qO`1R&! zFfL81BA~J%KIc1J^6wUDi0W7fD)8#2S90l)u5KE1IiFWY%+pz|nmtFm*0|`zoRft381mYj{vi^_RGjIK0KeC3^C|3j zBdXOC`PpDPRL=4ms*PIRrTlV|Yd(4KL@@dY2LD9Poldk#gLLCcJ`LL4MTe~9=0>F8 zv4WHPHKx9gPscT+JTAME;4J2)o7AXPQ#|fRNuE+$?)RX>O-= z@Fa`!@qdP#ah7S}Cnr?jsW+7=Z8VmhbH3dXv#hXTlH%dt8)*GEvf&A? z$45eI`Qkqmc%I;9A9d5IBW?o$b}K&`dfKYdsE=@~gRs>zG!aR4Vw@kL-z@@DC8v0_ ziZF6cM=Hja%_KKWd9W?Twzr7%x>#l(0+A`W6mPqeTv2uRRdi?R1E-d*LnJ=FwbNvj z9(`ND5NL0|B>23f!n+-rm+rn&ZIAEX=6+Ixovp=%<u|(TNmv5Br73bPkmH=RZLt0BdK?-L%7lI8$z5)&#sT+$cdSB_u_A{6SQcb$Z zOnmvp+LTkuy+$Oq-|ly1GvBT#cgtcH=SZycRoi@VaB!t{Ms=C+kHZD0SZ|p1*N@og zF2$K-d`UIlpP-H;(Sud#hRbz&rnuBo`?}?|GEx!0J)Q>0W`E@y=IPIU@MQ<3Onk%RLZHSU7!|w9r&~F0H0h-b+S!q=ea`(e%`F2l1{X@bcltW zaeV1}pHNfaLsp@XYW!QhfBk!UG1`y<7V|eirP7?9YVOOY6}93fOHo6*zqhQ|nQZ%o z-6=)KqcaOjyWU{7N}wngX>f1c*NZarpS-H;M;kgCz&)B1gWhr5JUF3iPLS8 zxy-^^AMb&B;0bi}Afx2IJP`ft>~}sH0hX`Y@}EI_P>RIfiNvWffJ?F0SrkHCO?Z^? z3i4U%ke^zKEv|(e2r+Mz&i0t_(=~|gm`BK?2lMeh(jOu*Kk8k|Gw>$L8W4gO9T&Xy zQuJ=UYnfmshadidlb?~)cA>5H9*2C3$o>1uehm)j{m%<2koqSF`~UbI?h7>1{{k32 z*#-u;3!`~2p#0AKXnVBfM!B_WE25}uVh3n`Ag(iHcsI;?Y};>_}CFIomPt<~2YBv9Pi%PBtf z^_=h^P3JXtJJ~xOto)Dz?eX%PTJKXHlEwZsMte!U=+%A)A|cc}H9qmM9S3AS#DQe! z7F`e!@LJtWTI~?dbbKrONx*Ip{Bv%xUcAxuSOmuxdk+G;3n(|M0jiN&D z`9ESp?dRir5-qj;Jme5Qq`^mG!o1mG)5q!$*|jFPCA)&aIjDak-oqa;={?H#UU+l% z;lrAI$;Ddr$Ol8+paay`;TPEtPq@?E;TEC@49*?z-u%XV137a!{z2m}V^>O3n3*^% z9c+qoo%joUk*ia!8o}RdZGVh@I{Vl%{?gwl4F336R=+QsmhTf(@)8-!;^{DOA278P z!D^2LR1m88SE-MSb(I!lUu?X=T1LKp|i`=!MO;cK^r5 zH6^^^c25^Frjt=ly1=17Wfqm#^ErO*t;=7JIHU=)N>WJ}6yrH5pHDmfa}lu?LcmP{ zC8MwK_49oZCVc4?Z0KNfz^k0fgxv{AZthA^!mc_8`|5HtR^wG^z6m1Vn;*Npd=;g2 zR&}J%P98*`W;1sy5lL`_DOx?rDsnm9edryE5g``k<>Vz)%4?YJyrFS z(M?Cq<04Ofa4}LDO7+R|t@Fp#!LJh=Z7-kDJBEYU6x%*CjWpNbA1H0iwwo`e5_=mR z09?{B?`&z4>IO;$tZ{f+4Vp!ZhNWgAsAt8=jNI_}%x^k1kU6UQ1-rUP#sJivc1jdo zsA|9ESYeq$6K#IHIfxY1$W!WS#EuvXtGGr_@B6PDoo3EbI8xih3EH~C^Eb14zzRv^ zVgB7abo1`ZuaXnnlJBSY#GhZv!&B7`jH;3xkt|yzh1dJ~Uku$gamx*7l%36gkwc_p z>S45+teUDOBOg|v6e6{>J#`jG_Q$Y_sVofDC5}-Vd55WU5E)*PZ5kb4dDBtVUZ`_Q z#G(yA!6M1YNBKmN;hwDXH**M)rLDMQ)LKP+RaSX^PFGCY_p3u3VQG?|TLPvY$C>+y zZCC9X71>{YE!ceQCPYQ4_FMAhRo)E<5BYWzZ`iS?C9<@&bP1UI(*^jq034C(j7EZQE8_g{WAZt$};tVLdO56C}1T_=}(3F-x0bf$GN1_vR}LQecM~_ zm67FTX)6PR*t`9!4Ov0)dYO0nPO25f%H{BC#~tJ3V|f@U6UUK?IeA^DL-Z^H&OpmM z1*l=CEAMZ$^17=P@DC2ue@DTHGY%5YXML4@5#5W!xmx)Bvs!g8G7n?;*57MmrHV%nspsqXpZEa191}a=Y0$2qsy|o@O%@L2AnnaO zXFs<|+Hm$|_e+ZAQ5rS)_9M!o$Ck(51E@vA_WuM8cmQg-v^3gN#1G};0#A1Xz?;2$ z0KS5QWq*QtY4G&vwK$Wp+}x85S*U~^Krqtf_2Ngxjzv*88sIi6Te5J#bVKNM_SSIG z@V$%Af1fw*eheJ*DZtIg}3Pfh#MD+{U(46+&sO#LCa}Z(97<10knp$ zH`=jVudj%rS~Ud;S>Xadw;H#6z&7^`^jNKVJI%_w{kjo#ZxJ~SjFOnM6En}$e99!4 z_AR#1?l;||i0_rZF(sj+sD769HOL!uaGER3&h;9rV`4lx(=HB;q#u2BD>7EOJd||X zOt&813+dR(SoH1h7kl^;kY-_Lk~@^~otj@}etRoqrl#_=W#Z ziLQFzJNW8&O4w9~F$&hzBtY)Dc?;ok#_vudEH8#BuwVVR$ig-86 z%8RMu6J|oG#u~(tl5~|C%#@VMkYj=R+T^vQSeeYGOPq2Avj4%gr9dF6d?C=Ie6RWF zm50eHMRvL#hj$2Sma)C72r+lx;$(b5yIw78x4e(gmFz0&=J+l)JnVmp!ANt%p}Nu* zU=J3Hy?n8&r*O0|$R#_w`syg{Yub@1a1lzsAOG0h+1U?RslW=j3|=7o*GHiluUJT5 zb_@&+JT5;Ya<#o@-_?>cj};`Ru;U_-D$!qOQYUE?KVnj^7_!ML=AF}90DI@TnnRs@xlGAT0G0Xu2zf#z|lf?D!N3#Ak~h!XO)&)`}d~tFXg@} zr!Xr1E~4^La;0--D;jvb5?tLg2OjS6ylCn~ONi;jL@G)s0wIVeQ?fiT$pBc-ROB^x zH@9D`ZX}oQE(bZw3Ilf!URkpA6tlIYvjGo!=iH4(4VyjI(!G*)+vJ@oB01o}tRHIw zJJ|2r*>)BjYasJjmE?(-GwgRYq5=XcLP9HCLcn|ZQwc@w!DTfrU+pfKcfvOY1Y- zk@EqwWc#Z~=Z!=x?p#eEc0VFUsrovDq`dSXs?qr{*tr0u3~aSQ=T*l$FfA!)HHk{n zJ5in`6D5(opi3!}$}+pt{n-ui9{Jm?CSdUy3(tdrANys#K+gV2@_2EXx9(drBA8nH0xU|!2$j~o zgr(Hitosg3dc4TGULgAClSa6xh@(c#= z-P%8EC>+z{@@p<&p5?H8Gm*9h*f+qTjO91M=iHk?RqHufS^xbQbICWtf~f4{rJD5l z(ypdIdw=n!Jke}#Qx^3fX$YKQU$SfmXzp9iYGb-3(?(GppW{X@y9?AOu0k2S>~|wc z`NA^90`&fV{rRu;l_xx#*JuG>w8yQ*jdLK)z3;JIim^CuV2%^)Ff9P;=tr;R(^Mc} zWsxt-|1W%Oi~#d!;1hJh;nM|ycn)rO|?PHpbYL=m>Yf|%im}`;rc2-Hs=Ad36wqYG6O&HlDpih zqS>E#yx9YXM}!m&?Fe{uuAsaaG$xOMLh~3*L>LYX1iqFIufn5pAP3KPV|$jwbj*bnI91cD zxe1W2ZaQ>1pI=AJ*IBQd<8iA^Jn3=gKTc3J=zfz8g%pxwbqnkdl)*V z&5HfnxoFjOWp0TBnO83W7)eQkUeIkC55IkR30W*^sw%tO-N1wEKDNHUc%||ZABF(A`pmvDqSb;-weh6&$W<3Z8^KH2a z#17DBxp5q@^ zKT<@ckGhjE^CWZ37ym_DyuI=>zeBwys%7xKkqMJT06b8^X@UB=Pl;~lSHP#oUOoR*<(zU8lA^5pE%|36=oO%Q%-_vGN=u+;*XINlY5Voi?{_}R+WQ*KIIfK*Fq^Y_9GJBit zeV_cX`-JwYQCC8{U;*)hq64Ik%DoRr__cWrCuMk5V9IN>Jd}2Go*IVk7 zpAei5pbq-u^T@R)FCD+=AM@Zn&ASy$ z9I<2FEiHFb^J%C=NFG$;-VC}La7wAogdo1ZdKs1EhAa0g_rVR|bfY5xB|I6*7|75C z3-qbSYf81SSs%SR`CLMzPE@BAMo+%ru0AEKziRBAe!?sfE_B2FV@lz282G-06nuR+m3A~l@5!& zWnu|h8Xd<%J|hy?K&4eL}W~V@~!s ziQZpucxmvcBS_-zyOeu#y*pNwIu1`YG^asA+&LP&!hHY19&oV_cs%Qa4UME2(sP!5~Nde-DbS;j2On9*}HQc&7 z)Men+((oOzW*t%BVMVh;dI$+GefW<+$t_zyn9^c^ULk3kGp5SCp&!oyDlor){i`iP zEPz0(Chu$}iZ(MaYNNhHdS>a_r5gpqA4UW^qpF1d-4T603G|QJdy&LD&AeNZ#QA0C z=Lv#{Oa2u-zELl%349plfNS6dS~<%_SQI>p$q+4WBmy};x4qH@Dg;<$(ZS|?Omg9i z^q3;E#l0hX3YJ8=u@UYXT`MR3X*Ma0*g3AKW=w||r+_X6nTdqG6Qb&xjRN|fU8b47 zwc7O)60p)Vlwh0HC6IfQrER zYrrFO5m149H+xK!l**ztX(-)J+cUs1%eBI^SR@~S!cJGtR*u0I#XX>?li*GwZelY2 z5H`<3i){;zhCBgWe)rUHtD>1FT)5fT?HDUpDt>JBq`Yfts8zwta|ivk5$YI6BFh2x z+`-PC^29S}hcK+b9=hdjm8_O4sj`g@#Tms@&u&b(dez+<{uLc@3mcMY#RH2@uPb?M*m$CPDsk2l)OASFfa7 z_4;|>a;UE-y0}(}RFLhps#&AVsgA`d+poFN3`3aE5~`t?YVH0YZDCW%_>xitm(E72Vqn*7;Tc43<2qEG?Se4GQ(iR1Fst z6%7|w$yD4ZEGZn#FW`BXhx@7Xlp>=rpf?KI9Y|cRDl6;Wag>G@{cuz)mZcMWmvIr> zs(h5iMx|V+?uzgR)UgPkanfEvoD;w$5F69)?oT@>))w|Pl9rKuGmo%0l0||YCl+Z$ zc}4xqp`^FvE;(n?gX0U}3-_PwEdXS5d{Y5APuR=zvom_r!oF7i@tjE7g}bE2vo^T8 zJB7r(W9`UD#6oFV)Yc;ERjm76CkF81RS|f3aQSAAmqkdvDNqM)&|N z^Izbg@di75{02Vx`de%B(XzMq)bavPlT z$i5}S+KPQ%h~?@ z;s8eSBp1wYE;^0vV-{eRGr;9?9lF))9xe;K9DMlGmn0WjU zBb`Ir8>c%>Woi=kptGV;?5aT9-o<9U zdo1(CQgrFouLrA!L^&-bf+g-P(}MzV!9>Z$y+#2C%!lB_#*Zap;fQF)#tg}TL-AX? z_PrHpdndB5C%*$6q8@JTNOsS@cXRZX3uMrLzlD<=E9p$E7Y785kFBOVR5-}M8#!S^ z!{GEdYC5wCM9Tm=L2oh3;+hczfg3%^bvnM}J_0C}HCu@_MKe?Lo|LL7WCnP6hqM`4dI{6-8 zV}O zH?+*`>asr`X~b+RsSRJq zqN|AK3hbSkJ&uGTRyx*=gvbX=u9{M+1T)u@v(tjQI4ZqjKs+hVUn(c_rA9W34H_Hr zhFr{74N}1* zyqMn(K*w{S%mVG)L^NBwg98YeDSv370E{uKUB&~#0xI}ka1qg>K$)Zr3I>zerDrIW z&VT7eXXzrjF%(n*?J^NVLQCHO>Ks#7sz;zAVw*3Xx{3%KoQPb>#^*0aT>uL9vpKZT z`fu8$|7}Zd=X|-C9IxERK!|MDgq+AgBiD02 zmZBcP#f=KNfKsEiHJlIKkR%ruR7+}1gGe?BYI>I%o%?%z0X!t)K;W23SWvU<{ZdHA$X9$I+o_pW?y5SDN|P!pbVVt-+#t$M zuFP;sfCk4g#@VjxTnxK}krYh-tv7_3!%?`_45+dq66c*OpQLrtucYxTRJkgCt+~!h z0;mMnMg`S)tQ$y4`RM?yrUR6a4$zfVr`Lc0fsTUsmL?>XD(J6+J;cq}MkrYRZUm`G%=!CK<%b=+W&z!dVxlrmJeUzs8(vHZ? zmxvYSm(0Q!k`S`@?j%Twd-Pg&rpHEx`Q==XFOgB#s|*514lYL@7+8k5|~ zzX?4P6v5#_MLPxQdSWDc529B|s4GK71<*zut&9X9k*VWXnfYc__l+HiGMI684d+=d zuZW)+Iy1~(00IQUwbTS~K!oBc&Mmeh3Bv+d6z3x)g@?h-L)4Zlk7BDI&sdWiYhwa9 zh~lvtx{3++Jl?-v6{DR$eRoZxF!M;fwu~q#U&_RHScsOqZs5u0y9Z-e&h8>_gzh+t zoyeTBggjCJ;PUQN=W@y&Ei@4Ypq(j1Lvbi!ons6|Wop=(HJp27uCKQHD4FJNQu;3| zPCIuX&~=G_TZLBXL;qbn^EW=v9YXQ0M)m9?fSmK?dSlF;rl|2#cp^6terD#r@%7lG zCC=+V?Szv-T~AuheS`EE0Lq>yZ#{Ky{;4%~3;1Z!DNb&DSN1ENE<+Dc?cI9P^uHwq zwmHe5M~+->T3eu>X;+Rc8!-(L$ADw+8xBKzpGY++Efgq)0E1jB6o7wx_=~5l-{2>c z_de3zYlBSy+&!qF?zG0DSs`EQoJRo95ID)G;FuPzKN@K$VXnZ?lk|#Kkpox``2qb1 zuCF_LZx4b9O3jdoqK)x&jFFBvkggUC=#Do8<~flLw?=m4%K>zY4l^K)CGdsExsOan z)xw_&lQulvynLTs{ElReK(S*!Gg>YP`3n8U=vRbC`)OHGSUl~0H#V8{I&qj?CM(U7 z_!9g5dM8D?%tN{^!!t#%nBI}2!FlzekxYs#R-m$#*oh7+Uyk7G7lZQY?&L^@bSETm z2VKh5*^g4hY19z@33H5_rxNf+1=V;gbsuwK2Ovvw%43sMwebdN{zY~LoQg42gpmFW zDLr~*mHv#0C%$=V_QU5q%#sU81RZMQac-eIg3MTnStF3|DErEhaxgRgw>?eq>PuTd zKbz46yGUeAC&z=W%!OtXnVAi2ds_CHQgVy)R*<}cHd|1I^K$6B*%gjB22M)&3Zc^zW^-mk3j5Y2cMk=vGzPRIGW3K*l^YB- z&o$xmkemy{^%eXHK0xyM6@8Vy)GtE0ZxT<3#huhpvNdWt*dM>ew7 zu>4~{kOw})$)#r*olH6Q7k7xRz`ZwUD~Y(-{9#``H2TAV z;VlP=a`IQt{&_oa^?%c*pyOd*`{^m>5AS$yPr=SzpL~`4-=KusomVe7*bCo(;rd7f z%s58sHYZ=U4}QP676-!`03pl1Q(k!jxJ}xVZDm?3>>DYSO10<$RyU&XAwrD`js7={ zm}G2sD_}L7fd>0*(x_FXMK!e%V7PyM5%2;-xJjRU*+AgBkPHJHA*gJQ0B$E`U{(B1 z%~Ge?r~s%hzg%?wRC_ zq!kw3oR0c2OzA{57pu9ry*x79vp(ZO+Ba(-(1-`jr8WMs6I0XiX;>TR@r&o&}q_ zG;QV61RG~*M9h{npS_0Am6mHom{n3+wTj-da#3maH?<^h1lZ6n$0d=N_SV2?I44H){`5`?CTDHN5jIsfBwo7|bdepSZ_S061Q>q93E z{Ak!&Dg>>77J3>jalFk@EfNQ4wX!PN%Q?uR)f}kaGN~(R*aGw^wuJTp_qr^uZ05s z=VIk^jlwS14GStYazW+@vEQvf0ye%!RlJ+ns{{|oqY3Gi`;IbDw=08DdK`cqn=KB_ zs&lGyio-A$3)%yzw<1zN7C{YB$S%qcU8T@Wr2j+fX(Y6^2;7odBDl_OYuAVhq4u#s zW=jxg3w5O-ENvfzo+>IiYegU`H?qPwuSF6cj?V)@4V1D1sb=0xR*5MDC~_J{^*y+> z(o$-T)R3Fy0vA~FnAtN}O3%{7^hUEIunLVJ-7)FonA|nv`Y!#J*zUhH@JkIrYort? zgCS5|!-8$L(NK(sfN7_$=)vzup~^f?w?^zoCY$ z`v%`F4Y&JwdG|1U)ZJlRCBH(D%k*cHIU9lB2IfKK5Pu{Ec8knhcJo854$P3Yv^dJL zxwa3vHp*J$vTdGg-8z2e^e@yBaAvX_{$F!d+=S$-uMdci`GRGn1Tw##d+*^qK2;Zc zEYHp)?DAAz%ziO<1K;Jx7hAWW!~MLCbtR83y?L1z7pCm;WL~VYshll(yQ;y}+{6#7 zZFL7P=H1n0-OvDFK%c);d3*I;p3IADNZIM}JimOxr5?-EYs9%6y{1}^=eMl&}(i;Zn@0>fFy#zNiXFuyQS?PNO5Ug2enM2PtgUS5#%A4UeCD_875i}*(!uCjYEJlePwfH5PMD(X+ z+8v7v%gYki#X=Uw7T3-iR^ytE&t`T45pB$7dP11zO=Y@lsYF4Ou=p^kwq#p)vs`8U zC`;Cne7ihG`J4*&R(M{9WBggsS?Lb4JB6uq``Mk+)L7funo6C})MeA)tmARIndybK zGmrTh#Bs^^b|!5iGds-^YcD%1Hj(ZyJF}WXx1`cLvx(>+hlSY@*sRGnw8DTr-m#ZA^C&9%guVO>-}A;fLMb zYL7+U?Vf!1e${=ic7JIPOmQy<_^XFk?y--Ja&3=4#aA`b0m3EaFO+UXG!R>yW`!*YP!gqT&*BgrgHU*g% zj4#x%Fl-UZMY{wc4|;&mW5hpYlF;P z$98AscdnI}b-k<X|6cRKeFT+yHiiY=#?h+c1XqjllHdO{1C{lfiA{7`d$6t1bO_ zD;9Dot6_4K1wRrU8CxOH*5KX#3Xf+`QdQ?U~WO?{=UYA3IpF z!{v8m7q2^Zu#!*R>I}{-(O%mhnDne z=9?3Ntp(K;>{E!%Lhbla7`5=|B2E{1cv0f~31S-5E*PO0(_-a=n}vuiZngw^i4994 z+s~(vu_ZH0+54krX^EwGU&eW4GCPd8R2~i+nsELpAMGIrdnhfN^c?^U7%e}8A%`dy zoq!Mp5ad+gi3T?Ppr3M=D;$ZIk$-<8_Kbs=&yH1A+cvjN==eL|p4j6FY z{=(Pf@d5=F)Tv89HDtFrIvwYStj1swLGCUkMr*C=HG;$JnbvV0e1_g^M zDs1zi&((ed20mA*!#3EE!j@-Qp54cw!%ql6S9Fpzjc?q$Eg)ls3)qYzgb4s>Gazat zArc&G77z)ecQD}n^7FM!1~IJZ-(YnkkeaC~O1SAaC`YR+KGW2+<@BWf z&h&IIs8A{3GXe@g6HpjNfdUzy5ZsqR%I2d`Fc=0wl_^qjiemsc3x%`snaq)n0Q|-x zq;AQv2zAX#(PDo9gH zBnFZ#g5Am*jAee|-cU`4+sga`e%3WK3@U*n&@hy+F~-Le`v+dtM zNmlYv86&d~hnIo95is}4ubLLLrS#z`S93bE!YGYz{ODcq+D$ljFTnfh8pUl2lPR=? zZyCo~%HTC0$`FgUpD|)sR0D&7iC>3`=IKB4HxJ#IN(!b##P}PdxSfbWej@Z1K*a|q zrKFY2(0y(5H(!$63zkO#S0{ioQ#osc=<=)X3A5p%Ls*XwSKxdD*;v4<| zVF$Db7rWC67ptMcFkQVC25^U{K(OGQJ%uurNjcaLC~Bxpp1jfC2Np%E#O=IqWPbz%c2Z@?J~I;!+R?Ed^xp>XHTE_DvmWOSBU7_14oLCWby~r z{uY)+t7M6!7+7>04PC3RbOOg|N%7UAnl}2MWE|mbm1Jj*a}#?LHblDxjeE6?(OARj z8WMO7e6zttgePZp;WYTt&6GOV;8r0t&y|~AV7nrf%o=Y=5mOu586$X5iUz2Mb*6pj zD)in;?$F-F2InAfWSAhOhc)n`Hc0OEq!*^%+1s#AkH#5`;sR-s!%=NrSqN1hDuiY9*C|z4 z;46;?DlEPdjDQQ;@EqIX$v(>~meEJtv>ZR8CDR0h`~9QX28RlfgO}HJOSFx}H8^~m z*Sd~n87#*%+0wPf#gFy!2)II_zw>CwFn3P4EmBMV+3<4}HE9@j+Xb-hym!$E z!Reew6hwC86{<&C%iG~n@(`lLh%OGc5^}DC-2F)N^RDp|oEpvS1Wz`BA>eTBgmbgW z6gJaIYI2&@_dak21^N5k^V}IcXK^Q`rqb2(w*pk*^qQLQ@7#LWV04u_X&IT+g zjPrGcF(~UoSm=U>`qc?T3b8;ti&+T`a1h>r2H0h$RwCh+4OH>CST}Y}*7{G_$Jinv z;F>)gKC83Zd~zYInPd1~DwSA`6;SPxtRL1XyQF8cU-neohm)7bM}KZ`N>##`4}bO% ze(@F?vo6NsX^=yF{g1AhxkwsLzTq5xr6IyGX5mjr!ALl_E}qbkm0iO@{u9B(4I~a^ zsD}f|;V83k6c)ofKDPW1v)O0b61u;UDOr@$u1(r8$uX?rA-812M;k&Grd$wglRnxs@ zzse|{kGAH9uF9tA_%#T?yx)MO667E)$I-cLu*dYEuMmQnT zKe1iroQQBoMb)OC#P(lm5KDH8{HsOjD|sYn<%Z@`ORP5DQ?I7xxTe1f-2YTMyN8-} zzvc6ky;v#9O?vJTy`}{g&=P(cKl?l?+@vmEl*4mrj`yoqw$VV@dAIwi`SEAWq z-+wgPcypa8t%Z;y8@J-MY-szzy-a2V)Vg{xVhPXLy|W!^3qP11yiYPL2PIJ;OUrJL z;#;DFk9k2-IF2Sz2&l(#_c}H>OpKgjUe}UZKDN{Zm#kWi&GkV{WNMaJr!IW28N`!h zYKKmd#rcw~s5Y!l1Qki#%e&)g!IN+c9IcBOrXZ~yA6smKdRV0E)~r33;Q>T~J{F22 z3;(s&g5CfK%F)7tKysN~#ITecG6m(_q%wiI|%t{qAvQ%IsAjdQLbe+Fx>?H*~w#?CsZFP!Vj@fFqt-PU`0- z0D-Xv3U4`TuPz$@->~95QPQDxS1rSuAxqVYrW>m6!o=AUObg77ybRlh%d(hKIms1` zmt{pYU8bemHbS5lqhP|SESR_UsuJqcAo*L^00qKYghrr1pU>IbG;qp!QRF2>H9;0d zffprZzFmrf5M)kjoG8UjpBy+P`p1?WI`GZw?)TXR_QSyrGIRAP6 zuC%Zu%G%PB=RZ0?+-asX=24Dig48X(?l1ntdH>IpPwn?xFK!t^htWtvN9ud2Bu#G; zh?UmeXAv#OndLNsRIc-rH@Gvxzt5D+1#lJ~o&g?%-w1vOkGa6D+MB>nrvb{IXgEcy zsLOzOHCSwg-z~HvRsxhB@ zY|fu>BTjhIIH?s1p9-|9O~~;jX2nN&Et&ABH*QVqT!tp1<#YR7Y*{vCH~8L*+4g6| zmGSIbQOuF)6Juq?h~1$g5yPX~y5~OR7Wzg!;jXvb9Dh~Uw@NxL=+4}@-`{`aZL$8u zT=i2&2cktZKcgs-h~^#|Ww`Wh03`Q9CU`7uY!Hm#Z5X%ocJW!4zv$Mye6T(I@!`krIR(Z846 zC_S_D$&|aQ=w#{-brRzJWD_#BUtl2{FQ7bbGi1Zd?f-w&GAWQ-mGM5`dDEGG{G(2n zPycuEb#MLJ;Mc|;J7!?0-@o7%Pd@bI9PIVfL&AE#FXIgP^1Pcjw>?Ee;T~2@hh5ifIkKx7-|FqD#l6>HzcE6xY9V<0%EX*`o z6kKS#%jprus@mf#Z(7$oXHOKQL7K2ILK;d7Lf8_T8o_cQh;mtx7x(5A+{|P29stpx zB>|us1(0!ITL3@gFg=}goEdL?vD_Xk*FfJc%+1Mq;r^1@U+8&o{fPZqoxIGJ9?rUJ zL^VnuCVu+na|Z`N6bb1=7Oo_}*6rz{uX~ztH_iL?+mdDiRv+(QW^)(&!5aQ}(#3{? z0*FvxW+&CvGdC~2l3^Z-~AT0#M$Mj@9V+mZMQ=aywTbr!b?_;@!EKFD?* zQwZ+OYPFf;Ob@_b>Ey{FYT=fCzV>VpFSuJO?^-b4%qu=9})y6W?hEC zUJ#Z5D`5vz!D3&wJ+xufwVFfYfMK7b!-*R6at}GR8uYa`I1h;{14}yKA9bxpb$1^x z%f@wtVFg@Wg_=@=t|yZ;W2$G@T4F^sNvBxhcb`uhrY{%IgJtLm9?sqARy;=JlV_cK znh~jjNB=cu!H9rj$4zgtWCkYwRCjZItj=bCHGeoFUe|&K4{MoolxOy@(rJ#E*KN9^ z`xEVPpokhxGGh5Mnl$+v>z(QkC-IR2Y%wC~Tvvs>ubx|0>dQ?|S#>A1vTG`L96Vh2 zcxd(smi>i0*4RKj<3WY-b=gunm56U;0&Z`tkYNq7ObNp?tFiV}DyO65Fks37Ovk)Q z-94~8&&Hk*x?mX*E;AQ$>ftby;jFcny4|U6)%$23F_KeX85zQIElih^6sT&aj?WWN z7$dq{>L)@Uh2=_V;W5T(pzBqV;$q;%1C%?li}=KQYUUuN!5|?a*f+cQ#w;!mYmZ<4th}9T*$RcS z{n}N0G+Yj@Z-~&|GA7}}YgI_jauzxgGKUmjc#@luJGGc>o}V_kjSU&y(0?5A>}qt= z?d!yQt|wWio#jDu=7mV{RI=wk(RQirUB#3BQ%rDV0&7S9|3;?n8zCMwXWH$q+t}34 zd}!03r4li_if2REv+RTt>Pg1u2Bhdd4|`6AlB@ZA8~|71&#*4i;j^d(%2?78u?1t< zdF_3J_^L$BHC3@thJzxyGmmZMbQMX-c1y*4n zgxhT$=Jk1vps%G=Mx|C!aEAd&e*L$<(DsF2y>k}i1->Wnd=1`S{>7I<;Hpe`T@W~Z ztt;7*n>`C)2Djvo+ZPWvpD)}A6$~y&-A#n8UcHXU-QKg^l{$w?)!$BA{}%xvLQdm8 zT#puTdHGLJr8i;$Hot778ODJkmXbI6OTt&;%yB)v?oXWcDT|Z;tL~o2iLseR+HG^b zNg`72KuauAM#%V(D|i{X>T0c90LeQI%E@=5X)KGS&ttr?LBf#swe@!s#2WB4E+m(yd-X)x)Zlu#|2_1$zAHQJ)yDd(N1`U|=*`XJO;}Qi-)0bgG^>YS`nQV-hkRQr8xVjn%9_{vL}u)NM&RV4786p|_Y zd`3B|9wY5O76QhQC)ieOKZL$LmYqrT_GUs{+lH`bl47jShoy>1Ih!zrA>%PsAi!r* zL}7u&-7E9(m`Hy|1$EV-C{dzCnj(fYr7JtFUsyS5I@w$cgM$MO4|B!)(I6~ti9vKb zuy8_opsn+6u~Y)D!iF5sfF{uWKm(eNuzD0k!y*}ewa$G73?b2;L>Jc`=h^^s#R7R= z6H)n)Pca z%U~F2o%tj%a?EzOTtiB4-}Opib@q|St#FW8FJQo3efpIz%Qm=RRqDd^3$K`kV$6&|Y4Yi_lI8WjH3 zePoGbr2_;Y007ezXl4n$rEIDHr!J%Yss{ogCJJd01hrzL-!c(75^Y*CPg|m>+O{Og z%O;s{Mi~bggY{)2gF!zQr)E-bM;~H$;Q=vwi%C!k+^QXuJ5EFb52TC-RL4UJ0p)<^>SgFwIUbJ3J?h;2%rGgS8^JN z5ph!>n&b$OEY**px!%NUDG}ZkIUZoY#gv(bVZ&(t2ahEhdVWPIp5Vkd;qN&Bb2`9V zvBL2uA|aBJpaoK)5VW9;Y`#%xPB zY{mDz)(OoTPL<-+mf)03VxKplB0zqdU>eUEdVIYq6!cn&BPJACk!#tncv2KpUrCaq=SKWCoPU_@am)%5DO%F2xJulajTdS4XjVs&KXnmfG>MzU6cB~9cD zgcOB?mn1(|s|YS6k>J$mJ@;`PMktLl7R8vj%UOk(#h+bmUQA6h-N17kuU70y?t(#u z%TblGF;`khAD~-}T%}2gq-jo4Wl@xMof%&%#C_X#^nqpAE@w!^u|YOZHU4=PtcmEq zd(*o|Orqips0-?Bqj62vn)C<2 z!GFf38`OhENCJ5xanG`7X6v)xXyUVu0I`ddRBckKWw4-dIiDqitB<815?tnbioI-!SLH;~*RI)#Si3O;7Yb?(s_uiJRs~&_}pqnMI0j3IiZ{;=dx(F|(}U)OyR6 z@N)49yJt)CI7E{fO=v&&%}8K6Ak<|7EQA4)aZ-J024TfH)7+;bcK#ai(IqH)VE!*{ zcE&M7!x`sL+Z5%oWaX1?O>`&U({qY zCNa8ohEEcK?baoI?auFCDWp@i9s>+l5S ztxhG9@+hkcl?RPcoVEogSHdX!d{Vu zVfF`;sw}CLWjUT&0n@_E*s*jc7aR{ym3oq`?-cV(6KPYuBx50xTp?ZG6dtBwXjw?a z`RnAmEDJ*6Lgm)*jSoN6%*!6LW|a`;FgAGRX4;?1>pn{|XL-YRz%O_qyN* z@nDO0B3g@RE>hHziJeXIeXF&#U)KVE!Yzw8hsVA35B{awz7%lnVD<211`#!?!XLu- zSmYyKy#tqV5-pfnW)S3Xov+$Xsh0h6QmUzrv`dJyt8$20h^3WQ@FwtBUik}RNT;kg z!R!`ov^VW|0yg)}!DewC0;s$b*9chkjX9(@am6_D!OmWeVja@`OB3_RobF%_u@C7W zrbz-ncWCxIi?+@!O&{zHfJhLcKhk)(5YPmP-l!M;= zi?n{Ud?9Dh6vmHn!2lHgIl{9>h=y@~0TiVF9d!A}Db1cb&odY}E-nY2pZU@_G^lOUk^e^SW*yuHNMz z^&FU$VQ+5Nk&A=F{Vv#p{rI5w-bwV^#Oy7-+2$I-Z^dt+Af zj$ZlC*AHz0|7@u(f^3)-Fm&~=V7GL**62JU$U6>x!VDtTc+AO<@eH3Lth{6GGfhm43a78UXUM4@aR6)?X=nPm_15Y!IF! z%AHE1_%kA!r(lLrhExy0p{4aA%Yu0`^@{j(uQ0aZ*G*|CNIhtsa&XS-Q-hsSQT zv?M;ssOrS8K6WfW#A!lgFOIDL^khFAT3{8q<4SqmJe%K0_QG>kL{KuvOt=uR`}4wB z3x`BXdhV$g5Ng|nXpy!C}`q@iMvMP8j@Ll{&Wq_U*UDH|1&b_#{4nz;@XYILv=7@~SE z^3ZY?wtFpEsF3lvf5H+v&g&HiWpQMJvfYQT0I69G7CP@hK0Mv*n8-k?rh{c;I>Y+6ApB`zU#A> znb_GDenrR?s_2?@Z|rqd*;*DfEhvB=3U0n4|CUtQ6tom;L*h{CtHO9h57fozz@9Nn zP6ROzw^9*d(j3nqR&|#X!C8yLj1vkz25k%k3MVh#$>dkO$=mTX8c1g;=ZCR9q=gEOhPxeiZqn9(nl0i1_da4&=|})&^`ufwXa%@XNDQ>cm6*-xSTtnK7$~iC{T=(%EkK$Sc6it6eQN5 z0cDuiBp)kC%qIVakY!EUh(Ue(_*dP)xDjriqnp*JYSL_y*^H7jx@Bl#f(axaMEuW|{ZLvN%u(rTW15>O)|*cWY*_ z{-U$CLrS7Ig_>9>jZ@4)qCo^E;RFyx7=S1@#t|-N=5yHFEW`aG9ae3LDM^~1!7-3P z$)A7#E=5IO^c_?c9J$XZa1yk@63(<;ICsO@x(CMk6&3nsJYrh0Sfkf# zTfszd>JSe5RB{nEWk&lX2_f-~WHUx-N#6wf{g;=ArlKp0!Yjxbqm~(`k!ac7J31^) zbHs7}eXYN3(dcvkrHeqLmBQ|hMsx1gk6lwz-F8`K#e&6;DEiy^3r~In^fBL0+49|P za0g^0TH%UO>kzCNOh*puS|!ALn1;ObMx}^)$?x~OY5?2 zHzDN$6dBD!p>m&hZMCu!tnJc@E6<=VT6G8@1Y zoIv_G2@qo<1m!3uMFhH9BK<2tPqnpYd1&`q^npRP-&wL<%s z&qX!Vvx%-dX4q-%qBrKe71XVyApG=7ZUmP6Ruk#Wg7I0R_kg==adk|z$Znk1cu1keRjZl$YXKx1(}${lfdee8g*Znf#Cg`A`n$ zA;*d=>~~lc-+Q^RVvcV=jNSQK)n~79LFS%)fazj??7QZiWS*1%AnmhFpf_;V;63?5 z$?{bEsP!e2ul;zvzk}R!IIvmxLGs(8A0D(_v)7}en{RLb+g(ui4M0L2uoIpK64Y{tR=-0hD;$#9J{ER+wXwd}g1cvPQYn<-83q~} ziWW1Hy=&<0O`a++~&KK2>y~a#JN1V(Er07OQUJTkqDV85rywS!|Gmamo44ck&WPO0w^GDY0a+cIa*oK8=eX*zP_B z?bD-vx#R!i1~C5^S``y_M+_&1Z!Z`AeeB+-Mh1+Mls)#F0_2E-5r3;A+OGzk2&PM` zbzr*llmjvdE;{f=2c4FOkM^50i6bK$*%d^rivSkMyDxg7 zSs&1~Cv&+H*mB!oyw>CxQ%nrohP+r?ZImj{=_jdIm2FiUn+LIA51W%09jS9ukY41B zd_sL_NyUIbuxMR}ygt{W_UwOV)5CSz<`yS;Juifsg&;&!IzAJ9>WDv7*a2`vJQ~7D zK*C|MNK{H(U~*bgjAX)s#DL!{)keI8h@uRvmfPK%ZF0G;xq+(wU$TT;kJ2FB=pzi> z^o{Mdjv;2wPSko9_@&Ms#{~PP&HY9H3kt0n1dpZ<#BNLvt9y@Bx2r`d^@kXVm@unfgDzf6a&8y*}D1*UbdAX`61` zA7gc75J9(sz`J-f=dM*~S4&}@3=7eg(Sq}~fa;;X+Up>2R^YqRIUQwi<1}#!T3267 zNe>+ikUU!C0I4H&C8rddc5%Bjm5Xf6;9Y2JaxhLJ<$-3`8bPfevY{~fA#yEq{797w z+c&|Jby~Z?O>MZyDQ!S)oLq`X1$I0hmxi1}5Ku-yQs(`>Mo}jw{C*{ipEo)!^N{%t zQ3LNm#ycGDlDe)l9M&j{HoamImdX`hksFWX8L(zm#o`y+J%d|rf2QxgVhQI<@^pmK zx}y&!3vkJaBP&*`qa4VE&ncPjvqjna8OG}4JCM%ZG_s4b(6uMl1}%a2@`FjEU=u%F zOCYUk^X7^+yVzKSG0VI*E(hc>JaEtd{u}-k&`HNM(2@w>p5Qej<% z6nnBdWvH zZ5v});6;u=QJipD6wUG+L(>c|NZH#A$DS%{2Nx?yWFn!}{43J|j#qn-ar<#xWRMbg%VsS$FmqQM?Hx+g;nGKntZV zZRC^}(19axBBBooj-(X7+oqLObj;u{O?|iZP-}c6J_p+O-?fm}eJwwmix(2qsK!pH(R2^8^93=0@Y2nUjpm0gxlE z`_*&XXVKmJ?o4i<_5U&^b0Z&qX+1Rl&}U<`d)^p6OLYc-27PD5NbS*yGr?Ixco0xz zMLE+~77@P&v&3e>WuxXWP~Vy^M(~=gX--;F{!Yqfb2-BRL95@w68+HW1I6G*O5pPU zX4w7ubN12;gDBfc9LF%rW4P3;x3I)L5QX~sYOttAAq7%kE~G$;8@fzVf@n8>qitfQ zDm04P_Mn`5AeNf8IHAM42^%ks%4R-HB3FJ0^0o_YV(EvLMIZ(5&J!RZ1-RuT2jXi~&nlbC$rW+8oKi zl?=JN32SfIW@iwz#!Nf4Bt@A^&*>-K6L)?9rb(-maH*+PD_<%=J65C8Uddiy9OXqC z5ec92qQc4=8o&xrR8|bR)C|fSmE9;1ym9gTaklKHA*Z}YSh0%(U!VKA5?c1r;SqpQ zQfOq|iN?h651#)MX{6TCr^-llq=2d-(Ix0sf|E$+lF*)kTYDL%Tt*m4B8ck-KBkiB zAm_dH`|C{53}zoQde2{tVBagtQbS-s#Djs{GI1LDF3Pt-f2=C-|uw!nRQ7X z9;HeJnC6-qP!J5|IiZk&rBqp<5t8bv8t6p58m(cX-;+$n3>ooR)aFAWEkZG@5t1Sl zSe(k#xhXPah*Nl)@TRiGzKavq?#8L(k9sn3`<6mqx-PvEo9J4>A6wzM57NJ9M;K;2 zW!iPz5}~(Fll@;#iB*dTu;p{nyyw_L#vaC{DO=oYa&Y2`;qS+zR(HZ&i#|^#B zIi=lk_Z0exG<$C6r2ApW%1i#}}ly*7FuM1^?}eS55z!%gEBByLZnh*bDmPLqzEUGb*J&)%}q24oXGb zFZA=+1()I(a)>rQRNuaEb1UebvG#p12$rph*P|~>>TTmIpqMJ7Z}zUU<*R&H1$RU- zAA(d7l`MnV@cjl@U9x?~%7nVaI(WhBJ+OxoK@$j0$?drSRG z#v-mdctcjX>|kz0ml~`)(pu0=AR>+0OM?Eg`{Ty}(Co?P}QkMIL4*+?0(CLm#w3+tg5yP}1lDe*ERn{Bc zJoxa&!9+T%BH==7Vk=pjqgtw5$%i!8HorO6%0q0PnS3n;*MJD5lBp zM=h520ZChXg)D=IaGU4w2#Cq&3Nc-%T|&@ts%pPkCG&f&_Q1$}rx`Fkrhe^43qyj@ z_DU5JGYd&~@P>MmcmP`Za@Eit8oAP7j~{!yvryl9w39}i`UbrdgL|V_alqE-Lb0{s zpRSa(nJFPv-SD^tV!3=@w~cO9i?AZRj78|Qu5Il3UFRr0!8+-$H?eN zr+vO0)c>08PA3ER4iC<^YXierXo5@qlmJ2O4?G^hs} zm50ud7ZS2`=={jJwSic<#ehXY<$8;e<3XYM|INx8yI#s_rF~s#j4pif9X?&dY*ZHz zP)WRsNr!(mu7Q?ezG9}%n9Lh=NMM1wrf8f+>=qO&-LSo?@48+PXc`z23`-!uaOx83d1HdK4DO^ZAzUO0 z%>E%EYl0 z;n(@9=6Z1Wbxtcigj$aG;VqpJ}3R{d?XlfNZAK6eRH6U zqp%^&qhjblvM%b0$9QDRktP%Xxy7d{rVCSoXZQOkRaBvgdp!m^qE*8SVEkC%+n?_m znR2reg}}1ks`n>F943kA(2#!0wF`4!zd^0HUY`C5ENx8jF@kI5Asu(V0HA_q7ZPSr z@XNYMP$iltn`FhsoS_M>Z#KqBYO8~Vik<;Z%_}u+i>E(tn3V|cRZX)_%FI%m*t0p7 z1u8SkoOjfLV0OZ>Ov1M&Lurzf7fyi7e1BB0YISN9YwqjO&Em@FoovSaTO1UnqUZ~% zB+@gJCxnklx}OQ*W>tZtO|tuwjRnm8Z|HKl(n=J|k3)WC~0BWZK# z&QnyxEw|=Xs|x_E>}jchFTL>)y5wnhe7^?lD3r&MD177 zf8R~V=(e?h8zAmZjzbZ)WFZd3I?yTcuqIQ%G@r{d_j;_@vpkU9 zz)>aX@z58q*uPz(x<-0%JN%urN@jMF$wC~=icR?LfA5a@rGM7vYtiza_XwTXP+u=@ zx{JTZ(@?!=YiGf~RyuE1XWnsMO$uq2HbunC01+IoDZ#eJb}lH=%;`}eO; zgp)N67@jk4K1pG`p6F^VmCBY$bj7-;uPJ4eXv*BRYUdm^#{(D_n?M?i9awZ zY=`^p2B~h_UHRYj z&D3!@V{uJ7IhnO^7-)nSpb;AV%*}4SOZReWTDF97kut_|lJBQq4onX5bXp+nLU3#qII;;hsaGv6O)_0q6@#syj7oMLL)>3YN0so7J>Lyth_M$YW8lMm zryBZ>SV4VASoF!MpY>h29I#(iNxL=wX6<4p3dm}l28-ZvH9?lS|&OOL~GS% z>c0OKkl2_3(d>pO6UB$`cW^SV*ITdXL~6pD8DTvV)01&tna&%>lo?kd^oiOixy<9T z3%rTGjtw?%NoaM~(`828^Bd7@++%6F{p|6yS5n|o%+4+6=;O;+a0#J^_4c33X`i+2 z@a)DAG3K8At@)8R(a=Nke$<2)<-v5$MTPwe87puJYvBr)lj-Qn-}jC$z=MeObaM<< zuC(;a(wa#BiM=@lt6)rPq_QJ@_DPb+RdsJl3k$l zl9vmCG+GG4#C9$r+ zfE@W9ZS6D29UG-pTPvf5tDu}&tq26yRfs#H8{NHjh1Pbr&i032%EKW8xOUy^)QVDn z9s)-YxbRUQc=2xw=TRQy43cqpqF+)=zEbIaW@@n^*m&SAUZ8M;1T78(5ff31`?yUn z>&ZpOX_PhnD+JmK{I{h)Qd82!z_tvydUVq9w{TcQ`rDr^9wvMX{JR^wppsaUzgMGL z+1ed*BN9mWNV?-nruPw-rioH9vz|Bsf1mS5dxuHNZv}#;HVRk1RE}?ZJlRCM@-tn4 zLZHi)IY$cBR%rk+z@RmpD;KxW7%x}T3TcYoMO!)E4ker+L4p3zu4cbDhRcSqkCYvtt%w^3~Wbk>MU)Uf7}K3ro}P><3>l{(O0~)fWgxGK*yC z_$}qLP%yO7Sm78$0|cZvM06Y|nPgjgLLAu+{qq?3%!j?Q^V=)E6n+R1qIfjyR3+K2 z{m!re!wEZ=FUsNju9ejnkhclkJ!+XQ@6N+^!)>ky$Y^1Q`WV7W;I%|H(cAM?hX1;98 zGvzH6WC?%}HW#wx4X4Q{mMrL%W1|F*%k_)8F_<<@%P>s0=$B(j37)%pb=CkQTm*l^ zb@&}F_{YAQ4muURjS0is>D+cMT_Q+nHXl#q(PAc%P46ahB%ZnKXzNJx@a%TCe@YGM zQdCnWZi1Fi=n6?6l3gL8CVN8xUt|~Ec6sv=Ay|mb<}QIli1@>N$O}w;iIoVGi7|Ze zZ;1g(D~`62K&mzeHX=I0bWV#%wOO2_Ixg9_E4Wa0RAL_37QJYP$CKZbR?}GPgBL7$ zWNAjT-eG@7UIXNhx0Nb#H-099^Y*^PV-LS8=n4#p2mJjPPHGuRySVrMl->8rKJc+b zh>~(b7fKl7{=~Kh&QJBdk^R3f&8n?%J$qsDI6T(?y~(WQuR7_s@D~~LXckf~wszxx zUocE8lZ|R2iSB&G-w;X>fYxNwEng%J;1!11pcP{xf1-9JPV{Cv(Yf*#sW`rpyTznl zJG1e-YMOmvm#(U*i^0x(COAIyW8GZ&<+YBo%ZiQ5n*gkm^fH7D|xg4wCa_sgC&u| z(zq(|nV^2|+);PlEB4otnlpqkVG+0sVc=(p7b>&bdTK)V>qEU~@|lwK@><FIQymsc*xQ#$YMF0Zp@zy8!-(;uSOy(*&DZ$|rdS|t$%f-jN-zGz@LBj9GFFn5d$ z9p-zI-P|uwX_56REYetCH6LeT!VFrz4edP`*rnm2zcKB4b4XSW*ph zZ0}J6n_RndkX=Pb>+H=t+SE5yk5!4TR1G~;DPt6++j`f)o=rF7Yc*R{Ki{%lY)h9Q zVN8Fb{3nU*6^Yr-ZjcjJjyqr%R7v2`w-vOy+WfX3Uirm;ay+)BsVMigW#Ni|w)?^{ zN|N!#+bWsOWi)>I;lK8{tTN35#O?)E=k~YV%)%&*?vJ6ZLX&vh9Mp7zn1rqw(L59=Ys$@N%nhdDSY_`$J<;;=26u_4T^G*S-G}LTvCLJeM7wlZ@25g&Rsur zPg!eBS3Wesm?W|xRp5j*Xr6`x z(QbSAtDMu0@1+?=I%6Qu4hJ{NnRsF861tZtV7m#FtmG*a2d0qBS|FRP)c2I_oXawj zr}P$Hy7noxcDjp}RI6EeUnwEbEw<_>6V$40Q+eTT6~pSeFO!}#mIxM{NzGaeHL zx4$BP=6k1c9E2F@)(|YCt7VRu^+>kaW$hOGXhd2CSs1vcwRIzVUq`foSsNeu^Zsnf zq~6t|ud=Fbr}$PZaE9(Rz*+&Cs0re5vr`VNh*-i|X2|gsUrUAaO>1vL-w)4KTmkpL z5!#RL-=1lowdE@Y>IXMR4`DN{!ctLLw)0&M8%%{K8EoDq;+A^Ci5z#5mBCQ=T(ENM z^5fJkx?D^#rO|Wl0}&ke#Sny~GVdRfWbDEm#Vi&rtW+|SnocECkRr~kesQj!s!?X& zAY^380A&bWA-r$Vj@Xt!DwwwF8H?wkj>YXDx7Z60Ud#vKat)-Q8r3+4YAlzeSq4ib zBqRWc@gNqGvIpPzW*r)R;JttN1@c_ON&h<_AsH~-T!f^#>9KqJy-HGRP|L(x z-Hbim<Dm!&%O@;7T8oe8M!31!ZgOhp;TvI{T(v8ko8>&N(xL&- z8$r(Z%EDRp+YMr`0b4nud<*00ttD5Rrk9N+`QBLeH?zOx(J*|&rqNqZvxpQAmte!{ zM)pStWG0cVl41%m& z+67*XIKiPEsXaocKPhj5In3V6ZER!5@^$>Py2qy)exf(`X8ty|)@IKa&E8gwJx!FB zhCNAwlv&8#-cde!&WMOn(Mgoc_O=NQ8c9eahk{CNM z6A;2Osn2C;;f@~I=-3R+MKT1JI$o+{v8M@HJtU0VK21GMpI1kflm?chllhX{RW2q) zF3rn`g>gSCNzPEw6EpzY$aN8SwMY}CnIPMY1c6Pdm8yR!7<1d`0+y-gH{&}vNxyzY zGTW}lsf6n5hzsY0Kud7}nm$c4LHG)X9IwZ=0Ns)0^Wy(zwp>8iwf1_IulwZRe3NzT zvE}vmAK=0&aH9)dB+XOK!ugcJ#Y>bdR#NF4QmK?Uo=jq%EuqEacBZ4q@&wQa+Z(7K zu;rrUJFU%mn8JXC21Sstl466|wG}iV6h#jo*&mR8%ZK3Ja`S z%$($XZ3> z?3tsJX_q|3K(JA4ueWDN-Wc3SUR!FLjDU^8EO&Uw4{`eH`7bhFnAR54c#4R`7Zo;c z`ijA@G)3`IyP`&MdxYlIq+(k#O+tpcFRs)s6rq>uRyc*onjB2lM#rQ?$WODVHTL~R zi>VF3)ml_z8@#YwPV6r)J${wJ4QI&7Vj4eNWKjlsP+I^drN*xLbmy$x1sQ zzdxkyo6rMnA*`<^!p1iR8Q^6%iHOS+>d}ldpkO!j_Z+FSCNg%JOa`0Ht?ukwiT^N7 z|5Ez71amnOPEj~|7_`PGj^LVv`?PrLWs;=ue3FNcl)SPam&|uxMPPb1%RJO%ANuM~!* zyS38k6i?Nl+~~GknuMQusJ5_#*>=8XHuvUkDj} zXqX{JnzPNX2rISLh4u5}zvGW$dfw!AAAatKe9$G^N|fX4$j&oHwX}Q;y=?Cu+4*=po8{84whk9jDi~5gWtq&*MM<=Am3KP8abmMFz z-rPc{@l~UxwMv=aq}sNw^WJ*%WuE7}MG)vdsaFUoNLe|E)|;32sEr3^Ph5_hr|SKx zLG4sGWQoy$hNhQqo|I=ISh1{k*I@3M_fet*gR_Gvc85l&Q6~Tnujrq5qQk!aF471^ z%{rZ?1s128p>~JgdrX&3fP6fn`sn2hG=v`9*0)-t!Ul9&`(-VOl@r5`yTfu)l};#T zeNSs@n|3MQl;5M6_faE@ogH6KL0?{8p-upXUJTpz!q>tzm0C!P^_hYNLu zIzgEB?7>WXA+t;OC6ks(rq**UJ8GpnFF_{H$XzG7LQJ4;k)+aQZ)*8MAs0jW%@Sl1 zjjV3w3TP#Dk9<;Tvr>~=hr_a48|h1It7+J&D>k8RsqWL7N-Ni@!>v~T%`yH!g4$Lq z@t+;Lg|e!UNoVsd$mY(swYo)o(n4mntn2yl{gNg@ZLbbKiOq5gGQ^@9%bKnZ)OCS)dHc8pf-md$3Wi@rEHh-p`a+xrF7+g3 zi(}SC>Cy^huS>sfKr>&5&+#(~@!B1^(~D^Ng~7??3(7^y9h8dzPNGP;m`&yB%JRUp z!>9_|0_H~(f(3$Q&r!5d(2{f97b$o6cJsWJ4f?v+ZGOlm!LP|}IaSEsFC$NQ`rI9% zu%&%8#63YGrq8C5r)`|v+f?HFPS!Cn8}Ay|zG2YC*S{BXS!YS%Hs+8mWfzm*MkLz+(V1y7NTPkr)x8+3-t&a_z3t;E%ADnBx+_rVih4Bt zM7pBqYP4Sfr>_5@Hs@BCPO*?zXIk-~TvS@7oAGj`OH}L>7f%Z#2HQds#hC+;L`3js z-Mx=w0i%5p@%Q=?vBX!VuBynA&7^9E#L*C$+ART%9=Ty~jI2$&zJ4i_4U z(ZB*_FkMCE6r98$*Rl){_8E}UG8RsR7spL`CAYt(8-e`26KHXJR^hH4yTa5;{>?lv zfoEamVaA+x`dJ(RxtIe5Q3t|?mE4T^+4Q`hiu<*f{JS&tuMbAc6M7^FH2F;L@3#QP zE~wztkwhV|Ek$Rl9_)sCcohg}D+`e2Wem$^soE13)_$t=KKZT!qY>*S+w|b!t3o1? zto0>GstC>mCnD%`N+@SEe|J|>RN%ik;72=X7xTo=jf&cnQizN&7 zvH%OaPQIWrkSp3!zpkG&lq{Pd|2BNmeY;9Q2KH!${iMCue}&!clB)1~fG9D7LrP{R zj%p3^;^8GP%G@kmVYk>GC-?ZuM&?$TuW#%%^ zR|1J)g+!vnoqm*O=~%Y2;w($IUJ;*Q1B-6keRvpfrd`+Mp%wG|oE&t%T&3ykJ&-S{ zc`=!uf?pthW8!YG;fA{0(Jw#Kg%)|`xnl2^=5sfSx!ZI$i50hB1EXp^Km5&300zd=bH^`Va=U;L9Ax|FZ+*gb~;mOQ#`c4smrS-^T4$a zeOGC!Zo^LtODCH&1RlK~vTeowbI$s%n_kfZcH^FF58uPC%c=?xo`$nNnMjODz4{Fp zw8~P!RJAPjG6Lw5sw%4fiZ^ZBE0zko=`rC!=KNMjyY;fhDQ~o>B@Z7mv9hWJCf2|{ zl*56{NtGi|Vj6BXP5Ifa`4?o8gu9NC=*(y9^tiSL?ccC)o ze6uEq#P}eq_9H9ND|S0Nm1yUqEHJfq_?F@0<}VXm{MQ9{w&B6h*ty{b2w|>MT!NJ8 z_gPk;5>~EUJTl1bI7GrME#VmfR^k^-luD`HOc}@GGMnk{VlEj^C%5(5r>G~|6R|Qd zaI`4Y1+zeNq20KF%Dx_qp)p#|yMza-#;c za}IeOx#Rlv{rVM1=p@@RwH?L7_~CP#UK?Eq{I;*%qQjNdmfd19&LhQq`#SX{r+?O{ z*JC~PQdu>(s*K-<<;D6T#soiaf>X=*d2%L@B*WV_8$&Zb6mDU&pk_hcsH~2Hv$Eog zhci*0msVBNF_WSoaj9(1N~PUg(MiS;_akKqx@`ZmO~%-|?5DOUXm6Uk)oyCChGnn} zHo`Kf&c_wFt1|IzgAvT}|7F#8ozb;6c*~&`Hqef`%Y3w{@4ij zG!|~LW*4e2NUE4lH_^np;j$i)tdVA4fiDTeXS(8|-BL@pcn!Pbc0ZaZEL2&PtEmZPFps&? zm1Oem+UU|v~C@dV9!UiJzEw?0UJtWa&3#4(VrEt{YSnJuD^Hn&93WVN)j5ZC@uU9cLzh3 zmdSjSxArdRHCuDj>!%`atan{_wm4gM4=SyIyGKn9uncqUE>pKGAu?hWg)`yK%0#?L zyS?jqAFSa93ttCUIHp)nqnMzyOLW3;iaZ>N5Zv}`&Cw`Su2SYgLH;C#>2r7Tf;lC4 z!FOh!8zaiDa#V!SS@kZ88kCR(8lV95ZgNX8EdwEKo>^n4bD{wctr{n86V*S~33()v z+pXJkn8sr5#_hoPJ(TBHl?SOUZX}T(Me3Pvmzt8_aIW5KMEBRpUMbab;UWVz4~k#l zw=xMYEu1?J1>C%QeO)^^6`BJlYfZ&8ZCD?M^IYRJ>q>ogH@Hl2q@Gx~q1n$N7U>wT zvDPejeWKyu63a->A_#Atj1vUYrve zUuHxaIQn=Fro))eCqQ!5OQAWJZ$+6~yz5}z7f^30zWm2{FX0n9ZNHbz%!wf{aGLl;Au2Q!v517on z1nl-%L-pNNxkS3eyx~oOamq0gWi01_QkPpK11^lp3R2Ml%Z@`dY7@CQJZL zcf<`1SYh6HeXzj8fC@=(Gd%G=@WEEt{Sol*V-^69cV@weaF7;g;$<+o7ceEdLG|4} z9hiHdsGnnw_zmHvvg@i9AkGH;AWKYD(y|zUSFFNk(opRO$Mj>CRCekj4n>TJ+tzp3 zd`L&uy3xBtOxd?6Yd4+AZ2Q33-YwIRCvdYo@Z$Sc8w|WkKZ-ABW<1joFf2OFyHWRP zcGSFDVt9t7wvAmTpT}cQJsTEy^>@)pPdstm?5Jni#@v~-P#ZCL{EU_b*??&NW7pbZEEpV};dsWIwJnxyjk0V}Dv6TiGzYFU zwk*Ba4qE@_Xk3ngL(pTTRT>womzZzWF(a1dS_7N4{fSK^I*?3a?8XS@%(i)m(OQYNBx)o z_`xO`!j~c4u8qs7F8^6o&&y12r+~JqbG=t54rzGqr3^7{6i>S)36)lFHOG{LL${~w zClbozy$VI<+HV_?>)jG@(h|PXwC(De(?(ii3xS2A@Id8;358+pmVz4A# zCP_+BO5&6;5KcWYw&gaKPO3ef7mDRl0fS-p#9i0UEisMO50$3c_t)g&B@$sX8vo75 zEOVEMt4cB4qm7wuj-%riCWcgv74QvXL_~mtiO1|sBgNG%Fx%Y9$lo>!^REs6W%mYl zu&xFV7l&MFALSV%8yM?NtyXou{nYRTm}225-t^>C-8=rqzUBO!uun7y5vw53b!Dy+ z))RZ@$|Q!tQwViW=8Qw69k_eeqZIXP_bn4xPbIp=GQoOlsE|65J3}vTTQeIo!b*2V z-_&FVOF=|tKu`isq-n}wiD8Io=+O)_*OBlR6-BHbE5Z)PLP^nf0HlFk6c}E0O9->W z8?kKw^nh*k4XLS6z|zVoU_4rx+EjC8C!kNgpw@N-GZZgN{>uA=%Wk806Wgh1va1j} zBY}}L1?&L>Y3cn+Dr?2}qa}C9G9E?8HedNv>2$=A$>fqbqo1XxFAFOcaCJ3$Qy!5F z5K(q$&Q9Iff=b%YLO5Etx{>{Hbnz})95!w~e#e{-u&1>fRv`MlTHq7GL`s+`?<^2z zvWaH&@3vXfO6}siZN4!zrPBul<)(;(3VKoX92d;KlKwUo^Hu{_lJSmZOI&!d%`Air zgOm%60V^g%v~=u(0AZ`q71!)f!q}FpvB{?5Ixk(5(HAxg-$?*7HNz*-p?es@RI13# zrY5pxbq3BTGWPi#mT^B1PhS|XABv!GUo>)ZYm#(4tb4P&)x)< z3S808I!#spFDa+hH%=f5=qCL1Jd8>WYvjQKALB63v22$QW6>dJRC69Bggx?L0grJU zs2MjMjYS2~B$y==p|G;(v@ewUlvzazMJt`b0UDNylV>(a07gtdib69u5E@}1L8NUA zDJn}zTIF^+y;0FEguNq9g!$mEaP9XipZT+{+_qyJeAhSvf)*1zuPjZ87f+STVq30Y zHTXmLT|)mwBK|BXOZil?ty1LOQoCNRY-~){ty~0UkE(Ar*>HPnR$I;U84d=6It8EL zeqcrv8Dl-9IR@s(Ns9>-T`G;hi!`E-*(JX^5oVF_3Y1|Qh$J&ymB09mqF=b(>JpiV z3r>>)XOmgcMO&=Xp%SV*^<13tH&!r)r6PKHA)VNYri;)@KX!#+K!uw5B4`apAwAxK zLuD6Z8}FK1y~Z=ye8g`sR%`d3#JJOrGEJK1k1ecARK_T`EHS@at@a!AdV^w8`#2II zp-)lq6F@Q*P>k}6|I~mNw+p`ocUu)-e{SVFZBm6sqRhr5p{_`+FWftpg}py#WEJg{ zV*Et)G2*!S$rd^$RXG{A0`Axw+{ zV$LfedFFK@%c#{&aEsD&!RrJ-V3bG!{{lTmu< zp~%u`h8OZYuNu^wrH?2>Opi(8N(X#UDQ=co*c4`21J#G=^>W7ti6s{IOa`dN8M@5 zml>Bh!iP75aL_&d%J_iVzj%KdER)INmfjH0jye4s8DQ3^Ts1qQ%N&b)Kp7ev2?%T8 zmVpjIvs`!d-zdicY8iVJx3Ml73NOD61g5urnlcN^w>LlUB7N*}7ZVOwCvG!Qrz$q? zN(**+ZCNiG3F{o}4}~;F+f|+sDUxZ}j(vm?9$d`a!}Nd`JAo7o(SYDL2plwFii_Tq zW(f~ww|K&TQk^YpbT@rMl-re(CEzMqoagcg1c5EHmdnfst=KHuv=!x{GOhQfLpX@; za!?2R;Vr0xT3f%?9CqIMa`t|FVXovQ9dzhX9*CXhbVZTGosI+}iu?BZ!wg$|h8eQ4 z{gqzBX7RNkn*EFrI~nrT7-g=6`dhvV8hGB`ye0xzM_Rlwbmh{CJHahprFkJJfr`)PM^(aHDGL-hSdbH9Cxx>nkV_@*1cYkSychO|LgJvz z26CXnd;b@ZSj^Sym+wI3cV(et<&|ORD~RPr#X8OQ=U>fTa5aL=^p z^`47naytQJILf;Xz?(^4es)g zD73s&L&30SxMraXt!Jhcq+0wiPx>>N#i-U_Po zVJnbI1o$mU5=apT)uGDhO~IgWArqh&54^T}zxF5%RD;8KIm~iZ>fp+uE?)RxDLmWu zJIF8YSbbyeTebW(tct)w82sIltTK3aGjLM}WlhO|^t@gS95^>hPk|z-Z|waLutO=$ z03!Py(%%TSU`~0=6M~IservF5Q|-+>Eq*m<on%f9^w*4MPoZdb$7Ey3FH^6b1 zMw`3v?j*Lrhfv=s@If089wo&<{j`on8x8g?pcMnx7NpRGYLqCwrvV?lJh=C-Z^q6kT6ZK^rg!vLk$X>jQ!U+}#$b6(n(`j&w_t4Uh_c%Zv}ODId+ zb5A@L6GtBS%B)9$IhPBUoFAMKZg@n!IrhIarSLc$P< zLE-!iD*WQfqhW<38t$_RxyIXdBWsX81s8vL4CiSU_*jNkeAFDHo4G~ky@He033vR< z#jD$D11DBS84+Yd;OBB(6p@@k;r5JGC>S&+^5{k3WkH0vM`>ck-59VVxWf|2hZ5KT zW{?vhT51FiPF&=cmcFjU+TedDx{F+I&LdJFvetm-qexe4+&Tq5R*@{NK{Sl?o7qBW z8d+;l^U*lcZ!`;|xnUm5QUfy}3K_!biXg|1Ypv!KKca_yn|BLIPU;1a~{#KFg8APn7D&&O!GRa50ZI?;3sHN_v5x(Fe z(h+2VDHQfY6`Y5_2%Xhxv`kOzec4XL2n(yW$Nk)beAiF>Q%o$uQy#W-oLU6a_kR0f zVbJ0K9e)yALgo~%c6D(%4<9jg4?RV8gnZ+0{&2;X)z3Kl+r7@Q4UtqMRT8HnC8?8S$IQURY2wH!|HKHx`(FJu? zr?R?!n(}*u=?RPfQC8V7`h|q8a>ZdsmUD=iJ(5-XEVvou!onz2MNnTmH~KfHFv#d4 zC;E(M6(1F$0!5m@aa^9~_&HymVnW6O0pi+Vf@1`TZ67Wjp7ey9ee=k&!-x(@fz!;Y zDSzCvrng(_j6c(|urRYSqee11^o{%|I-7eIjJyiTuXIC)7@r0Rw|Z2te}WJc>pxqe zh1?8ZLl4YBjo9WEcO;og>NR7ybsJH#w9SNH9ZnVYP=5jH`o2OKTDzxr867g>Etw(X zbF~&jRaC>Xh0!-G%eH3QoijSw-d;MLOl+q+cN3}f0-ywVE5#^ICg<17-IJCL%r|)$ zG0UyWlAIJ%!g(GP^0i=F9XY(TBOm0+y<9Gn$VmA@K2^+m8488vOkZk@xL%&;B!Rg! z!*XSkG|ELl(IipeDBOJ%ZaZGuz42G<(-V+lrqs4AnI=02S+!-C?pfc~KdBDByY;|6b~NET|}}lIQ`@y>~@s0R#|Oj7?p|Z>`OCSW#5tC)|K) zG?{I??z&-WTf33H^C!SmB&@f}8 z@42|JK5`h^E`j;4K|i*C_+|t0V<@hJ&Vz#))3E;5OYW)vzof_gtv7Za#Cfz_A(AVQ z2y&fo*-lYN%q!FPzIlwjM?M-kHJMNfhB%*)ork&U@|w4IbC z*Zg+7F?5Bm0#jGtwgUs)uQgY!K`9a51dGts5BAdkW20xHlMENlS7{Ei)`b6yKs3H_ zjEZY41n-W-$7@W7BHM?nhcZqZYqd)ax*ijKuvAzOVd)Em4FL#INf2`OXL3ete3qsVnx!bF z8mNXy60*#aGE9M?me4ImU8k}M`32L&liQX-&-66tnU>Eb!TqPW-y5>oyzTMi7|t?8 z1!d4A=qIGzVDH8~^o%52rk5-Xup)e&t)U$X6MK5Km&oc8nE-Biy&XGd4(*or&cS| z({*hOmw3(d70Xj{s&(5fMq#IDO-g1PO9RO#5n?5kgRK?FBQ2R11vVXC&)`0ZCMeWt zT5bs?qyokA0t2K9ucOHVY94Vj;r{K#=zuet$;QX5fpOV?246@HT=tiFu;q6HD zck8V#$lrIW6t~UF0K5y)>|YvcH+AJatLTvIZ+X)z?e$I7&8&%7fdg2I6{jm1juA3^#FH<;C$TXnZ|AMT z`_Vw>gy~_83{4GVJNHZ{R|3B{#y6NLFW21*IqNy8qL!*Ij)&iG7J+$Ny9#&lAQ)K4 z1}Sx*N~-z}iwb5ubZcbge`h~_nwb^uZ0`2?51$!BpZQD5K#c`5PUCIPFy+hrQdmi9EB5fn#7KFTToj;CpgM-I<4w2Et+ zhmnc_5pba_qB0t6JiirhROz&9>6xP+o5@Ueb$U5>HOPpT-x=F5-p!y^H>}9QwWcr}QcF-Hbq|#Sg-#di}$_{KP&0^rFAs zsBiqMKJ8zg>zL!vJ3FAkwYF1W>>cpx8CjNe3BdMPkqiY;2!&7sMNqgZ(xAi6Y{i15 zdrI-m{F=>Nn~u$(IoOU?9G`NTHR~x1)L1lYr|dW`jRK7}H2N(iSSJ%SCnp9ME}Ct4 z@iSn8^WCxd@Vv_zs?ajvm0#>LQ<|HaRU@<+IP|K3Rx4g^m*I~m`gepG=Q>sne50Xw ztGfBwrx!*Yyej|D5ZIAhdo>kf? znbv{IG8pp~7@n$wbH=+8c-eH+anKt5XXOR$S(O!{!86OaU_0 zvHO`PzS-A3s+;Nr&d=ya08@)y!Q(p<9UAH_gO*g4cI7EF~6#!xE}WCOg)>= z?o5Lvr=}#utHHl*Sx08&_Sw?!9KO&6@{kk)hT110l7$UH{dE#1PEF6+hCFI>1m{E| zjAFHhshz4_VG5V=(&^<)iZGE4cszf>xwzrMW5XD6v>;kEbmH6*XmJ=a#7I-C@4TCG zFwDs}wLnDeDolj)@c4M>Yy^TlcUlmTdU-562ZDL2D!nxQH>VSkbP8q!W5I8F3@kZTu3RyVj+rrBB@vqRFQhJu?U$(7Udy}kzH_| zC4L!Fr?h6tgDE7PL7^byU~~R~C&z|i3pEbieO309-Q_JNTt|W5o}UjWerK^O6K3ZVSq*8RsPpZzpi~_UW*Y}4l>BcO#U7P;7OX#~_ z3;xJ-x-T2A(CU$Om)Cdq*L;s3wJ6(Ir)3NIR;5zi6V%J|e62#k84J=C-e06&X_iW@ zJ{0s4R;%0|P|tm*Xtk0%p>>pPe?66P)|%DZU6H;sf!#zXL{-eQ&(v4`)N8dH8l*x^ zQ>>`l^qjUzd2+58mhi4OYdhwBwb^4*7HWvcPvzfV5r=*LT_9z$#B#aROax0je)7s? z&z&#!RPRB!?x zDNOF5dRfNH@-r;(Wl>dT3=8*l1Hl9*tc}dDRyLcn9c+?UUCY6$@aj>k-j}o~^6FYe z@^^*D5yavIYjwGzKF3K)AP?o+Towv7kudTDLwhEhWi)=OaNHj!fF#o4z37Lx+`xAl>9WPoL8(O5|ZRR_VVNXkXI<6Uts(+v2!b%!P;kOk@3?slwC>u(^7tJ6NTTuV zAu+QC#wT?tLVe^B-+tPi!JFK1Yu21{#uYa<*QfD*$Adu$1jf24KJ|z-6+X`3Ptotz z)Pf~ywSOPHwb2g5yGptu|O$+qwh2=81f_lhzt#<#4hW^u42oa5UZr)a&i%pH`JW{&%|Cbo=l`t zxnl7;T5hR^VJF0R1La1gU)HGT@-e?2PNMp1mc@_7s_$@42-X}})fCo8&WUPOJ(OrG5ws5>PbkS!x`G$@v;_WR{jsl`BYO3b}~q@#xmY|M}T7%{<t@dCpalIuQh{nt0?%hzxPi(jVWWf%i%QjV{2w%NE;@b4K23_jhxdD{8Y_dO!54DEe5BH`q+6BbfS$t&d)otC zI1U|dCBM5V&|C}FvDjvFsB@T#@yL8&N;7QF>eBotH@K{bu-yZELpE(^+*}OCC3UpDyXJwEB;|bs!f(9M5CNAhGtPFYxUXW zM6MDq3b0ix)2_OuOtM+Y7?N_8V%Ea*8Aw!?N6JOiIEd6dvCe71YiXscQ&JWNM{*b- z6Vfb31~Kx0nz7Dizbu`{<1OXpH|e8$)po0=<6$cioQ1(zS0b3RJy*iq2@}Z5l3!mE z+uz8~q?p0riX;-T(k>ZiU72A{eYK=jJ8=-@OG5`<1dB$ux>%6~i}A&=S8n?Qhz(Dj zsXtF7Jz~zi+S*bNH}{s%4V74fZOc?fLfU0`%Vjqs-Q_z&g2iEDD0%@uC?bZ|q=gPa-MMXzXcUrSK(%nXRe=ASN;LjLGy3n-%4=puM0Q<+EU(IWV zCe2j_VkQH8=L1Uo;9inJwMvMotch0g^VcGQmfoC>Rd3~Qys`)BY$U0ZLoO_!g&)qQ zN%VwpRb)_~WR8CB2+SFM03enf$8Slq?yA_@k%eq{YX}GN3S{M%cLf8+FHeBPD<^pj zWc|@F56x-W#DwXj$n%Q)o(2s_7TvZ{!d5{fEuCkuve%OaI{- zN3H5R_Lb%`mX|B4|6?NQL=^AnL`j{!3Xs9ZPJsk}LVafk3BG{R&KMgQFxM#%AaP+6 z)W8a;hZGar?bR<=h^MyEulW`kJa`?Ha+Y7Q8 zNx4O7W*7tq#$eedggCRkXF!4HDH5;b6i(lYJir(G4rP}$;@grvHydE5XSyequXK9* z`1+bIiN4s6Cz*>JcC81*vxz7B#I(kZQoX;w96rBQt0d9mHDMFou`g4_bRHcaA1!JI zQPHEFYqqMP5pGFzVLKTX6;G0}bt`lndy$YN+w%sQaH@=C_g;ezRy?zDNI}~0O!9@$ zJ7*SxM93Al56D0P>zA5u0(0%`)-DB@)=YCu-E3y#47joY7G&>MxZYi&z|dS3m5WoXd5TforsqMQ$aglx&=0`pAdh8UFdiLrDZR0io0SPxNK93L6X-rmjaKoj)!%S` z?1FZy12Aiteqe%Ij)K`kCB_(wdCYpZkaFm^SR*kRfMV(3wn91h*3x8h{wL@lk-++T z7|h*^9cUp3iXagZT;4pcYNRKlN;uCiM~g%Au_DN3JqumY841pqqlJn5dlHF!jQ(=G zsh)=sW=>uszfo77O(NB|oNd!v9R^_%))gunmA|N`skJ%{kzRb|7~W55{G#RJ8M<5o zOC1@};6W*>jva@h($NyNeQU_pz!pFu)Kw8ky)Hs=gKuDxQvZM{f%NNNXh2|%B@chCwtmQ!TghOLJ8i~7wV>)da#7q?PceqaXo7<2Sg9K)RYgzJ{bZPU1^glXAD zHe6hIv%j#s?99mf z2bghUJoK^tR}M!QkR!=o-{Umf=2g4smczHShW*k0L&arI!$>0f%H28bn3UVwe@%?5 z^}4Onip>r@wq(M5{qsleCk=YTZfTDA(%gMH(BWW*0^@KbuTL31s@~Ep%sRWQ+z?2* zXpi$!i3u-z16jMdgRQ%~%8~?~ExW1FLS}{WDuAPUE{hP;prSLT@ftSALHUAv#Mg( zD&5(X1cS$I+H7a2n*jm3C7fV}nrp@yNtz->c(!F4e;=6Xvs?^4;tc!Bw${`td(jA$ zBl^F}2C06DsA(+3m13F?P1{4Z-U& z%=Ol3X!zjozlH__HXtvS;Axk_=;Lf%lR@)RB(R5VnOw1$V{MGU+kc`X@tyCH;~Yl2 zwD(MViiU*Gkvz^s4&}S{$VdOKZ&HQfvdUVpRjl3wRJdKGrb6L;%H^75j}V>Sf$GoiR8@k*$I71-*X z2O^iY$-X3;MS6ZBYy~$9aR(f<0f1YBtlIUpExt6C3j=c+vU=RVX8VB%e~0;VNf=Gw zoZj;LmIJtyXGZ1jOgtd*VgAI=CEkk5^N_J~3e^XnnE{NW)gQO)0bsHgggpMo59Hy_ zTW*(?7s^m010923MnR`sQ_+b{QAY_yShU|vsbm-)u%`y>PTv=W6+c{`#(MTQsiRaG zV8I^yW7nxR9Kj5uA2sqofClSqxH09FoH&kXBg&hXG3J$^e9zmEfJzN`o0zJTQdPjv z_LYpR#cz&6p3nlONR zMAt#wR44snH+*L?6=oLC!6(Y>vQe-NWhh1sa!_zr)D|}#l2QkaM9>F?h!owJ9{oq?&cf&9ZIWPvM4UPJbBE1leuIX>|Cu5n9EDV7X- zu*cFA|BVyWFzA&Qnlc0v3C_anb^stwT+kfXwH9=6OHm89QbEg8RuJ6H5OzE;-y+w{Q_ zR8#8f_%{r0Py%q=)jQtUi^_Mbaf^4q_(cFj$s$@_W0p4|k;-+xB0IAfY@lTuHB5CB zT?;D~6%6}ByPP=$kr2LH?A^u0U$Xg1HnS(Nbb0sABY$I}<;Fz6ye1SfJUMsx>bh91 zEqvi}3B?ZMj=14@lVDaj`GtW=&!aDJn9!e>Ptm?tI|Z}VsMS1wnz->61W|A*YNEbV zt1VLyQopINKWzm4oGk`zuzX#(&cbALX~k-7Uzs_rquMhHQtE|jH&1&uu)lzYEQ~ zU;h2wA6RGE%)a(-hnOI~cfK!UWSrC*1rlwoV*@xrr&X$CH7Pl0)nUeenN?z3#&yvX zV4u)U*YX@?l6hqg4sMVJXYnFKqL{D{`2x09w5%er!-{vY4ZhIfgTody?|BJ4k`DH# zXWg_`i>#zXU!xkuo@`~tLOd(t7Kd2>t6W;W-c|C3ZRy!5jr`i2PN$D1eBw5MHd}|rD{Ve|aH8v@ zbJ}f}HfR5E)5Z|$MLqzTY#7C$xN;Ca`&WVA+>3BISkjd}YLAUonop5kdiQdjf!34_ z`O(wl44#ILa#Xi4W%k6gB*Y7RsxT7n+?UShO9SZnn{Y7KUg$;MUeXfgBiIQ!tLo8~ z=me9EeCM|AU{P%~A9qhe(-wP$j>)DWPv@D)bb@-TfcwG8ihTHfBBHRnC1m}sn$JSA&1+pW!Zmn*2V+8wsA%V{#`bsR;Jn&B20pg+x01+2Tsc$>%0MP zDC!S{gTZ23rclge%Y_0{DyCDrJDGUAJroK!kw6|JkA26!XXqcZd*KTr3{Gejzw+dsnoneVGvFDyF4@bZlFy}kE0dWM47dg@z^T#9{b__cWn@@qaPU^HP! zRt~1oE%7J%@{i6jqCed$iHg63WL4Say1G`S7`l!|B~P4NkA6@=&4}FI{hDL74rk$Q zB>21aWr|{>f65&qVXsT$NaUC8>40F|$){N2tRK?q+*XA``nx{=Ca{{?eM^b6kd*0!9 z{xa3-Ty;a~BWFik&L2KB>;3;&N(`QIVt^$m)b{RX;ltI_t@i$g7K1XLjFR`-ujB6Q z*5*0sNN4adKyv*<;7Ugbb*?bk&MXzOAPp8n8f1pW zhl|e#ol0*`)RS7tr+J!1<98y-0w%R2yq~T1paJf^r{=!a^eZ}(tF?uWIZWUC{FX>< zXt@^^zH}MED>JAi_B^k{8k=cI8@feCKh?kznM`ZV!VA5FqF6f5!3Yn{!Odd#w4&UU zFXw7kkqmjVe~n=K)ME(!q5mcp_d1+gq+h1+Xk0EISOKvwPUl&0vZ!6Gb}n>8Mt_)TkDfNk2E(2HjM>vS6i?KHo%Ke z1FJmkIGVZts)sU)Af=1eNKY=k$>8!QdcfFfRZMM_(4wg(om*mp<-f-3@?62VZk~?t zMraCQegEESCe%R8Bx{F;YaX3*CLtuFL8rw&RW3pHygxs((QUs_k!HYS##Tw&pKAAn zlcQ%eka=H&7nJbg?3o3~U3|LBsv7RJNR_cMU4M<&(TlOw9Ul^yHnF=~Zk)9{PA;>c-pvgkNHCLNlPjK ziz<4sM+CI7$IsY#gr)E$c(j?S8`sOF;fPtptZu@(>TVBuo{3xU`K#p~sql5wgYw%% zBdj*-jf1V1^7{MI*PersY8SRjIcmqCYldg7#Mu3#-3(N<_U;9Mi4~atlEIz9r}d3K z+iOVIL-Fm7D}7IGT_Um@cG>;oPrmyE-CgQ6-#e}LOZx6?B{I+66Wjaud3RxM>9Q9o z**{@Y;t@i9`=Q)4894p~DdA+EmtO2v#pr#q{X=(0MJ26npXRuF>T?UYfz;HGjrM3X zG6XtGHyYPFJz+5tBhl?Uj>iXR39KkULc3lyT5WJqOIJH3yKgn0nx|`3ghZ&K;9S|S zaHOYN)yNK!iS@$rHiCgvhjv?5nXoA{GHoRg0g?M@qIse= zeIDML9w>gZHIw0R7U}cPBeTqZw^B(Ya&EmG2~vHn@u2agcB-gowGV;$V>+-R z8vh^Cli;<9kfl!+05rL;Ry~M^#OVb?0(I^sZKgpQ*mFD^b@voFYlFu7C4i+l8j>(}f!Bnu zzMwV@Kd)z%f;Pw0cLYY;f}ich?)GV#O*?(dN|3p4#CM+)4H*c663j|I8QUP;uh5~T zy}@$G+&AKEDjG60C2X)5WOD_S!#3dhw8x`u{uZYr z5N_v|GswXOm_TDwZ6=t|szvf7!t4?UrJ9HeZoI41u8i$klysmTAM%FRnb7n&cS2D^ zY&HKzM7V8G$&Cbu5F<pZk_E^Ridl z;d7ya!~EvJ&46JRxG&IYmvk*4K8!d3=9t*cj0N;HYn2f0v{TZ=!!O-czZR2(TY!UV z^0E0vTNJe%v&YYm0ZLvstul^T!Q9zVZ7DZxhvi3)dxU~_3B(19G$t`qDud_GmpS<~ z7XTwz~U^&Qr0?V*9;YFRgOrwBrfGr>>`QmmMCJ!WOy{{6Hd zg96Bd3OEPZse0&^?J_WqVL@RfLVV->*flQ93`}n34(EZe1et^9{;#>!*mvHNK_=6i zOa@_3XAM99CRt@)_KPe@HBqNijGpO#H86ITG4te>Wl?cbgWPC4deANvyDcB>o_at!hv-O%v^wYVzd8$uj+l z_Si&RR?1-9MNV53>D+z2wfngf%1l&5e)#klR-7bn+e2S|VW_3GmC9X>fDS=YEFxa3 zR{9(o>trI49E0TSnC`hV!w|($PdVOGU@acqboS8CGj}U1@xfo!0mH7Q1`A^qF%vki z2VC91T{$<)^vrXc1H(y049_xr0kez3#j6PQG{&*<5u;c%m?aGfbGe$3G%8a%bAqO;_WfMeNV2tz z1&h}f@lT<*QajR!H;qZI&&t#%aoKqY8Xc#Z=gkzR+QuVnjb|T<)+mpds0v&V0cECY z!b&hQE31&_NK({vU6xpy<<}BXf^f|Z2?aFGz^#F415il>AV2^>Q`$HMA>sQH?HPXW z<$9UaG2|UdoM5$k)coLyWhw*1O%aX93!K**jB4;$oT&1mZo54;BAJaT?cCW*!zngl z)Lrj9F_G%!%#cfsy766!jfR-&j`X1H&OQ#;7%IP`xQ+!|D5Ck7qS-T7!mMaLHwC{a z9^;DI_<6nFtxYb5m$@={OsMB>nR=}1)44^p$}4_uB7Op>piiMa-gnPJRx|n4vn=-i zsIFRrH|<`6{ndWVZBis?n4YJJf}p6DV_BA_LYR4Ud8nW#Eocb=*}_0O2RSEvu(!Ryx%Z(_P=crEtCFmMP)qz_FCo{OOMzu5+lgJBz7GiupIIR7zeUXqjC%q6mr z`f|(~3P)P_xM$`v^fZ+oJ@CaE!b+AKZfny;PHL*^aMsJ!N)V;TCnz_6e`QZ|#Jar*8>YeR#_S|Q3~P)QEU>ze7C)=Ntn_sK>n?f>HL zt10*P`Q5ddd|zaF;SmQ?sw{9c<>U+pV!^8DqXM5Um+vjm_5gY+NkY}Elx9EggoeAd zbD~Ny@Tg9O7llh(Rf{|u9Hd45nMpV4Q1U%D!X~BV+Ijxw6g;rAAiMbbYB*i00;bmR z$Yc`Zt}JSI>skn%0^c$#rftXI%5fHh4lT-Y3X^t=8B!Jc4i<4y(CcuUVe8K{wyzwC zUgL+UzZF?tX`~%d5$7q%yg8Mdx}Li%Pv6dsS&!0&r1DOyUUSkP&RHmX!6Cow@f=Oh&tDt7gxXay%J?;nm~D0gZU^ z^5gER-JBnUb~+?fx2FfS={t$E(}jCx3l5G^VO=DWNy^E+f<41p?u(Y8|H2JDNzu)P znFMST^omu@-sCv~g1oPu({Npgg-M)E-+Cz7_h6HjYq8XE2^+D8j+q0>g>Y27v=rWVM1u^+>jBRX&M1 z-?GMt$VU;?QHI~v+_LOUS(H2MY&!_M{M0|KjzM3rYvzw``Fo0`nyW5Li_fle+l`lw zE&z>9CRSs~purK3#Jg}zj9$eCXrAzoL|F|h;T~vTs`sl!(4f}hXTve>YDBuA;Fpu4 zHtpJCnMD+I3*uVrsR3(B%&1N7g#NTTlDQ}puYIOlPFdgR&(6)njx=oXsf$|qdb4sv zaCa~MeZ4+0QY_FRe7C1IoRTR}OR`r?8v@$aCm(PCsE&8xzAB>O#x(?g z_(Yl_b|TAA_wxsS>!JNsnW1=xQnEfBGuWWf5vf^qS67pY+U(6D`e{z*$tNvL(b2yj6jRDxB%Yh z#=)QNSr5BYVjHfP%8snM$-3p?vP^nm6%&?=?ZHPxj-p7=oK%*Eilo?`w5mLi?l0Ja z&auA+a1qhKF2zF!@S_@pbgk1?+E{xbta~cQ{xc$%p>Bd*m;EUi+z~8UMER z&ED2-R6ST!H7(KHDcyHkEc+Gcva|Pfg)BaDIRjF`cH^(VUG&C9T!_rCS5H7)sIAVL zu9d>$i~V1E8-7eK-+z3lw)(nFc9c_NrF}X2kC%N4C!ih^d27US`O2+&M>{ud#PcsvA+P`--GGtp; zEeo@#nog@qxNB9_2pe2r0n7?8?Q_hWuC5Ckf~uE57(QAU+P!h@e1B>MKc*>J&$7qSk-AhF<5+A9&GLXRjsKCSRAjQJkl|D$mC0_ke$-j*lY`A6=}IP^ywbc8Hs5db%l)8kSzL)XOQ9M>v~+>R z%K2~GQv*~1R|;tYc3q!75w3r^$6K_HCc&1HlZ9GG{&5?k|HVfJl{7uQ&Qn+84QT_O z%~+baKZd;|m2b7Hz{8dIAln3DzB%o}7Nq3T!AZYE6fJA`S=&)2@=tdP%l?t67~s@W%wWz#4kUzhK`eNUW? zZoixc4|!v&j#GAlLtrsepAxH<^lRKD0Uau<7;<2!q16!QrKK&=!Ex5#Pk6+#TFU{L z;9zc=wOQTTz=7fMmUAb^gkw!M6WYBb2#j$_iSmXbQ=HWg%$md6k?mHGE)Y1Ilz1dX zK!FsE%OLC=q2ka8@w8@n7*(#xC7Py*^vbvfj@mTKf38$UNTsnv$y*W9dzbcCn&i|m zIy)(fhEO8nHwUBza+97N9zj*{jae|2N}l1ey)ta#o2L2rrX-1C_WGW7VP5)Nv!}lY z9Lb39{5bo+vpe|eLp?lj;o(2-X7kAy$DYG;*OjWRA~w|E3bzafqX3nHRItN#x3>De zZ(i3XmT3MH7Ny84M=)bsk8ff^hR4u&<}^iJBAxnTKX)_ozsNhj%N6GI@qwM9!;Agc z^Kslx)i79rgxXe8#x1=8*17CYqbj zvW9(BM&x{LQ+{+{^`2sLk)6x&M^M)%qsmDp7KGJ<(n2k(s?ykGmV#7l)=A}Gbc52{GSnq1engn@u+}lOJ^SQK?*+2Al63nj()Pv(@ zr_V+n=ajTP)yjpkU9GJ-e&Aku3x7S&ft{umS8?+>oNJ2>vlWpKgnu-kv0#8u$XQ05 z#RW?BfBAb7lkxekh(bQ{dHHVS3Q?y_Q&o-SMP3v{N$w6MNHa90bFv2=5|~MUcbFRB z<~Q(*q%5N@+Gm&C7vFt7Wra4#2Qhk5f2v^l6f(hTbn9TwFHByn3p!HMtMzkJhZdNj6=zC^+uzdnh6YQf)JWW z$1*g@Te_yKx&&3|*fJhq)loas1(jwR0Bz|fYM4xHwHp@p8}5SIwLI2QeNEeXlmNc~#^*(~u<6R7JR1JXWuAuZ4^RO^?~dlem8E)ZASBCi>BMMcmB^ zH?LiT6QWT<({_~NM#mfj+lwOhj|#)+aq(Evj@Ac$78icXTT+BDwGO?~Ai zJZz`R!q%!S2`gMKgfNm-_Oq-AWvHskLzfz@HQw>pO$bRD@72ae0M;o&4=o0OB_p^h z@_^lVdwNH*_a2JfPK-htS}Q5BbIJR36XR=5uvw~5i$+K=4D_V#Z+`4Qt{ktT&<8iN z)l^!?NBmju`_G-msQEqyIGP!3yNW-H!O;LhJMfNoK?vvhaE#||nzjB7Ge<^Zv)R{} zP%tQ_8}ZF^oFUStx#-nyF{-X>!mn(3WqYRF*=#x;?7qb`XJJr(BM}k(k*z$|iJVw; zjailk6(~uv*Hx^uX1I#y|XJx;S2@*MXu+QU18c%DWi!d=hn#U^EqbysUYZHikd zV9~ORxW_NExUT8oq#!l@9WdbmGG#SYS_snz03G%fUriu@S^~5RP7azNP!R%JzhaU}; z57$x8v;DDnudz%rL4p+4;`ZM+f}MBmEYGMax0nMM$Oa>^p|HukF^%xTIFh8RnSJN` z_WvA3prG4N!coa&i!l)b*T7=gqlDSZY z6qW`7U~nLo)zct2DA710G&zkgSHLYDieJvX)Q&35n1kHRRZF3e%jyA2J=GBUi^QU5 zX__0`k>@*^97;~vQ2vte8CDTR>yiI+S5|vQN z5e7Km_KApWi?{&%SN87RT1 ztCagm)>&WBTEPEvE#|_;_P9L4dpn@_{8e6^zuZ!$cs>e9Pkv0cp=#MfqNh^I6%wNe z{qC>Z;jO$TK4akwX}dDR=H;lR^B)G#iUtF*UZEIaH#bd&CR^Bqf+#GA5P>4Xo{LDF zkdh$@+3rb+lOf9VjJd-W^Z&loeY#qb$Bzbb7d z@+XsvAh3qECGdealokCHJ2TX*ZtoryfAZv8|MFn@>&~1Zg?9!z`6^IoznMaZn?uiy z)u3X@w#To&Ns9~Y$dM&-BbP0D&V68gOC?N1uBQTlxuLJ6a~R3nk7NxF^rAf^aa=B z8c|58fntb~kFGaE7=3xcCtpY;al?eLK@^{=M|2}~>P1hV`Gb>&VPleux$(cNfXaL% zE{0$yK;@rV)EP)Sg3Lc_9}bOL?)nG`&>UP~gyYF3OOqy^#U4)loap+qR+y=GS-j{2 z{jD@RM@$GEN0#fE>u_GWW>l-7TLejMRHuYeT@|1JsXO_cl52|aW;IE~%fryDrh#G^ zb#Fi-%ommeiIAv=*5b%w3B&V}O_8#V&nk)idN?D^kjCy9Ah1-z{({+$!|$CU>(cLUX{!I;eT zv)_Pa%#41|DV(g{2^5@$Vyp<>qMO=a2uN&Qj7L%_?epP{#5ad?`e-Qc|AQt?5M~&?UjGRDq!qVcgi> z&EwXLl^mN5r21O}hNnS8J;{yi>9D7_jdPuv21&=d!ShiCWd1*;iCkBe>xv+Hm zyl{DDJiDlXttySBszqP++n>G(h}<;XMea7cJBXL8+4S>KVfYFr#V%nrs?q7^j@oEc zkaY#dYzprUtX}%~fa)=vszKRMB*oI9VM0CdG!B#trQoNJ0s)E*ofXAYk8PnHgSOMKf%eH54OFNM%Rr!y z>rB^4Ga3Z}%ouuzM@h_qW2@Zj@A3u8I1(E15h^m}@1ubYJN!g;y!4&|7q-KPa1OSk?IB26 zUajv@ltDgXxGMxm7_;+Qb$SsUm4r%n1sMEf4|K+zATKm`*++7Qs5@rk?&KTI!E+eJR%w6yF&xI?M|Wea{W27JYp~C3x?%*^pjODDNyigq~o#5|=dc$%8YZ<~|x+ zFh}+07$saU7{U<2b*=PK)U<3$x+z1cq*xGI3rkm2u$Y=vDW;jpmSx*Fut1MQkD5dK zz%)f5#=z+zF>|PHDW(yvVFi&f%pqB&dqyI>v4HE#haXBL$*_!#J|e>reuZ1$5#kpr zm59mEpNWMpO0o%W)E|BxlrJ=eV+%IGTF8UE)$&5Pq_rqlIRVyl;A^Fkhap<`{F=hD>^S*aJHyV6QIRH}vkx18&+YNn^I_`n;tDB>cDD z7!LUZE{|QS4ZeEyKmWTFC~!craIs+|VvMu}Mzzrqd)6KxJ7CWM(tzvT5M+h)f!4F7 zUvs!s4=b?=`>_f&k`x=QIi>?`BI$rb19?%ZrZHP&J; zs{jm)I@V=m_@{VsB_$2he~-V*r$&)}(Wa*O81H&1@dF%w?K~!LOiDQfCm3G2 zf318H1G31_Q_2wsp<@<`5l&r&Ggl}^#ol@Yz*iy->;gyi7xkOk;NC&V+;z`EXz?n? z@uFZDnj(_qg$$4uoovHtLrF}WSeoRRSgX+ivoNY<%A_`yaUcSSd4eRAtZA*eVv32I zGl55Sv5_m3tB6z%`>jVqhS>{ZVz`^YeErnguo(Uz*X)QjEwY?`8OhdtaE*ETf8#+n zW5gi)FWtuwj+5BdpUeUnHyt65Tek*}w{~0|Ti9^6G<`fJ!DF}>gAKj!#CFs57q2!N zpB{@*9490FwM{GF zVD9YSEC$(m#jtlMy}8x%?sx;sTYZR<^ywP^a`=4b6d*Qwf14w#Ut2C>I?<&Hwht#F=DVYrZ19egAU@)8dQ1@lf6Vt3?O zXtp7|b{heW3c7}G7v{k2vfM6~5hUJ~z|suE2?B*v6M-fP*MoZElKK*=cEf zC-qXLgE;PD`2Q{K?FfDlA<{Q<7f)6pv2v-dZh;20Uyf5nzD4A2YEmWjQEW6 zX;0Fb5Kf6$op2-pGZoMP2n-p~k~v~ey4v5hP&Z?E)&XTbVMeSjzEm4H-|^}1J7Y<_ zXIkDWK6>NRZ}On=BC<-e^J+$zAjzcp_BYP>dCZ4PEea;el<=Bc!y$V!$EC=AXY}Vr zQT%n+{iCM^_?W5eQA`T^sD&>Iadr`>H(vAQKA$id%69E;M(U3$@nb!ClBb5_FU}e^ zrGjDoP2QAd^JG$VG+j{Hc^A9gF<+zqvCx=zOr9ot_ zX?pa&%k3@;h?wIPXIW-0>ORkLVy?29&|n(tVdw3j)||SnuZKlKhHq1*k+HGMHow2u zZnlTzghl)PTq8%<$ZgPHW6nw_=?S{O?mFXe}qE9BYdO-kn!FgHuM7YYh<98G|YcFIX>&%yS)6$4ti!!deOLkXflUcL4K71x;ys#FI54fD}UnVI*O~2_s9a z3^@?U%qm7H-e`bGpDvlpJ!vOw=sZnm(peB#PlR=LbQ?9!c`bQY+Lhj0t*f@02xUze zY;;+9B6VTHGG$rYvtNsvP|zy3pDWpsy6w7Fp+o%zhaq%zRa%YNvTFPA_w={p?da`@ z6@GE{e{Ry$Bo(^8GhWB2j|%5WoN7<90#BLc=s=1bs@XhAnKGNLNZ*f?fB;F!GRFBG z#MUJoBnb$B_`eU|7k~Fk;|Y4>BC@(d6FC~W;r3WOHAWS)xpXSaVOv1YbNPMj$T~nl z1Uw>vUwF4TCBI#o>}(_=q_f*fF9@;I9_#Wfb=wNddIs=&;#aGqu!P|Dl;!G2YHy<7 z1iDpg@)uB!$hGh+a;8);(rMAJ-77f-L?H9sJz=MG_1j5U7g(Q>)uDf3&@|+E z3@f7*kX|Hk3cwYtj3kkJ(j=si2XSbjKUQKc!F`PrB`I2D=I51^YpYC6)qLMG@h8yJ z(v+83{eruEVwSkw+5;FavJ&Z$^GbFWiL^ZdF1)UVnl;dUN+yKB1}LMVMaX zEL&V0oi*PZZ>rT)-3G&O9B3HTYNN;z)00YaI3QNGoo?i)AtgNNJ0iybb=}Bpi(yg+ z5r$EgXiV3Qp~owB+xFY??QW&)eut+2#_97QS_6yG6f*D~f($Dt>^QEdGEXIKGE`T! zY?gscN=#Sm5Vn2J!DX>|WWAkZTHPA~f2D=ZX0bN%;j>_+%u8=;z)lhSpn+!- z?*oLuHtu>8>PZg+j0rDqZaq47@RCV43r@8`a|WYnq6*N1m5y(3M@=rxIZ<&?cSEkL zYoFHoWl1p{2vytdBJyV?(rWDi*ong?+yW~iLbfp!lJ}2@VWQ3OXL@cAoJWI2JZmh-- zAcG-fFd>b@o+{>xNdO{#?G}7z^F9Bnq<*?#)EalRLH9A1zTT!e6eC{3Zf;a}~Bj$p=;D5dbEUaWOtU|Cfc{pc`UbENd+x4w}^n0IY#!(cffwIdS zr+J6VmH3JCqU!xq$wL>aHaZnM<>_m^s575Qllmzu3%a1TSi$TS+@IHVP#UxWDRH3a zv}a78Ss81SuA)b%TIeTU&!*GF{MN^E{u!_T#agg~@NMIuW|+{{yW{VpWy^|TIhHQ) z*^@qifC>;1P>3+I9w7_^zaPzVNMKsuA2Pf^6j)y5nYcB#?9{Q2xH#zCB7mu!7?I(3 zKxdDT&g3wtkg2mH4x;Gxl1tBl2YUe4!frSU>tKEO3OCR6WOd^NbR%fIBeuPMj3cUx z6H3R-DcEiDMUC!71s)gD$1@W>+@2Xl2`v6SBOa8j$$1{mO*f4k{fivdKe2es&SoLp z-VLJ0Dk6dU@rf8Uq@U!voVMVxEK%=tKHaT7F~%^_+X{L~_a4 z=;48H*clTYyId>e12Y2I2?Z+@n$`%tsvBBCpS-0k$Q(&#GNh^oBPKp?-3`MTImPT9 z-kDVgGGn409aL0RiY9C<8Wmc-$H!1r4`>TSx23w_jJfp=%O3X+)QeKWMly45FHJv& zAYW#U?OBe~)6`N^)Q(V=2qoAlM=O=7`$s$D2te`Zcc5YMo6{H*6W0+3#Hl4{Apg>t z#kQ_pXgi!*!|#lv=p3b?sS@-Km{m#P%!cD$L|JK-2>% zNStk+qCOh()K=~^QvAyvn^HedO3l{XYIB(cR(J1Exgw6WveC%u!QtiRVC^Ok3ENtH zAd}jezSR@Qsc+;%T|NqWuRD^L(ib>Zig;LjdECDamHkJMoL7xBAF5~nzOdq7w6}PD z!GO>0XiXL*(N4e+5J_9I*X?iHll!*89qlTkV#RMJekSBmiNnfdvs_mJ!+v?7nKkO% z4K$ze`B9TSlX{JTuWw5z>H3kHHA==!m>J6)jYO4Fxi>EL)y{<<)K${Yzha3T(QPp3E>u1o_fG_FuBunyG;?%ZGj zi>&lF0JhHQed84LL0D@|+<5O@>F6*Nb*h60Q<2kH>7ScSGW_l zfnU_c6q{--f$4Cj}0R0HVzc)W`0&`T)Ud+>D$W z{>b7i^4S=0ovC)t*Bg6>L9%#2UTLoDX#{SS87pDLkyYD_t@Uzn&|a0$z@C>E2!cl` z@9_Do?VeXF#95ePP>;zv>CHZB-8x|nh> zvg6`@=iT3#i@+Z@9F1{MCL&UBL4FxR&9^Wx@IS$~J5KE$47_t!fOD5;5ZePAvQlU= z1w?K8yvR{pW2ALbMUi4yoyCGc%4tSLkQ{k7C4r4NCMMe}4l@ChB*X1M`c!x>Bz6ce ztn_|WR|OG>gs2E2Byu3=S!0-V_KP|IfA$bmx0f$W&@#T-;ovCQ#d6+@OY39d*scd}6&6t!)-Y6=3h;Mlg1 zV-0JbsW!IOv)pQI$B;dsjGnL?TQy2}2Dxo=xkp**f?$4N$Tpv-Qie-r|35GCOG>@9 z+pnK5KL6SWdo zOyeJD7+(JG%Pz#?Crl{SPBzXMlPcS54BSEMd~=ju$V3lp<4{sMt&1uNLfXzqDl2J* zpLRr!Iv6qCaonO0SCk5(R=nnBvDA?qAvr1ez>$h3OI@#+h7+*(+-W61d)_A1y#4w4 zL<4DpK0+F#pfndmTXaPAN74(!)okWkrdWpcHEe-FZT@%HjC;gup30o+QaF~(R|SaSH_z2%WMj34|H zVHy^KLP(=8U#W*hoGy**VrgKFVg-D>Iras;N2Wv*+(?xsW%3lY7>f-|RJJymVLWfO z9^?p%a%ZNo=IWx-K+U*nG0!EOahPzJUYwTC*sj)R%)qEtZOirq*I~I}Seqx@BMjab z#59TuoeEfJI$4UiUFX)y#UH{GR?)nJ;A+{X@`Dy+!sF>{Y6CE z&^FPeI3|J+^cWT?a=XI@mt(rtFgxq^>>~$RQJ0(g^mIq!H10qU7!dg+C9$Ze75CjNa z(T~k0u`SKOInM);kR1Dyi?7YGJQV%5)lQu0BA9hV6a-0;1V+(E+j6;VHkV4JUF%@e zF24==4(46}z+xZrLjqT}R*s12Cjnn2!{Z)s;u!tN(CMV{Ee+MZjbAk+?HB=q0n=m@m&Ml}sM*t9AP-}|hAJ{C5Z^uh+NC@?!2hOs?>e?0L_dIN^Pe}8cQ z`EZt!R~tAseZTdnBqc*==Hp~)Ie;7IuuFH)@z2?K#Af zi4d&$3<%MK@riOA<}?rsd2#nexLdq^8HdJ+!t5|lVqQ8||3*25G(nkXX(J_W$} z!$@y+%s}zc%ip+of7uUzM*p|9ku&1es%8YZf|G4qZ0=^K>eM=hf0k(7cvSfh-`<2_ zG*I_)w~cp#h}iyO5@^4NhG9ar=|@1hTmMG`bWr6R0lb{$^{-9TZKi+fJgn}3w@rHf z(*x^k_1K@+x5^Pig{mpZl4;pydO?P{h-vPjD+sQ#6rwoXbE~|-+4rk^0(J@85#9j1 zP~9-3Y%*mlXaNO{;kiQdNj6(sYY=`x0_Tb7Jg4C78SV5U)fdpVA>6#>4iHf;wWx5&lA00~w$v$G8> zxTE-v=FumxT<|=3sXETRI6{JTTb6K)EMurTgSOLX?YYBu(0yd9ZJ76o-t*ggSm2tY ziP&7OzA>bJ1zRvuFjh6I_vKT$;f257M(kFNzl)Vq+z}=rIW?fvNa<8*ZQ0Oh&}>9M z=rcprCo4pM9ltQ&+{uDj@r)CWZ9IR>&QRA1MkUqe6e7AVWHi29ph&$vsB#`*d3tT# z;C(JQB9-S!y2(jFBWZIRWb-&;X;8L+4`4vttS(9qHxCTh!45GMx~3qMVydZa>_oOd zaKV)79i+*T9^fXRB z>$xweN?ie#!fI%MWw6AH+UnWIr9F-8uS=Tmb?K!~tUuQ1QlTQtie_2Wen=cMu%v_j z5!EW|92z3)joERWX@-=Gq%KQtfU^f2EFnoVVO3OZVY%*K+ca&9Q?Xk`;S0AGnTtG@ zr-!4;u6TC8wz0zNL^_DxAbZ8tnUe zGNuPJBIhe?@99^GD5*W?9 zfC8B@>|y|z2_KB;Cnv=0b`{RcCms(SZ98^4pVOMIb%T4?pK-};f#M9O0$k~cSh$GG zXS6CiSDzd+8b5OiYaQy1EgL^;8Zyh(h-JHhy!7!pyy^W2b7LuSp8Y#0ZwM}mb-(L49(6T> zXZnZWjatv)?9^pux%FksZ*;1v$UI*-PT@*x2p}2201yWlA_zInb1XyFtdy+V8QV@9 zNquN3qn!R})Tb{-3UK3(K#5A|S-Aq=Kfvf##p_aRnM)N@Oj}s!Eu5p z3si;S@e0Mmi{LKP2oGg|u7xa<(gM(Ld1ZM{S@%3|qV3Y)lD@V$y0AyITe4oXVt&I= zu3H*h8J6I#LuGM1yF}3HeO59|>5p{bkgz^J`|<1P#S6lY3a9N@o;F5B!9bN+Xgthr z!g6xZTC-RC!Kc$~xC@D-{~y~$qa~^sM|S&;ebt$`q3D1LW+~ij386!8%4HYYFH%M9 zIZQ{o?D%?*IlsSde8?QgD!f{&J+oSeS@Rbgx7NwLW~Z2&0w6FALh!(VB$jH;;0CZQ zOJ}uf$J&Rn^(tM>(BrEBT~k7B6i!_s3uSGdQ~;!1TV#YG`D!sf*C&|clBuG=Kqznw z&1$A5avU$ns(qHibsrd`XNzQr0A|k1$gR&D4AHX=0KOcwk2E)!O&90aOZ9npXQIm# z(d7Y=1q#yB`-@9M@|okpGr`+#hzJcg;oFd-ezRl#p}}!C4Kz5ZbM<=6$}#bP#Z0Sn z?5+Q~S+Tp%T5G%oC;xGx$H$YIJ)n$<^$d0h=3LT|tmABIZGIEaR`>K-F#QTEckO(c zzP8o*4`;LPu@RC>|>h5YUkO|Kj!F_LENhVO4rKed81OtrQ? z2T9`4V?`pMa!d_OR5DLrS7HQ&7|FKRB}}KpajhMb{1CpqTIc>k%Y{_XLnhfX1TCzE z*ajRAPk~xNhY>MK=M2FMCpz=xu``4Rz=v2%1*}owEchTU$A7jG_V%GyCKyNw)`lzl zy+2Ryocv*T*S9R+Xei2o9wVVLJ_V5#p)g<8$#HpG*2y}qilKMBpem4cQ4CW8nM zO>!^^`$SDA4n(uTKMmd(xEAJC_QX2*-*h!Z7XFraq=MghN)BPYKgD<-z8;_U8<&~k_<7DUWR zTgPw%do9X=@~sbuIkbgjj`tU5l+RE2F4Th00yBraKDWg-*3O#rK6tVdLGuOkFZ^Z@l#w6Te~ABeL{fPbK(=yf5%z zwy{YaQ1yrd2qC@u{dG!mCSb-F8M_3fCuu}eh~zF+Rdma+MOKkyw>HorW=JR2$}a(i zG$6)geLcXXrG%M0)02}xD-aP~MT%tj=Sbi{`TQw#7_hc&0~G2}abQ7?$(L-e#+@8a zklvz_GP$Ax>5e6vQ3q0o&Ff;<_XEM{KtRb2oiw0gHoSpue2)UTubNkm>IZwtx=8Z-EA8wU->mmqpAx^ZB180myN_^UB?){$K&E+Q zoEJY)Ufv?3DLg6joO6PRl4B?bRd>Ql*VHsqR}-d^GP$A*oz}2oWgW@V>g3Ms)qbF} zA7GTA(2A1dsDwCP5JO7hXqsc7K%-J7XA{17xjvv;!_O({th#5`gN4iY z8R?J1H)<@`n3`N~Xgzv4Km zfs#EbNzbAB{M$O55g=}ky}MSMsi02)e+ZGDDRMg3b#8&tLR}h3OTAqC$8!{c?CnR? zAgA2!x#$`4?vsdR(~d?#%-Ym=ha#wh1}M^tQfa1EoSHJpyu@=XMT_$p6j@n+a*Cuu zG_+bUXgpOWwUU%`Mo6ImGD8358a@qK2;Jhp=`${rm5df~r_LnDsS>O~YkXaeo9Sb+ z$c8g_c08q@JH7lcdYjQGaX;OiN}mY*@uan)1q!TqMPe@|NHXI6pC-(B!=1BGQPB1L zD1)i8DB(C*=R_x(_4}5<=8-Z?Sk_vjF1i&M*03Fu`@J2z7P}5B-)R(^(ZDx#Fqvo5 z77Tkjm-|Awm_!+c(HP?cinkz)BRQ}3%5`_l#VA5(rdcxg4AXKohOX5#OF*F9^&C)C zq?QZ{%&gT?Y0A+$pCtlmw{VnElx${j9}}NA#d5qPayrfFu1o%NB#WTlz*JduLLp~o zG7|_^7>21sL4=y7h-^Y6UV|VVtSkUr^2Dq{m_>-RR}6RBT?o3l{WUpxJtNtEtcOFI zpnFZ5A9#7W3J_0EfpAY))(wqMK|oeqY8peQ?^joBeyz;m?E7EseB!7vw~2y+svS+I z<#c5was@cSNcoee>)LdKN6tT3yS;c`2$ZSu-*FG}JSRY18+=JaW7r_OHv~Gx$|&F$ zTsX(PXHx{So82KX%d~xlMhV9&@k5Y(cr6h1v|cSx!gp8UtE+G*qQwK7-Ik33WEh=( zBpB{Rsiu5W%$hq;;j(0?51W!@&D3Djb*z;w3gTyS5@+6;n76pC-eXwI$u|Y=Bq*TR z5FvpKg>1Dz1Tcq13XB0l{=2VucRO)+w!L%hq+Ol4zHg;mk|r?syg4yxnquT%Rxdtk zY?==OfvbgZZ~<|93O9545($Grs(3S%Dd#_qEg}oc zW%@AtJ@VX4&L5T&ryqAVlE6P|x(^U*PDfpUvMZ4jZE<+xTl!Vu$a(~Zo*F2d7p?J0NH!quz#zujhm!%LirxWl01;SBV=A`@IjCg(|fB^81)AWd|xVabG1GVKc~c)*j+i%|H_lV zNzfzSs9JT>3x_6R5{Bd2 z(*p$V$LzBWyjkL^a71=dslWeA^*&xR9Lt%bL_*oxHik0F_-(;&Q+uB-iK28e-LfH6 zP0dL^94M_=XzEvryB&}Lhn+#@S#XIm?ojDu3@;#}$kDso&s=ELJq$cSgb)GnbRL~k zjT3@EF#-)0Ve;8X4uO0#m;OlSvYA3y8%2E*_(75MwHoRFEWZ0vBZHV`4S4%V=A&SM z9u$#&ij03NeY)=2x&xC+-sIj$;Kqjlv&={WBO+Y`DwxtW0YQ5V!h8&XZik}e`?I(B z`&z6B1Fvom_W_Gw`}8IhZba3EkrV}n(*>|0M=nN594Bd91`*_&AzS(+};WXS}9>tIM^ za`IwSR#jPSd>|5nGj=#wP_Jzj@Wa5?<+fc4pr?wW9bqUL)4;nC!H(b*)&PD z3c2^-CgTDgUI+$CKnY1(XA)=t)!t9M_vL=tpFEuRgtsv!N%#%w3bwbGl46lLE01r@}A#Joh?Opleob_w35Hq)u>mJAKS5^P%)UyWwh;WW-eKa+w-kL zMEd|}?jR*Gz->MUc<``qazw<*sJ+YGQnj>S+ro|krUI{4%t_nONH;Pn8lk0_Xkd3* zBkNoQQIf#=&CPU(yo(wKG=dFGKIazii$^d|15L?RV}Vq81;%1qne*`0tM_HdvjWFS zx{18mj_0rcSXJiL-bLvgnr4f#WQqabNPgM8(P+_} zHtELVq1UZ+a~lAk+f5&2DT+aoS$dS*#_|cnaww5Wm9S)rV9Bya(7*ztkdsN4V0wI+ zvmZAO^>y1}>7vGF`?PQMYwW|?U`)AYZXubRg_V>Y8vtjU*-3<>ZOnApJc4Ntn{|w! z=E5__E;iUtJyw#TGeIA%6~VIZh8dgg{Q-&WAhvIFvbpFoJg<3ZV|a=>)gYD(^MaYh zEG7`wmB%eq;SJ_$7lXaMUMVvV^czRS6vZG(mA|NutGWg($%wYCVvZ}a4Ck>tXo0k$ z=dP6>B_hi=x2H;`i|fd8WT<7E01X<7r7U zW{i?$QIwULFR%tVCb*~dfuYYGBwp@@6dYhC1j{r!1Wr$N>|(e8{QUbp z|JnS@+a$W&~9O*4HA^nPc?rYpLDQE(Iny z+it@qc^Yhz<;b;^4^3@c%WvP!yu(IRJXvY&-C68}?~PeQ|K63A^xcy-=_wQKyQ4_` zv-d&;9jh2dZ-f&M%rmU`h-P|lWa`TUp2E&PytAftUCiUjMB-+rL9g={@3flZ`CWNs zSEfK()0!AxtcDhbUwuj?I;kmHgNtk?liRo`09puVACaLJH;VB-)Z%h9exXfOFoOR+ zyIsnoq`G^yi8mj^xsPgOsxZ7+7>nSH_S2t)!HhoaR6A+g3-Dmih0Aay7~J94NAY!}>{K$P;K8AeKh zN^2pM5`5`8Z&g)fluxgdBuMjhFV?IAYWJ{Ux#i^8(Ruk1imI&_c}a4^yrx1-91%Y; z2$EvSN3G9Ctoow4CRCO|mY2Lv>g_r>$We}bVC?`+6bdc>eTdcQIsIIjmQ!h1YJVLM;T(BAmp0Ggn-Q;D<;E=lJ~z}VZ%4b zGdDr|HD+8)xPEgR;o`r3Am2bXKENQna}~b4f&m#;Piv)Ejq?obC&@OXS*35P=AtxV zf#Z1w!zsEs&Q>Jh$7F?Eqji(yQRu7>;108sq2`=!5qv#6fJ`U`cl$-}hbta9*AL}4 z;VT>m^Y_~E*JU{vJ^KW5=f={L(aBUUwJ?`$-1=(jUiVQ2Tu|fK>IIul^ma}UKlVvv z#MicT&Ml?Dg8sH@LraoAB5y*r@SZv3jVAe(-v19CluVT*l^3*2UWLCuv%?=fNC63( zVz0{U=|1Ai1`2&S#=wCbD;zfGMpVyW=ly<-+2O*MSYipO5^Uu=VIFBVIBX`AsKarw zLh&EVgwT@T1vL^0IK#N6UUSA+B5TU=06`S$EU(#Aqgol3HEC$}P!~P;dZJ;3{(4lz z=9=vxu6JWmLfv0!!n$b~b~SJvES@c^`j2Vpxl;NphpM{grU2l;9%GfnGOaxw1rA8c zTU|Ax2{Rna3Ysd3jdnIsWPV;Eo($5~69wzRbtoxf$4lp0JG6WticJ;k z>fBA=8D@qDK`7X67Jc^^Tk!s;<{uilLz3Sc-Wz{kJ&e?NSQbZu*~k_bYmuE9HPZSQ zgqp{S#qBiELvYl?j?#Ck;ZuVzW`RWw@xGhK2VyXK@>idy!JbSWDL(lBi)Fg;L9d0w zxcR?K6CZN+0;qy!f`clowUes6LiLAkvL$Fx$#)fWqrIa@2JkQQ&Iwx>LLrT7@VEAQOP;R6v+NVV|=pS{ZaPYRE8n#S7;8ZIu zuIeNiUd)T^TSJ@Yqgh@Ml^ruUx{^cL-V3g--xyec7}wP&CM+Yt-bz*%CYPHk9>1wgc7v< z{`9CEU}>3;CKSt=3Ow7;l0eRSyS1g~wEO9r%43G&nNOML#sb#%!Mjj!R^suZr32>ZS?V03IENR zVipSz8sYTy(s!Av$A9 z091x$Dj@*?%-0L_qD>eqL(JF&i<0go_?CI}y$%+R+b}($iTI7x5t{J6vvNX~*E{eA z{)iViAl{xv1RpH=w-$zpv>O3}-S&eo@6gNM;pT=IRg9tcwqnh74_95c#v@^)W?yR1 zBq9I}HxOH)`#NkRb}9Dw<9iOfd9-;=3RF;?+FG>{l%ZduH9AjL(m2Ji4~+s0yVBf9q^Jo4QpYU=v7A ztjsM6HLY&QS4K7P99=a%-|M2FVV38w3mYC|4`O&{SDuC{9*nJR6AR z3d`+i4v;dXE~Jk1pZdP7ZPxH6G{V8BE7NH=E1Y|CGB(as;v27v8~d{9tp$H98IFNy zuzH>?FAPD`yjJZIUj+MGl_G}c63KG|nSpy+ruA@`2xfPRM$lDQARc4QD9@=k?;Out z;ryHUtA|O9dX4hIN|9Q@k&Kc2Jbx$AW`MXj*;7JKxmI<4>86J+FKsnE44zq9d-EG{ zn`S3@b$Nn6;23b&{EUOvIlqZ9?NxbYO7$dv`b=^FPU^g3z;FnDahB$B)MJXrjYueP zjD9kLoRPJ}G}(n@NeRXr^)hsElKAea$b1oGc*D&PUVr(*?W*L8_7T$Pg>F=32)wRN z*|84~ziXy%T*gz(Py3{_=iG+#-hj|t;a;3mp!T)a;DOa|Evj7*4-_QOX2qCpP*hl7 zow%c%_Oy%&wua+TN8`@boICE)2aPkjgAq=^i&hYxU^ei|>a?pSk3HvFoE0v}IVl;6 z&6fS%b^Vpv(4>)8cq*hQ!9N;fWoT(McYs-1aVOh(kQK^e<06HNJQ?v009_dpB7;Ya zQ9Z$6J-xiO<8`f3>`lOD1E}7O_f@W`aO$0*UV$IX(CYSSu+G2-8oY{@!{Ub^ytp5{ zlVct(Ho&VDfC zM*^Si5Db`8Kkn#ygBMg?WW#&h7dsBa$E0zkwy%uoW{H(mwO)x`(em2NRF1u|^Y~@y-J2+zuFqu0x`bW~qQ6fcGCR zgMa|6DTNFMhk+8NBqc&ns2~Ox-Y*P>OgE#VtX~2e+;^@779bQ?mi_KX#Wf5;K5T1f z+F@F-P}N@Kd~^Ky@^W&r-|I|&|G>aap(92{cu@lI*G3=<0^*V?$xqF==L4RxVmw}mY&j@P*NAkWq9Ip2rE1)@b)fPC;5vSUi1ZzByPOUMKZd6$|J9fwp>pU;55#tSw z4P>U6*UCyz=JsJ|3M7fe*SU@xll+U`8Fcr>t*@0Gk1kB}gf7}(P33j)KRlJ0wG!Vg z-L(z4WZ(~mU`RF`?J{e{x_DI4u7VaZy)};S8lcK!5X`-xcIaQ<{roR{;-S;7-Xxsh zG#C=e?(HTJy^}q6PtaeOvjH()A7fMv%OCZT8!VZhc0bKz*~%XlAsd?<+YB`Zv(U2l z8Z*{4Msb?eTwJ=fw%&2+#gq3kAq&1=-eE`;B(iz-Yk6F{UNb+H*q6A zt|gp8lsLL5YIY{$>P#?Ma)RF6Jbk@BVavH(*_=F)Z_+efmMLgihI;C#jN;^5cbK}h zy4)^u(yFDKwKLxhL*G);zAx4IkGn;i5@!b^jE}q!t*G9J3ZF&QXRU~e5Ksl9OuY6e zpGDIQ;Ypw8S&FsH(?wCY=({61ouX4p4qtW49LqE8Z@V*|#Y5Dqq&q^N;b%^4>Vpm2 zRG1N|IO{%iB;KgG=5;MdSqQ>vcpu(|)v(&rb+Mw%Rgx0&6nP;xnW_t`RB)8k-ZUZj z9LICa|8FB?dIbY+B4{IDeMSG#S0iZE#qe4FZYl6-I^#DB!FZ? zQ7f_w;+aKewyx$J%VuR^^WA+9fLB*neR|Enp1I?>K6RWS zJM44bStsg5&ov2ijIEhiay$>h8i6%Lj&(SAFrZ@--*Q|LpGqp)ZUFh9b|&>fO%Ii(X_&TcwHuU!A(erY5qzocksfxrT4*^0pjga2 z5H&eCrJMYB;hd7VnPI_K^@ZGIs;;i@+fZt2Z*=!S$yo25!l4`L+sV4K1rTT$rY-!} zgmZpsxFty!carC!q+N5jfmjFPjYc^A7V>dr)K8s%AHU6;Il2%8fC59Lt|PvB_OwG2 zzjg~^Aap`Mr~XMmKWZ3I6@51WZjVlrE~&v47EuWRrggVF*KE|F89l07!{d_(H*0SU zm5yws2uT;frVMr+W}zZW3tJFpEG0^tVUSD>$pO+hVx19VHJVc(7ap?XD=o8F-#YW` zHh6b@@xPIkMI;|Lu`2NH`aC>ui??P=gP}@R@MFlMU{vIXxAjRd5BsE*!)x8x45gT@ zjwfOl-Xe-$jl$Vf$r``>if-WXG3KNBcjNi=Z;V>DpJmlr|^&|qGpci{h%AIFo6u_37EGCXp zwuwF~sSOsFyVREH)5cWmCo3%}x5-ZoKmS`U0>aO!4;-nAk|-yybx(!Yb|q+eHA8`? zN^Abk&5WMb*B}1q1Z-JvtVA*xQZE1V+wHa_^>HeT#yg6y-CPI;KW*apEtt`h6rz$!Sk}p<<9{%s2DXjt#%`@4zK(|U)LwO4%4(k3bYJpDCs2AM@eps zfPkFG%*J%JqssB0021*mVoCc6JK;Ld^ag^&-9JHMG5z715KI4#5c!(bZL8yY*~OR3 zR;X&`L$m}q3S@Z$4JFyzkmCv^kW49vh)&W5{f#~u&^x8ulPwkth;{3iCyO^ny@}gN zOpV%oRJM!Kmb_2do(`O)2TqevCaG5n_(^stou5ql=4XH_|8nPv1!HU9|GfZLo&}Fw z=|W+CGuHfP;RnY9xokEU&?*a*PhSr^-Elp$eDKIOm!GX8#l(Hg2LF;gsL9c5mFR=F zR6+wA&F1!o^x$!eEcSeL@DwO+T1*<0q-;kO)9=dAGG9uqCU+Z}W}yOfNhEzGZA-!N zMk~m4Cy`zLDPRsfS{H)5nGQ`+B;oViOR3cp!1g(=aD71j{N7GUSiJnI>%_7xk~FkU zRpmHj*PN1W-A)3ojTcv^jbK6rKdDVnaY*7y+oOB^p_k75@b~fO4SA#a4cGWbH3!e^ z1l~|4y+3*?agZo)v#(DJ^iiHyRX;Nc_VI}0$)`6@dEo5EMR?qNnyY)eWpY{0cHnwN zRrAF4bwKQJ^>d`e64Pn~#U^Mulev=jeAn95XTtNtL&LKWI(Q~|z_L0fZOCwHndY1% zyOeh8MG#yY7T0(@c(#%`Jl`?-Nr%Fw>sC3CZ=l!OQmBC~un-pNDv~_HQKE}l+{nSv z#ggv`FR2Dh{qUj58i=P7&YiD#ld|o}zR?bH&N$`P174IupOZr#HiBo?=-A80^Zy%? zSNJGy8~x49s~mE7z4LgYouh`a|Ke3(tKrA&&Ukq9)U~>EC_4%{mJ7VdB)B%KmlxRsK zF{f)K&=EtGc$oU(Lz6|&Bh60;8=MFV=v*q2_9#_4!Vo}c0jxmG)47lie?mV>6rqtg z)MVQ}~9r5RnUF=ra-FpcT1qgAZ z8e>+{+Pox6WUd0*0`iiK34*9r6JUJpA~gy@|MHN;-uvF{YGJ{D8KiW-}+kQAgFyu-8pcRlQ9bU}Qz4 z+s#T4CkUcVCDx72QF0h^k`SpP%)6qWE}I^<2`dmzf)!}Rg9i9BzcamT6W5~Sy|uev zt3N2lm&UAdkGM&m)6@BfYOgU`%-&dbfT8$wK3m}d;{Hq?qLn)Q>?4QX@az>A7#7n% zbmnjvPFY|Q0C=I+hp)=pSYc@(dof!m{CMJ_M2dppE%s=BK~cFiAuOc%Lt)11i_RHf5kT8-jCu-!%dA3~f=B*y0Nz zZY5Ys88dGmn>#UJ+2EJ!#cYFl>P9@)kOSO~pI01NORrM&sSd~Wzc$+Xaomj%&=ch= zJuczF`5dwyZa)ob|8uQgHEKPSd*9jFo|}jf$a8~`^H^B5mba{OVlbkbY=_Ou9q1KU zr;`teh>ui#5?VciVi?Wf6w8#6D;fBxQHr{PZeXU`+7OYKK}B?SO9D{iRm;fn3B#E z7mpx*Oi+m*V%K1^VC9|&b~ORvmKZdjXF(^iq2UFNkeZ)8ztSiST1m*F&0fPrV`r=v zGY;#kS=F%v*RmUz09sX7nd^#a%Feo2^|ltdAp;ot3?)hi{J|)tYnmje5-%7j%Q8)4 za-F31vb`gpCLFt-{l<0Ugp4ube(gZc5KbYb(rR~)W_cK@RYyyf$YX3ls#FelhY;W# zF+n7m3YzGylv4RMrjt1U@at`N1 zf2#_oW`O~qIuNgH)f{I6#}F|_AL7%zLybXLZ%p(VNq4rjIgU$P>GY@pFmouhK~g)*He@dp7$8nfMWS zbJ2TFJC>25S~Im2mEgtJ)v$6*WRm>rh#>-VW_dz6&{_{fY=FH8wJK8NSrn?ZQH!J~ zU2KL*R@a#;KC8EXi0~QwBkYQ>$4Xy@Xb?6-qC&qPGUJngAcjPvtVT1lmT`)1q$!H$ z$l1pTpgm|cO1KtNebIhOEF>bx^4xh?0{%{Zb3zO8fUYXb2BFY0J~yP|BTwbGSPEvi zso!s$*&!Csxad_3H`QW)PFdne=JJ;eaDJx)df7_yb&4f3W{TKM6B(^I^E5g-zbHvJ z3=22d9bkpfJEewYdiDo3C{3Hb-)K~3w&$bMjfUcT=M-Tg1?5GrMS!qXA#YM!s?1A| zZfHnnUpPuet`ZB~!17SQGeY!j8;cxnz+CRYN`>C{77K+iniW}o#>A9~K*Ni%ix9UJ zo4_>q;2!Lgfl9uwnuD1<8e*uH^DU(G3~dS?*91FHc0RpIG2^UW@w}ZI(}H~$IwxGg z5cvpR=&~oE)=aq1>pXkca%H3NCxe??R@WXWQ8r;@;uKBly@YN(Mq{{a{ZX408ni4; zD-#oB*wYQmQT$_SPHh{eN+&ntwH%d7;(>?6M3M+zK*Av&8j+GR_Xe)$k3D%hBMEVIW3kb-8$L9xVOn+sr8x$(I>qd@$q_7ivgQ zlq{!;oI-U870cG>(XA1hQ1vS~uXd3WpltA=E|QmS0?DioR4Y{kT9+HGVpPW<<|Bko zzj+Q0H16hediaK2EO|H1iAipg@SF1w6s}3h`^&)T*Z0?>@LP5~W#iwe5nMGeZGY42 zBrJK`$_l=kMRaMpBN8;t#h_MMX}BD*ortr6d*=C(m-N3G7!p%?Unfu%U7;&?Hgq%mxeqNP>g# zG9;lSXI%98eQcg*q==E*iZ&dZ73m6sRA`2mAVX2PP3EagYU8(f!b0jO1uCQy$+F}~ znUP0;*W}XYjhJ0Ui3*`(Rz0eYt8I9g!!S}b@LM}Zq=nvOr^|m{=a!k9+fbqHy5u>Tr!uJ>R1QH5 zD3m#-5{lz2mS@m&z|_N{#bhd#6a|(-f+U@orX<;QQp->8m0c>NL?JVRKo{W65v)d@ z!;EA0JR?J_f)7{WW@4{3V|*PpUQqjF-4j9~o^!c6$pE=CJ1F`X&ISA+g}a}oph#yP z*q9TYmzGW*;>Iim=$HbI=H8xSIBLJ;3jvix4ATS%elCLJ@!;;K$HNy@D954ZG{)sM zE>%so0;~DQgjrA$5=;oJt1N*;_4Z4VdsjB8LN5FQ=OGv6TC@6e0O>l1P(WtAe2*1^ zXyys{SA#Hl%8?d>i3CYtC{ivLS*wJi7(v_;5g?_OgnYAF0btJkwz-Y-6C9e-f_vGLvUjq#oF!|~JOO|29cjZW{%7)Rg1-#&(t97Cubj&G_2 zo6B3Flu{WVtk3WVq#k#2ixk4b_0Hu5k-*E9bStS8G(e>(E1&vrL$w|!Li7@+xxh_Q z#OAQwQojPNnEDQ_YUt*v?bs`c_auoH{f+KLh9bieD``?m0GW9*C)W|a8nzg@9r+V| zWx+G(Ep!6CgpQbkSM!uH@Y2{Ud1VWz_8yX9O4sr77P}(YY0Rxnjnw~Nw#J=K9UDp(){M;#)Ho|r|2<5OKFW*LngtLmW zwOYiv!Nc*P=_^mcF!{z^-_fs`92AvoOrY985|s|zj@Djc`;H7-4c8bwkDW3Lw@Vw1 zRC%SFdcN4_6|`h_PyFBT%gUl+VI<7OIp_uW2|Wy+$)I;?5Ynd~uaimcmRQCLvIpLI z5`!2v3TJ+12#)DS#~{I^n>$&>;)Su;A&t;^4PiJw$6ejJwU-2(3VzLnL>~-N-N1r7 zK|)ts4|Gbk*xLnfbFao=H|O`$l#x+g(fiBzkPbuZ&4uBdF}p`V5ddN`y4Q@*pLl4MjE2w`u3HRsmn_&5$Qq8bWqD||h>6)y**ancyh(gKPZYVUg<5jWMEVDNDWMYNIaOvzYQI-Dgv}8Ih z;NkEqKtc&Vzi!O{X9PPg+{^|WOV|{4L6p1*Q--zlM$zkKiBj}n#4uB9vLXYu5!A1X zwc2dC|1(X49{C7+9r@V%=W3UFQ0 zANwX*Qh`H?kZ!))iH{ykTlk8vsrtO)eXjd)9T5jugrYd`nbszN10Gn>X;3RFnoNmppKQ*z&Jwhbg70QY9oK zK|G_OE?d({T2Yw1s_=<2C(fr(H}|NfLuYeX;f>&q>E zQ^2GQalb70Vu!(yIY_Z2g`5+bq(-S0$-2Yh)HAJ2@PfPUtr+d7vSuma{OfC`s+Vms zIH2ak!vw>`D{Y&!dbMHcnkM$^@VqS}%U_J68G&OcP7I?k0o<)(#4Ce+mZB=JYP0uF znp9jVnA~z|+0JQj`CcPi{Or*cJKpG6RBD9GQ<|&|R$)@UlzHyA&Y#=tq6yH%+vt5i zH%d4uewL~`Ej>lkx5M+MEvQP|IGG2mn}B4RT}D-ehSO1Ahn*j3^br}52ZAlR{(_k_cmae9IdpM_tpnZ zR;O=%cL94WgwwIyMRY)QKmB{~fo+gzJo-=yGbqaHi3Dy=6aO*N>kn_e=pF{J=%n`; zHvRO2FXVQe70R1kjPk+WL_kX)N^heVcG!|Ad**@6fA0CuYS#90_*NdyjcM}2DRk&9 zeA(+g|0QNiJyiUL9>?DiAZ72+O=l!-!jX5{bmO2;E|`z zw~nTN;s);K)!aF(W!*}3ZE#Moe7@5Gtw_jJ7WuKx%*2l7S!&Cv4yyfQS}SdCOJY-$ zn^0t_NR@TXv<)qBGLPH@pcaEu_hJ!gz-&TW!Zgx*=h1wmjDe!kH8dS`NJbEFP)=nc zq;9g(f7^kFVr;5WTpr+&+UXh{fg_q&fZS!wl1^k2xl*8-3#&;=u!zJYS|ZGIIt-Pm zp^EEL@r~ZGXEOXSlPItZNQMKGH1Q^j;@c%85_FvV&&^*2#z^Y?w z%U16j;Y6bX3cA7Wx5Z==GS6s{O@6x$XX{sB|0P>H46NdTso(bVik1Fj_ClP(dxxVa zs?1ZGNJS@M%iB3BAj zlV&wliNH}}STGSYIvs|})Q}|L5%Fy$?bx6KKZG^ivO$+Nz_N;+n_Tj+FL5U1wTM1Q zNax50H0bvM9ydP^`RF0;0Ivs@~;kjN`uv?Limuw`9 z>DB4e3@?EEmCZDQW;{R}nw4g6wF0@n1xVBSDdl8pdLVciKr$$RPKd75vli{4DTzpO z9}G34C%&8n+^H;ovA{Ab0||#CpPhuIuS^>e!vTA445lMq$W(DQB86q9!^zSD6r4U0 zcvBTCw^wp^q3KD}dXJK>njQ!YgWdN4+)JEY$MRa7s;GqN`P|a%wd>!M+9g zi(Axs$m_ho#143ozP z_xz8e_HkO46VRLvLhS7%i*B}a_CA%n<#v<)|qz@TPLO zsOkczFcQk&QD;*+j-eTgv6!QrxK(nd=Ln*J2)P0;i}4mnvT{!pNEs;Lt^f|h-80G^ zOqlY=Sb!_giTb0x`f0)G+?S}zg?Z#<0e|gN$fT*EadfJGhz*7Zu%jsuAb1*`Baw~4}r7?59;}WxvmP1AC*f!zt zL+pD2M=Br9!4V3k@YO%sy40UuE~j6~D;!8GQYwHXr}r>X$D7J(!bLCu!s|0cDF>s%78$tZMtlG9?0yAN1E| zi?_|O5 zMB-XVF@<5F-Mu>V-V%fWLdZ5&+kKYa3Q4&@T}1?r*7v(>c{g}h_Frq4oPS+aU#vJf zuonu#6R6G!%*^Uf_#Y0sz##D}F7NG2_*u{+4hTkgovQk)rbip}(WmdQqG6=&gnjB87#ay&hk|8fA+On0F|2x~gKHYd9hvsb zKIBDC6}^4@5j_u@CV@ z{Ekp9Y6HiRMH!`@U>Q~7Yb0xu(}*#PCvcKkGON8&6PSj~C~24x-$I&?c<#H;ZLWDB z^q-Z|uM3H9QR%2&p;$Vw#MfMf~cd z2~q90alChG^iC*BEFHSVr?+S5u1xf>3J<2 z!;k3$I&lO^u$DYTkD0J+Ni`ZmkYSsqKc1uE2cBI#t5f3@KqNpyY10%V_mw~fF(O{T zi!8^I2vHoT;1$9usx0K5nvEMcAiO~M031LEDj<86qUj;1i=ZS3TnEn!mMD=D5Ktf0 zAqbM7)=U&v577k2?pAN4hc-Ko5UXT|hDVyzG4nEG8?c_&sD9ucG!2^? z1MX~pz6NEsojM}bouQ4?H6OjBn{v7gs+uEHAqu^aEXYo6XpPI6>UO6Hvtzu<(e=ow zJJl$gwytpDqUsmh=~8{_4I2_(Z@>UH#d*KHQ74GMyT`BHW+GD4-5o4u{E|Y!?qm(% z2InJV<{oXKsh!3|sE&|0S?7(1WOSI-gVNyG&93sw7Otg_Byx!i?2Q!HW+ss%$lS{t za}BWasBtCjU&{vlLhD7H+@T zgpINg?#bl>g+TF9x1Yya=WjGg`;**}Sp|xRd#wZs8GZW31*aqgwg{!5ZHF;>DJ2DR zroPt^1gX{PfZ|^KKkD1~n(yQZCQ8`I8cHasVi~`6+#XU}HUvT*QY9kH$eE^RY~aSy zEQki&l)9u_X%`HjICG>Fp?*`&L*MATx<^H%K+`7IG1&4j#N7))@m>znWIHP|7r%6 zgOTfNsX*DD5-SnKFy2)P_^H;*YRBp1n3I=M{M9b&`nc$3rU3npk8q zjLTv(7>dX->x_tC&JZ&pjICV+7+ZV|Ebu{VhmNP|9*_-dB2HeDWYIJIC2vR6RMi4q~O=d>GW8-G~Oet!lrc#kHBEK=Xg zEcDX=mG&xu^u4su$I*XO8FW3kV90?5AHqU-sUuUh_;CkP;VGZYxFJh{FT9WlLnprX zJkA9RE=Ze{EhR?zy{l}&XP&tf#&MmSw%%kok7?U3TTc(mnrWw_)aQ@YN}2GYGT?i1 zpj2U%jwuK(Tc3WBUWpUzCruf*aDfh2%SPx5M_9@~fcN=f8RW@Ra^;`<4qpGM9g*Ze zS3vT;G#vM-MC!?Zh1?J4_#w-^$qNxbt@B)7cs@Fdou78c+0`J<@m<-hW9HXRj@Y+FmYkmZ(a?nmCuR*84R%Jho6Rd5#K^temmEdhXi3=Q3_RSYL&C zI$N@jp5dx94@7B2;>=e{b%Xpm1P$@cU$C#W?VI#fvvb(2tES_5jtLA0ATSseYX}8@ zdoGdd(7_==(|u35GoXOGIvCo(bWBW#;MMFU`)GO=F`B4YsZ^^`FNbESlz6pT<%TED zyCRL`5L$GdOCbma8i4TLhEp;uVOWkLNja9z#rSGhV-vuWH>sMn9oJA^%W@q%TdmhU z#}KjJaJ+hf1qDzIyP*IIhN6#5#dyA?N*gggpr13yTH|NTDxvs zn7B-hx?|!`CZl7s8Iv86ywM-rKi8d(gg(>H*Z6`nVDq{`w)tZ>feYRtVEfH0+GfLe z5&r8Ux_v2xt~L2Wa*Z)av6-BdO3O=C@8yk_!DMS+Bwg|^pD@BXb+JD~5^Q>msA30U?!3003&O{)}Uj|6sZS-XU>YujBe=N=lxvgO*8qHxTy!u0i+H2FL6QEw6- zODuePtS#M1+(E-6#I&`G+aMWv3-_?2et;N7kcX(F78xQa-?#RaQ2!dHq$*k^Yo@0t zrYX9es?9<(bUO!~^qYj-VUbp|h@%Y90Q-Xh^HeN7qQuD!uc~x*N|%ycQnI}(EuYPS zfdd>NA_8Yiee`REEG(&e2^2A=VC9Sr1*I9r<&R#mo?xY5Fu@v3O+$1!-|B$dO(j@) zuXzNenQ6aPPFKztMPRSJhPrJO;Zax6b@{w;9l4YBm5E>PnpPBcYvE?f+Y~}#n=lpL z4+$!$jzZIfERI8BDFVlhsRZO;;af&Mor?cp1FH!o_mBW&h@3y|2)}$63FG{GbyN1x z!I?qGacaB0nSg~l7L~)b+?P;{%IUm3-BbSEmF>gu^;m9aSKb7C;O`b@BLnALt(cpt z>Nqj+^6qG@MY~+~Eh|pn{i@ZNRWnrHJq7>a^yfB)Iw@DHmD1Sj;%yLpPOjPYj^E?NBY4bKVj1sL-UkY_X1HBU4dJZWFRy6%7}zgL-siS_X2S4OCYs9{1zQ)`@=gTLl%$E?Op5 zp-zkm&d_X!yuHOirJeBp-rWsfC^@{l)PrnzL!uBn^nB#gFS>2vUXwMpKb4rBb8+me zp0T$~8r6nrAQ6x>@;UvEY?cOtf})N#D9~_@c#%&sR8okJ#w~ydCq~4Pp>_RHeZpd- zI7&S<9P@l$;!$l;iK7r!iF>X?GYf31P%5z`ii$o-i7cw;oeFHruQgm@hP5Tj4w|i{ z@9JW@{yQ5(AXOrO005kr0>MZqWk{_hBgT28U5cjDSwpErnQU&GM*2~3u2auPNxj&% z&*3WhA@s?|OMxcDCGU!2OYg6XRc%bMsZtRGzFW2jw4%q{zk_Zj~2c;!td(-Um)}qb=lo8aB0}7C9A$xR-<7+^*o@{ak zZOV*Y$eUv3<_dg!#WA3k>88q`&PeuBSS!_HuE7{u^S`JyV0Q9h4Xo~3Y_c1zCo4H= zD56XPXThuo=cPmq6naP>By~BPikXb>OGt)HW|thD49mr*OO-K21(U~IE{2joCnciB z7aszpny?VYLls8;9>FNMG)MKI(d-CZh#M&@z=4i%g9b7n7Brx7Ll$v8bcI`=O8cSO z0$urhx{iX`XMzvTpPIK;-y z)!k}4hVxT)oMtkV;xjcfGS~GKM7k^a*;O}BaGS`TLMuD7jWy+E)EID18yeHWCDkzw z*O48UkQ(lrWmM?;3$Byd7O<<^W)0%8>tcd9_J`&rNUi_@Vsl~AU~!MNb!RWKyW~p_A4czN zjL6g|OA1Tq^6<=@AIyzZNS>i8UbJ^sTI|N%hlcMXJhv7D6J3Kmc423?LLYdqn=*Xv7yF{{F8TSzP2)FA_;i|Q$bx{Pm!NG#Lh1K@O>okOFMXM>w;{-8lV^dPp&>Hz78!U z>F|hdXqB%^krs{oZU*o}k0l{!3XsY>pn84f;iIX+T>bfcbBSdl%E3Vl(I8JLSD*!# zGa~b{vBSNG!E>2#*!f(4NI5`sp|+>udHt*uv2@mCu!g`iBl%6!}V`P)?W3<>{! zWzV)e>dTK{V*_45;TmR^Aud;x%=UtL~t#=w=zs_D+D3K zt13|x86kKgzWU)sc?w<|<=ysuk6)af?L>YB<>m}L{voh!_pHD5fjEM#5HA1_Ib4JF z^8V}$J)=hGj&yjUZv4c%q>w}%@@ANxI6`!dvi;HJQbQbO8~ zq94q~(%VBHsGlo$-&)~b^xH4K`G3@)<_}_@A1ypwXg^g?oq|Y^vb#D)*AUIQ#&4r; zkIU)xx4IFfy+fQtJhiX@l3m!@#;>JPJf|l=DanTT{m4VF{cGb*KO46z<}7*V`Dvja zI&Db)=vOyVG4{6Qciuj~$k-x)RA|P$qQ6mV^;gUF#_Jz|^6mAeHX(3vgs|Lm6SnQt z2o)H;OZyX7x?`iBRqOlKO^*k9$PsWki@wzDycw{{4O$_1kKH_@R_Z{OkI(%+9|{IT zet#g4{AaIr*tWucTgFe0f}6}M6wJ~9rHU-~olQ%X%qXrXz0vG+ue?UCxX~i_xlypAHjb>}L>-jwQ8aCD&RjaML`S!2e&Z!4DXVVWF!J-}|`&U&yX8d9$LB}vTO-kZ-P|*9DVYS*BXu7nmc7o zH9~9@G*Ku6R9+?&$Se%}hkQI$%POn;2Y@bl0T_rN-kHfD{=rzEmau z+l}YZZ-+|hVoNV)6CAB_e{J_#$79q?>p;J+n#t11R7YB(`jw?WT1j{~I;yEQ?D}b( zb?N_vlX_7l`BFs*SOzUsMG8yW18(dhDfV75CmVxG@#k07TN@}^J2p0y1Bl(f%DJ86 zx;T!E+atDJh}m3J;KDuKTGSZY6&`R_oF{d`M3^&;HH^~)fMU9=$jd1Z3|ev^!w7I|ozJKks!#GMPxLkgr#CnQ0UnGDeZP8NX})y61Mw)luRLQfq`ZsYdYrWYL#> zm@V+x4HBWTHs*3&LPTsw)fqaUr%hQwMwWTDZaP(s58J75-E#DjLQ2Tzg;b#q?1>qa zVT#2h6Kw7b1Y#Y4ooX(V09PBjqH$afPPw-&y`yso3Ic&+jg*Rs0jkPm4U2`^00k;2 z&CGP(xGqKB_0Gh8r`b8@3l}P6#L-{dfQ7ORRlCf4mba=H8wuvLWmx!##E~ngLWmpp zQsg$OW;VM0iyQ9ACZ&X_h088jVk&OK&8$d{=b|`m1w$@+Rmhs@tAn=WGZuXWlvdsT-l}G zj?}}!?0V?4hF0Bh^|2q0E5qGZ&OJPDkoNe$G~A2^R{661bnWp6Lo2MFTRONG)`N;3 zr*>6XWcvHuOK&hdTDc)nxY}8ldsG6dZ5TyLxfa!&#_dvJcx+$*95|7+NYFr0 z;gCk%BX_KFY%{`FueDPO1YZAb?}~r5jc209o$4oNv;@L*`a6hn-{|4{l9aPQ#I4gQ zm9+Fp$cm67Xk)5qKR~MFHzj*{e$%aE=jZB{s>fvSk`A6PIY)H5ppKquxA__U=NfjP zqFw~gU9Gpa?lOFw)ebUs>twwuCRm3M+?pAJjnn~`&UaPzl5yfbk4{oyat z`(}l2R8H*`6bLz#9F-28J+43?=b4Bu`%r5Kjm=OD9r`^cFtNaZWFc3&N~l)Pxn%oAf`eS)lnb;G=I_B5$|&x zNMWVD%`!Vn7zLdmP~KU#iW=$hLd4@+1^K|hSRv%jS!w(OpclkB~6eg!f(9hEaD7MLC(NuioMn8Ow z>ONxjjiKix_g=_(HuqM|j}itB{Rt;zO_v0yq~{@#fRvrPM)1qV|MOUP9^Ve1id(jA zDrE|Y9ds_Xn(7UDhds+QQ#sGe{T17!dz zOiNrL{lbu7{J3~7ZI-CBT`0UJs`)Dp`BhU8PP*%#>PK%l(-{vjH;;2p`gr~?4Z$zZ zlM{J)8oExvOuebzC72*YNQ@8*!T}+Rny3S4tv1YXPPdivQ!x z>P3Ki*JTZEg#47PEJcy5V7jVYcJcNNiye3KCjMFvpub8K*hDFnc-76acRl?%0XD5k zCUf^;93oLnZN(H~lwjBO0K(a$n+t2p)+z=7zY4YbIY*k~w~wIqoVg|dk5=~W2Sc~# zpdf%0mNWd9mq2Ya=~A?g16@KP+^nx@`VAhqEJ+xRUrQF2#UU}Q$RxZxlt)K<6FSQ?u zjG6a=w}9!TtC%tww?-9G=s86Q#A7DBgi2ol2LIpw(iAA`oUG%d=TcM>=U{Qew)lX~ z>;$jz_NV{ta?|-&N`@oE$4@mk#yAb?a=wu{2hPuz`mt`T*r==UvMq)ku3X$_+p;Of zwdP;D;d(nl4)g>+!C8xdZgX85=w+l_b3@S;6N=`mtzxZ!_rLRFJ#eks8gK@*8XACL zj<5h>4*lkLVPA}xlpiZZrn6QTeyvH)39NuvX7^L98za>zYzdcnG8i{4vtFO{rj!Q; zxynuda6;LVN#1K|X}a*18Vr51p-hKcJ!bL0Z?sql)49N!>`zs5Zb6>qwPs)q^qOKS zW0@-~a}&kaEqF~)E00^P@pvj%ZghHzsilJ!qf@s4>xt!4UZq)qyp9;d+oqTW$;`E= z=q9dKm0Zeuj;R-NDrI`ba*gJ_38TT(95k>~vQtEHxom;sNCehJFg#gk$uwol3~2AK zJyNkfFgPq58JXn$$x?&eA8ElQrNk%c&H_I?&UbuMO%1=t9W&G+Y1ppGbTGhTC;)=F@biVu1+C(FcV)yJxj<(Cn(g`Y+W{qLc+H`;Bokx0eS5AbnVgof5x0M} zAS4p`76+Vw+-<;v9`>f<#pph4kdOY~)`1On3$0vWLrzmKqZ9C3= zTcB`a+vn1zwaLR{hkX3}ZEaf&ZO>6ELE@C~ob4tok_8>%j98VyafW3XK{Uf?@kSH= zh#x<9B3_o;3MsfyVU&1j=6UaN63*s50PX)fyO2)+D&2P0r2= zAA4XbQ&lSqZO28fCoy@}^01Z0Dho200yW8 z0~lbnD``I6V~*GDa@uXSol0YH++a}*FIsoKbDe3>iR-s7s(hYD!Qs-j<5$f95p(Rb z#|&tNLDE~xarPJvonUX6;@T*l^W&Eq4C69eV85*b!$G(0dDEh|Ur9J_!lT>WiEoMZ zOF_3itLj#^v{1dtNjgAwew!Tym2M2T3mU<#YgxGsRow)0rQ}$Y7Bx2r4pDPHo1!sh z>zp>lYS#&%7PN2s3ZNSMxz|7}^6_eoq3_rq)kD|>OomZw#KSr42I3dQUj!b_?JAVE zVwX^ceob^C3bnPzQDi#rGiq-i_=cC{FlAFrLM6L12g zf4o3=@OGF=KX-TPz*A+nW8cI6FfDrF?9&5mplf#yVrkd^*Xcd)=pr3@={+M4ypIEc zTF?8tw-ery_amQC(DiXAq3!)$wfU)sAGQzy3O2>%eVD`aU_KcLM!`A|xle{6BeznC zZ0u6&^kH>VxsgwK7-&rGhab;wa^pq z7t+NN+#`TF#M4`l`5!mlk(GsPS29vKGwivF9 z--pF9!F$g~ygaZkw%-B2cwFk@Ca6RG8~vE;bL?$^#p`Z!3?MH#1s!%i32Vfhz`Fp6 zsh!$K+s=CYma{HBBzR*-EowJe00uA=003}O3LrPdoh;A>Cdt2cV;-30tT7hpeI6gAwhKToH`w^Jf8-IMunSo(t#|<=;iOmgfxM)3NdBVT$8n z0r3V_TaZxOb>GYpT9uMjDm|2(&S~uJdDZH*T&$v&c8$Lun`!Xc&WDN4oa4H-X}f$T znY^Abl5xs@5M-PsrX+>}bc20IHCm8_iVcrqlIufWK4KgQW8_YTI4XCR-{4H3QY`Xh z`6*v1r)#EYKd+~H6|36blhb|^f623m)s5|;fq~td(F|DHB%W#1mtMLF3T8RmeL*q$ z*|O7>`dDg*#~6w^O?n;5CIv|s5Y46`j8)|T0W7TizvNnd&;DPb!T{j2?`Ag-4ZYrX z9((^<&lA9)?AHqXe+F+>?ejo5@DRL>_b{qI$?UOFCR5(Nz1Y_e%$=q8Zw=C;>2MF} z53kh>1O1ea!&QU7Nt7^vz`Gs)6pm#Gi-*d3&b3QFbbMhzzXq-nM%sj+3oF&3tdQ)c z8o4&024hrj=MXAuFARR{qG}pbOA$S2?SmGM0Tl60!n(A^f66CmxAjDxdVo0%@8TA+ z{%(Z!`7t6-V$0yqh`b|Qk;h7o-cg-4=Ikc(#ig#o`IV=Oj8leUroLIa7D3pehnbk) zZlfOr+tJ7T4>cH-3ZLT)7tc&Ha?SKIWAn`~pBLTysl_>~R@ylzR|IaQiq`pr_PRZCzi6Wh0M*X} zmO%%)tqrU24#*JOo?&OK#1qISvFHF`Uq^?c~ZbQUF$1b?dE|qnDYxcCOhB2j*|TwyC|V3kr(W z-~TvhbDhvWtM5IE$ey_Qpud0uGN5}}$g#CTn8- zHd_;2w|gJaRw4R`R}ZUxMzPuITHyTqLz|b!a(VZgVK%w&FZTcJzz&C`BbTL9YFIol zKe1PCmwC#n{}EZc+|d3H5)OtRH;ut-5Sg{V^Al(2k_2=U6t;x30PksWgT z#B_QOFz`qtkSe?tgT0$?nZ}5m2ghDB(`-m3<*6wArMbuV(Vx&30lli^W)VATB#AiD98u4QDz2@=(#B-m`K}M-k&ufqo0vi*f2T2mR%D zy}c)1lyerjxqrOS@w1lDoj&UxtEJP}5X%GD7&v|+A#Wk2g54NaN}M*#F-=E#>Z5N& zf-nV0qKiE#n0S*GT?HB3_K}s)i{#+4i#$cGLm{t|Fe$OnoJ-XyGM&~PTDXdNC(46&e*6fD~;;!M-Ofc<%<$6K`f#$1Qd#N z5+q6?Rk@Lnky4Q;!;H=5!qyvwRIFfSZ=U#W688DA;#8R`ftDkIf{-|$X9atEJ8F#!MqC`?me^Z)<= literal 0 HcmV?d00001 diff --git a/assets/inter-roman-latin.2ed14f66.woff2 b/assets/inter-roman-latin.2ed14f66.woff2 deleted file mode 100644 index a540b7afe7a46b9ff1412f433cd5180a9a9ab77d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42464 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�zBE;A6`RoYnYVbGchb9$^iIU2 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 diff --git a/assets/inter-roman-latin.Di8DUHzh.woff2 b/assets/inter-roman-latin.Di8DUHzh.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..07d3c53aef14e7e3aec6b11684395f2833e0b3d5 GIT binary patch literal 67792 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 IZR%D40KZ@npa1{> literal 0 HcmV?d00001 diff --git a/assets/inter-roman-vietnamese.14ce25a6.woff2 b/assets/inter-roman-vietnamese.14ce25a6.woff2 deleted file mode 100644 index 5a9f9cb9ca0cd78b6ea2f3e5c9d2838dc8895598..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8492 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 a!Vc~9U7SGB8$q3Ii#9CnAx#qS0RRAsKuhfa diff --git a/assets/inter-roman-vietnamese.BjW4sHH5.woff2 b/assets/inter-roman-vietnamese.BjW4sHH5.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..57bdc22ae88555c6217307e4064a642f83d642b1 GIT binary patch literal 14072 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 b6r&82^QQ+ZZ1?Zre-i}g|91_a`#}W>14e7b literal 0 HcmV?d00001 diff --git a/assets/inter-italic-latin-ext.CN1xVJS-.woff2 b/assets/inter-italic-latin-ext.CN1xVJS-.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2210a899edaeb06655f7bc50e7f94444da140b94 GIT binary patch literal 120840 zcmV)DK*7IvPew8T0RR910oVut6951J1HHHa0oRcL1ONa400000000000000000000 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 diff --git a/assets/inter-italic-latin.C2AdPX0b.woff2 b/assets/inter-italic-latin.C2AdPX0b.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..790d62dc7ba719231f86afaf50988bf0f3705a5f GIT binary patch literal 74784 zcmZr$Lw6+%pu4r*scqZl)V6JV%3IrZr?zcdQ`@$!_buMyEnYUsNls4wKs*$Fvj9K< z000OX5diH!237qB03odafd8leAK)Z%;Rc++;`QkZN~#MhC;k$Y`;P*sAPogoRE1Ro zbSc>YA=Zom9Iydxk^xzwOu_fAARM4%U@_2ep}zs(L=e%gP((WI!p@<1%#T^utiVB=aH{$zoq`p#x-T)UQ&XOF@J-O>rH_l;h_*~ZY+GubIr*_ z$9_fg=hU9C^ttn+n5hq)5-WJ;F1v20ZFTc+@WzT>BFFrd^2cHh!Ls5%CO02S(TuR1 zCLPMoETwm{mLjKk2|L+(2DbTUQd7s6SxwIA@3a$Smi@}OklGvTo5CR37x9QBbs;$h zU?R#oi5(LShdkhB<|n*4F1ib3S__7f#fpjx6g}6yFxcIYI^rK)gDGYNwU`A!G-+Fb zSh!oJi5spF1}h3d#kstg z=%sBfpAs1|QFjypRP!}Y1uvT*8QYpjQVfJn5(7pN?@2az7u>9T|4cUL&$hpwA_1U( zU=IH_>MeMzf^v&EPwlmr+N!sxlOiah!3Q`N4}%3Vz4P<0O1;)k<_kvH#`?2_NmSwX z*?l3wRWiIUne_;i=H6%=MQsCwLCSHsM<@y*yM-(9iZPdSywq+A^dUaM4(d3$%Bg9q zQQdgC$=(sjH@OWY0a+P`H=^9lz(N$wRQ#azRbrabC}b^r55fHig+7hUgzTcVWH4w% zp71QW01T|KQMnIH=u~v1j)B#(@#c%q>q?!QtXEx~uw@nUSn?ssI)FrbLu9h*s-oRr zkXbt9IHWzeSKjX}IJF9}p%u`1WbE~;5)olg33CztTA7!;Bfu^a@&#U%GP#8Or(Y)5}&)F>SMIg}!A)+z-m>hwV@}?y z2A^0*;60it?Y7b<%Yp)(;MR~Iru~!snPYj0Z$UGb>F=@+g1h9frhAcY0HqOkg?wZS z)eyV#lrWd_ggxuwAyq;Ul4PhmI?7cvE`lkq3GL>npw#(h9LsuFpzM78l|MmvxQQ(D z{1y4W0n{gGvI(Z-Bxa@V#ZBJ=r&NT=F83fj1o2ix$)KzV^G(Sd#fxUtb{g)*wd#$U zBWu$cOH*F%lUj`C^>n{_YP)w_cS!Z068+d;!UXY;%i;*tA z@7%B#^YC~}WNkII3gT2R=<(cR#V3!Tg5jVQ`2I}Zugpb_RJQ52swXQaplRa>GjNU3 zL70K^!odNUlA#n6-&V@2zlA$5i}?3}eS_+t1RQU)XT5|FV~k5G5vqMKl7>L>W>Xpz z{DJii3f<02iAkc5v2o&8{}$ZTtKGey?YoZ)juJDxP`2a!b^uxw+6I>IxsNp-5)(=5 zoSQC36GdRJ<;C0&t3^vEolO8kMAR6yzI5#ElX>unVvxoc1%BUur{lue}hPct6o@Hs?pO=fAZd=1rQK*5TF|AX7lOrUo#r85) zvZu`uq0wT#AW>x{fr$}=!j(VqlEA5|`qWF!nLBvB-q4-ayoIWW-nNX)$n*jxl7`jE zmT<}9KQ0HpjXQ*&QFM(zWYID#w&HlpcwG4CrtcgRNY-PiJdgEU{Z-{L$ zf)osNy4T$WR~i|_lhMI`LlcYm14IuAfDeuLEWH|^o$4OmEfCmZWZ`3YgI16m`s~%D zxp=}=&QN<@$7by=aN$TM3QWb&*60mu1N8C6{GrlXEq~5PH=p8HxaXunD^M3rGgIy4 zSt}!lQulcPv#uAv%Y`6gc?>1ZvV8l_!EBE@DyO(!QF{}BLFl$&UycOVls8aoXKiSV zNrFM2MqT3DrSBHPq^qFb2dCJaUh)#wWo&%q3#u z4KOdCmiCV^59A|~)|xWx?jH+oUPNF-w>g*$)})M~3kAkom05%>jSF#Z!k__ti?s`= zq#7eI{vf+IjWt1duO4`ca(tj5L7qql2A@DWgegCfMteiIO1;2wu~iwq1t#Yop!c=r zGK?1^*YtyL$4#5i%VvFg`^lLCl-C%o@?zDln^(NR@OisD+cJwRM93*V%cm6541uqM@_$4R!u5D$NsRh%`F2EFeV{3y{7zyxz z55Y+~lHV5Km z{rLo=9ed2;xDO-YHtxJ$ZZAnBaumOthoBod-+CaaRPU-Q-azn1>P!$T27zyb>@d>9J+a$>fyb&G#6|qmxmNaQxY8lKaGbny?j>W{D8QH(yyHmBN*wJJ+K#<40bN7oD`UeFYU<00> z;)EA@Jc)318T~ThYFim)Y!7>93TvuBz@2w43?jK<<%-aHXrn? z5Q;lqu4i0Vf6WlJ9X;T=Ipob6@on(7_?hzJKDFuMl)lE|&&b$sIEhc58rXaAtlS(8 z-j;m1T+5mCzC}UqqzPuiS)_Zzf*7Bd(!BqDo;0=GfxGoZ{MZqD&xOh2%P$WSbEJH6 z)Ab+Q%0NOJ$Z2Qte8GhG4)cw^Qa#8sVovN$iHRS0x)eUw_G{*y`q8HEt+)JO2ewQh zeJmrPK8m{~;iveuuLA|2CV#DWK3Opcp}jZ?Wah>WKZkoLf^^se35#>I-rafRTf?UI zXVaiKWh}7L3!O^a=N&lib!2+UPFmM^UnE>QE#NeIEov(@Fk46B{=C|LqChbcY+2u$ ze9>@3?_!b6t=KOWO*@hCQe&#}9@K0ge+)l0mw4fPD8X4Q|7zxMEJ@D$W)P-dp;Sj^ zqfAw^^J_fM4KtafFS}5Gy(_e+saEIQ-%pQQX4c#Os&4mR#Z6`#&4@EoX|TQi9NGqH z{WKiEzkWkrT6&|KsDvvrds&N>C!{~f&NgVF|E)as@$7!#v2#OM`+e4VJ<$B)<~4l~ z@TsMJPx}7%PBB`eJ=V+KMs>ctaFP7HdqM>$Go7uR`&``+g=%&!ph4;}O>O?FIf2C_ zM=-H9I;BiN@gw@XD*4?dswc9Xi~RCgORTO+FK;}R*;x}zYEFE85u?Mzu7>c*+t zv;(#a2PQvSnuVu$pDd-XKnj~G>2D75`SWw`^J4Fz(JP>0)^S;y3G5f@(~A&>>e_gD zm^T0UxoOhg^T?mbdFMm{#R@Eq^&D#N@xAs02qEzLPVg)^n^N=WXR_%DhxN302Xs8k zHG-mp_$wQpP1d|A)*3G0H{iMJYE-!}DC8f(r^=JOAiz|9rn)@`F?-%2KKI`7eV$!R z^aQA91WW&TQh*RG6C?P8dHfNfx+9}FGaS)guFs9JEns1cH3d$lCh;MdWm%OY9MF_s zX{=XBTD8;fnAF{BmKRYD9F~w&8wICyxQbDP!7LN+4K~rd9GY@*6yK)=>vKr!)lSn zVSiX(=%O1 z(uH7^4vzk2w3mjsr|Ouw*;Q3&W~5edVx=3NvsA_iE=?@+O`{Gzy`*GVHqP_T2vad` zm(0GhIMqL0J}GwlXL3hvomjT^i#?w%a;;EeCZ%T0m{*uj?T0kmm1WFgp474Ioh4#a z$aRTD({*={3V$Jl()~{3I8w2Q`&;%Dq~!tY4Gb`eP?+trWyIXAUj>U?(1{0!_ye98 z)w4iRuZPI~5xZ)|u5gdmx~_gI<0X;ugWpk|4C^_N8=qeS=0JZ7y3XHUV%2W4;@kLn zSFh06p4AIcuC?VyL=t{EJC}`%ip+Dg&tkWxH~BgN$CG7+Pw0aCJ*xNE@cF7 zl4JT3{=?Vhr4@to2poKz4g9?q7rgoN{k;8g;j7g?r>Fs9ZOlPrJrqMm~$q?@g%{g%7v z#6ygI13%z|N~G?jpo3XOhC1PDM@sVyzvwCZXr)jvmrNALNVD&ql7|cv(o9}n!Iw%g zJre|NSJoFFt3;Z@3Q1wnYog;BxR6qid{1MuBCrb^*rAa|$v!GjGnSEV{Y0kY;`m$| zQ(;#FVp6XlVY#s!>9#Uo@Faa&lX*epho#n@G$Y_Tv)!HE_1rYC&W29)Qdcy}fDmJ4 zb*^MuMzs5t|{PN6bDZV?Io{sHY)!yx~*LSQeE}`kGPU zQEM{s>hlIY-{}Ccx4N9G_PC8Od70QYqFOkMP+hP*Po`T!cZ3Ja5d1vDjzHw$$eB({ zx#mu@AXzBC0dqn?0xVJcGhW&}R7zO!B|_ZKZ?U4}~I5zVMu9eK~S3QnF}o!)Wc zpO+V!-mHmF4;xl!#F#?kojZm4qimMeu}i5Wtc$`CG!=#}DBM+M8AEzvoEMhwBS#w) zx$caIV$sT+jBJ@l*>P>nDdR|}eDiDHm8KB=@zwTJ&_`e^;h;!4A4ekz58x-6^rZG+m@|b0S`r`IO=)ucP zN)Xg)$XALvb{*m;z*Y60KwKjBws2XzTBD|Gbq4H~kaFy@6=x6&8TaB|6bd=cz}&De zIo1&JR_8~}I6l?Qjk6WJ>+xv_N3fg6zYF5GKvJZNSYNL%6ydH6x3N)0ta|cPvsPQq zIbmykhxQLrKpcB^Of{*Bmp?TEu&=&@bZ-oA$>gk`Kaz8W^p|AEfLmYj7KLmsVnPA; zu-YNL5=X7B=RW&9@v^b|GV6>dcP^)pKitS~6*A!|KJP|kn$%+O@w(iki}~KI__L5K z=OY)D@bN*~{o>qKcR>kc;5OAM=G2J6gVyEB_|^TEeeYF0$49DWJRF({`RHStvazr$ z4%|%~ev~st1Ua+izdJ#UDPPO?^1iKfJ^&{rJfsRjqIh4{l%qX zm5Z#g0KSq%@4q1@>*2x%AlHi zQ=8chTteK><^5FSAzAqS1EYQ)TsV zFmGKx!SUMSgwlHfTz-YHREBb2v2HwyS~RI8=XFYJht`5CVV@_~GWY3{c> z7hAS{IeKG#9M7lL>O0Yt)iioGO4)s?wjf{kC_w-&q}NiYU$Ck#3nFX|*Q~o(Vr>oA zV&Y9-UXdC&*_K$@hGSz)E*V9q90ufi_L1lJ4blsz*Wg8?BA) zB;Y4kb}?kx>i9(@p+Z=(oek#bTv-K3IQ`6hmGw)$U6T$l8~>RH1<*({b48t(0r6oB zvf+NlKb)N7D5ij{(`@i}A+T*OXkZ_`PY{O0Hua~+Fo>wSrQa0;Pf-0!lF}ACp{tOR zjsy794AB0KU6drRk~z;Nf)87slYfLA>vmKOeWG|>5HV}2Jq<}!ZI#pS8su~wrP^Hn zCwG*J@uOkDtDepU(Uh3oB$;NNRHaa}DrD8U{y%cl2oQ^&ML%CKP4qF)Y`g5b^s(<#9fj zGmH||h?YpmCVgD0Kc2FwXOVRJxgE-?A0sT^t6MI-EWS|viw$QXgkyZk-H5j(@4`vE z{@`bSQs@rs8o$oaxaZn?3n6bKuizsl$Lq6pna4W!vgFT|F28a2vv_I93slEmoIQjS z;yJ0uN1CCZ-RnF!UK}Mgwn?$rLS2ptZ%$ZY$K5fyANF_}E`NhJ*woj}JUI;qdz|?F z&pBF{CGo6zw7{TxoDH&0wPY(6@Njam0iw>1Xxq9d+k8s`sjFlV!XYz<5$t#mE} ze~Hf#*SaT`R>1osc}FXH<;c6`^w=4ND#=^kD~YW7fCc=&cjs2-S;Ip|v>|-qJGA_p z*y=ci8#c93EqV6fa|ZjZ&j4E=>eQ7N}x3KR$wdYVvGUDUKK~_&jIbS%}UfuiYSIk02HM z-^X}Hj-l0jjaIf(N6YihpB9Gi;eQ>L^U%)mm&vWN8qn98_W#~=uT~6JaF&v8nm11Z za!{CNdD>Ts!gN`C!e}c@U(uTkXz9rtUd%u?CUw{I=>7N60vy9Z-QzT&M5F4mZE;G5 zZ(F{-n!|Ok-nE>4l};Oe!fD#|OKQz+Qiv_W3_E?MH=r-ECIqT7Xw7XW`x6#c@iZda z31;b<9gh1+ebIThC74|wR}1cEi`Wn)MI@WsYj?w8IeX`1Bp7|~nHd}cWVb!oL|K^5 zvYZzL2Lu@GsWl!Io5|lLpT#^H5Cu|V$r-H;dAd`bZ$`X%B*asg5<3u@6;%6*X zx^WV#6Bj5*DE4oax$*2&B|=BPvZUiYvNSCeQUQ8hMX5=jh3~2HrWE+;65R7yXFDrO z286BjEf5|Ky;Nl#XdWg+6b)&-y^|w}LJY2-D!>0|>{~vV@^biF#<}Rv6kLx=dxNKT zf9k@HUeRxn9w&I~H)SOZrEbVQ5h_LbuwI7qnC4pf6WKub$kTGU8Lq%?Ax_T49wD0O zsaNh1AfI&Ks5P}tW;$`7s<;r-P!D~@c<-+?r1n*fG5gvnJAfrzf__YKHgjB7Gc8G7 zWieuBrB-XtSudUcSVY$l>DzOUw)o-AH}-x1h;xQQJJv zz5aXYY$U!+;*@DFh?LvpYxKPV@2ntM(UuwS6)R|%Q*^$UU`gG)B7H0S)$JK#uvzt_ z>9esY6N%cog+c;TWGz41MlYSO5xK^a>Mv#uKgFl1>*?qao$7`2yorSIVvuqcm0%V&h8h>| zoQD{r*C}emWs7!6yVp|*sC5Aq!w=6zLX=)b}S>>xN6rh(*9DFYwLbe6C-2> zp731jFWQNp=}y@;iED!3WzSJ|&BFRyadPKP{OMT7DuLL1Q zB_fS}Zj-`s_B8SjsC3)q2Rk>eaV>YvSPPL^XGbt&OTlU@9GV=vq_tLAQ;zigCDS=G zFRsK=>_yvwVu=m%KE8=kSIIfQhx`#9NydPAU`QKo5ID_y`ti{&Ws8}`tV%GyqG#Qo zry~ktr2N;H<80!mLQcDgWEpMQ60j-i>@*8~%U5%m^nSXm_mnZuV%BU=-{BSwyWKFx zCK$X4?s9n>VfL>MYOIRmo!|S6&cWZ%N^xl;Oksvv;l(I5Z&#W?cx@D|CRomlLKp6@ zvz_pejIn{`N3h;(jp>IA?z&ap>?onzO*_u_JxC;RNk;_OS^E&=9b~H3HpfFl~EAwt!w3o)%%R^mOZHB(%|E^V)i}-g}$N5y3Pb ze%=!WpN^Cc(Eia9XT{DXPhoKEI-r4cXs2$uvUkDezs1ky1Op+rZx=G%t*k1A_M4Jd zOJ9SFz+Gc>V&y^o5mVUT!ApCc{hj;iV30CKuQFM&Ahll#C-L?~F>!MTitJDDd<)c- zM_R#L0}IY6nPm@-bjD9t`JL7mX8_Ge3ASe%0e$1~(ek+H^v&KjhzEQgl?n z{ze1wEMJ5XZRC9SFPA<@j}O#bLrnQklxJIl=Q>Z3(As$whqWkz5(jPN1DhqeDic&& zhfo@xIc}iN+(~it#)f{=dIqUV>S0F}lqjPLH9lfd?7~*2CCPLtjv})nmLhlvqv7cOgFyoxIYcbX@$zYx{>k|K_iui2LXtQpxH0V*& z=tmEMX8o0lqt2X{Q4pZ+y2M%jcj+C{y45S=A~#dZv~@@H7Z# z(-0Ux7*~gx{6AG=7y&1!9Hv447-1-nJtv~I2rolh`MQ8J2Ezh585jxt@bILPKe~QF zD*e=3cDj+{lF)c*d(yGG8AbiD1g#O^knJ;w2u{?d!m`I?$k32sy9qgXw_=tF10M{Q zPGe)P1Z`XWiWQ9sTmOPhruww~#>F`xcG86%KnPxpiN*5%A!G@xmeJ6I<;K?bpslh`6~7g`?nP12(B)?;(Xdj!cLIq1`=Tl~yVENdPV2 z0^wqALbAtDLy)l|RBf0vqOoJ}w|m)au;6sb6KuK4HzuzoT=aP%r!fLZ+*5*G_En5-Y! z8WJ)kvgf=z&3qsjDtr9r5YrHa1*5Rfu}C-^MJmW$WDt1#UTP9bBokNaWdX6SF%^d6 z%BqwSxb$)?HDCPrT;8HDSZY%N(J)9rK^1%uuTj`sEVzdea>xKQeCaej!Y3*ue`594 zUQxV+S!y>|A_#~tz!#jH-j#^|%>!#7$PoP|*mdsNS-Rv@g|hdpZC&JYLC=kMnIr ze%pYGca=r~Mgv@UEHN3^@L|d=-e59&`k9t<2PaDoFk^VfdZ%g$g(m}XF?5J}s0k*f zQr6j0j0qxE90?dveQC*{&w}#Q4fmkzWK`~pmU~E+QpU*IpOZ195U2?nLYE~dk|gaO z!8>fDt{L}&WltZLSYm}Mt5rkF1YKLSf$Gq_o3ekdyLs8QG#p@ZC)gtqmr1LIAf=!) zYI8i8fkT1#rI!s3TMfnfr})w+v6}_Z_Tfk3Q2mwzkwLKc4|4fOf_TL zBx0VIBHfs-_+?iMDwT{`=fIN1$!>F+<)-@U)}$OW)zvACmZ`hw`~>Y6MQk4T3OZ01 zeMTara0(NZo_(ifyTDXL@mSuAf;f_NI9iDDtgh<@Mf?02%4+kbQo5cCJGHlFwS98E+(`vNXl23o$OPnv{!o@Gmvxg4&U`bSXG6(5|Y+G#B|h z>M>e%)^WDQ6{P^#tCwbQeg%eum^nB6 z*Che{uWE^`FrWXALaIY{fhjyZC=``u$664p&KU7HE>jb>yoB;nvM`cI%}Q1mYh1>v zZLgFSEF+rjp09kQ`hF?Py7)?tzW4rEW2K{oqg=}@bs@AxL(_>ogAGA34Oe{fH5S1K5lq6`k0dQ*F!2F=&?Q99pm1rY~Lh$kny&nw%(guBA1aLt#qOjZViP zM(A4aht3A!mJL4g28ayt<%cC485o9}+kU<5E6EyBKJRJK?Jij{`MSP8y1KqsmMj6U zYO8+dU(?S_O-UvulfeK0C)qA;HhzZapscK{iDcwbpnyK^lg+k`rL1U?v8kzOGAXG< z0KjpETchxAvn{d8EV0r`HPZ?;!U{FA_z$Bhq2?#2+ckEY#+SndBfb6+{*cJJ#!DLD zh=%%Qvs&6#)P0Dg*)?)mol@P90P+{j8|dy0k@Vdt2cv%f$?-2-Ey0-&uPB82-RJBS zmcZeD6e;f5Y6FYyyJnqKV>l(#h-4yCdsB#l1R}oRzJ0(h?Y2wXmLHZPq&5*QE_mV~ zdjjsJQ<(x*ppgA>H=j)Y@{7=hpg0<(8msJ4+j{&c%wlt`YXdw|vKnr3bh$G$wE(J=WPXnk*>bk51=2y4^nt@o4csiflT{)int1Uj6Tc>R7ZoSP1&B-m zLaF0K`H&-_$m-8ck9mc95a{2GwFbwh^DOhiFPiGRzuf8@dqr>{wp;0M-muE}!jLQ~ zuG8urO&Lqg&1*+3t*l?%+fuT#VE%Gq^)i{ra&Hy`t&iVdxs7+^S5?46WoL*K?xtn@Xt z2-?p%jgPoLQrb-6gTOhDODGz3SLrby?d!VOGPCx>-?d}bt&gS$5-#$Pa; z6)c|AB%1{suA>jb;t!07mAoK`o{z4H>Co#35`xlbMv2|OmYy5Fi5^xvt7=jvW%xW# z@N`Vu(1C3?gA*Z}1;&dcS?H^Ho$bCdKYVe9TMO!FvQ5BXif9Xkd5b6?3XXj;o8 z)h3%rgPLdZWXAmV*Y&1BLGCPfvcNPpe6ZL>2(=A8v3_-1&~QT61}j^Cn6`r3w>{Ij zth%B6E<537*a$OC@p|MEoFk3Ty_ln~Y}QzI_fMz(PFZ@E&ez-GUi%;h8D!l+&REzM z3Haq@esLeu*&@~0zY$<~={Cg&IuQPj-@lno@f5s>_WaJ5-kVN=IgdV|e*^wdxv;3& zp}Bei!kKc}kkC=_rE@I(=6i zwC6Dx$cP|f!6Jc?!U^itKhhL3T0E6zIS(+ZVer}5d*|k3VpiO;c~wiXe*X$lEiPNXPhHKmHIr2+hn*yd7<1V;U)42M5bdfiO#Oy ziOzCnE`fq9@|O>d7Z4u=Injf1As!c~SuE~lnI z+2s$q*GXC)4dTu$A>?&8@S)RlG$?C_e76!9`0lF~fBRGTem560A=jFC8)czPaM>-v zy7%xUabYgo60M*ZbP05~*unp~h9X_nSt-k(uhnlP83jIh@kw`ivg6=?%vhhAY^45H z@NIfLJ8k~JyonRwbGzl0kpDSpe2@?Ub{h|ye?Q))F}{`pZw0j9dlkmws?hYNeG`VH8lAy@PM2~Ldvw7N$?xuaoB5SzmrzufaDkm(AS z3*YUiRDk=2w(4tDkoe4bE+>SEa-8v1SPuBURl&sX2a9$7^wUw`J#xbk7RR=*V=GdG z#R|Sl0FMX-HQGP9{ZVHI)k(htg!_kYJ)?371p7xzIp(?E+*MM7I?pMP51X)Tphu@Y zp+g`(Y2^E|*{pQfW8rsDIQA}d^HliPr;OVTMGSa39pcUO>h#JAcJ(&;&GZ|B zZ)FID>?88&4ijJx`!h822_^iY`rt*lE-V>rOZ^vNC`t8RMb}RCbG7px9B%596N8{dvYls+xY6)idwfgmEn&iH$s`Z9IS~c}&^RpY} zFaJ$l4~sIns?EWtsM6x=wuScgMlKiL=Qzgw^AU_T{X{3`=u+~EUl)JTeZ~7~R84c- z#${4<_&s*}jZbgI`FwwhJ=ZsXSF)<;hwvZCY3^^V9|AKaDyP#A8|>~~F2brcnxiy( zmn!eLIi8I_1#x0}%2l#_4EF_vZHH@?;k#H;SyA+6CQH$5`tK#YWmFM{HrqSMhW zRj-_w`i_jm4+TrVJ3pfBq^4#_1N(}Jx8>GqeSej?m%Nt>S(&1$L;FdE*gZnbLu+@PNf)6lXaZb+MyX7^oz zjN&AHGix@0Q*EOv&?{-td@TBYmUjkfm3IaZliTo7cX)Pzm(xI zHfBiYv&`|}VWXj+&P|A~@oC(#m91QIuNF|SFbR|;oyC6RN;G!Zht|-g0jRwfa=f%8Z`5^w#DNg|3VFcLp5%vLgh? zEUqfZu-beY3J?qYURl}EiC#f6V3TQ^f1}il4MVeJ-jTGSv{eYeJSv+kwJwUeSz*T- zsC^d?1X;;}0KiSDo8;b7RuB&d_F<~9$H1Q@(t{>0ETF&NYxgFlFCRhxj%WEYg+p+d z2-wsnX6`Q!6wX}txeUb1Up)M#sG4|Ny)p^9~>J*?P|#j0)&3d^MJGgj76kr{n!)7pHG@ zg`UsXPDS{XoC^Q6auWwV&dkm36phfP(d`ZM2Q5nYBBjhtvQAQFiQE$*w)DjI@3gHo_ zAc@H?#sg*-(PjdfCm?(RqdQMRKutD9!+ zBNyAGBa;CJb-FU_r7;yTMWL5d8GBx@S zKvJpBks{k1)bW@i-dX9*y8$`DEkkQk$ZLreG{zB<=CmSMK0^KqzC`JW?0~PXPr*eg z_JJhC*h_I+T*mQZNf$YPy%7^VnwoY_#MOqv60m@ZJJ#PxItcX&Tfxnqp4pMA(9{w_ zt=cHTps%_3K(MQBNC;b1ZsGD~8OV%Ow6H=|1r{cu2f`1sA_F6p#h1#|dJmJVUiO;s z5Z)&_@WC-ZSPUVK$sPeyRd4p!%}|a`^$K!1@tN3lg4DssAqEd&QKwe&?Yv`s8&>*I z^ZgoEd9nkJaF|yNLg=B%Xr>X$r7L-vhm@G8p0{NNdU7G<5Mvmk__^?v81vtAArmX# z4|uZcSw??nU0FwBm^pHC-7nP;(rAHG$=}n2ptG_Ii};PrS$usgw`+yWZ_T2AslnlX zJwTZ*hNG+UeW0f75bsS24$B|345EKGU9ZX|?_m-Q{ekh2s` zsIHG%7a2I`FW}7UcB6+O=iMRav(4KZcK!}K|FOtv~ z@KR{UcCT{pkiXN}q{Tu`PB-V-ve%&atG26KQClctcERm9|gk5=ZKKw=aFHhcwJ8$P1E^%r&TAToHsHjuDw{ZlNJDiMwLl)M2t!}(hl zkW&0f(>{I2>CWH3_?WB(T69(|$9Ln=j)B1iNpKi%uUm!&pi`KPUBg2ZQox~jZ{q|y zb;VLRZ>db1QepvN3y2C1^sh1`LmJa9sFp9Y!_azsF|xf{%6Fe<_pt^3?6Smk)L6PE zLs%}`gYvhxM!WH)7w3JVkLY(v6r@|VcXDmq(Kp=_Sl?HVl)nQT7(;E?`}r>-~fMyN#mF(-qOxJ00D>{JeI$k`@Y z?Slpg%;&xp2_~m&FBIo_KeYV1*gT^81S3r-pcd~_xkzGF6@iuW+ghZounK={eEX+S z-*4HPg2;A!{^X~J4dXJz6*z)Oq*Nr^96f1@MWybJ>Pu~y^v2Cq?cms&$xw`tl$>SMXSh3)M5ib#P;p8kSu7 zjV(bXh48R#R9ivQO(4VH;k(SH;UB1}>*yegBUed?ACQw<#4mB5nD{d8rjh2K$`7?%h{%q?&HI3-YR^K>arB($$SxcECtSsOZ(sVff@-y%m`(t=qhV>{IbzphN1h-C50s?-~GA@_zw;f-ey6N7<3 z5LX|0H1oY)fL&U5iZ1z_?{MSSHuU^!>oh-Mdn+otR1E$(K3{1NrfRvY_@eQW^SD&i zj6!wMmbQ-bYSwARy7f;FX#`%}l>X}1<2)VQ)j~I*K)%4i$V^FT${ZaVf~>;FK9frP!G()biXK)?i2^0dv*x@i-hlDl+u!554g|W2|+`2Mf?dY%F=OC z;1kP%UaJm_e!{<-6>f8j`{`x;Szb|ya`1G8ZL%jqTu&Sz`#iPH?G*?z=*LWO$Mb`2-c7=IT#S}6-+H{G$u?u)drBg*#FjX)ph|1_a3)r^bvWQn0 zW&`SNT&UM(!7n;}DQ0#X&rmc~TfA^lj^4?Qnp{KVbdIHU2x|N0+~Brb>AaL_=yXRi z%OB^01>&=6Ucy(%hy4!#CqUT0TgCTtB!7dUTVhfHx9on!hW)f$Dd`qLHKrh$jSm#w! zSy2TZ+~iSJ@8)b&eNwyC3vsn2qAICR46#wPUWszd?&IDz17dVuU3QA##HX9?-QP*>*Pz+>;MXAU4XdY9#>F3$OY~XM%0e$P3r3C6*N~(|j*|pt7cQ#|&O}P{4ZR$2PCxl~ zcN_e|a#89%h{xz@?G@a?TE;riZth5l(xx-3eJP!v)sH+$gSK}nF3-u;sfT>)mJKj8(IO>(JyVjUcVkpWgnlO)ru~`-3N=rN+la-8a!q*b7cG@lGe~+NwW2H}(TZ zWNtIxWZ4^=|87A&gDjZ=Za2(W-aCEi;pvk|PYAAMQ`_ncQG{0ewmkinfq@H7ABQOJ{x^g)8}g5uIe1bjYF%m zsoxTjJFl@)T4^mc41YzWHmWp4VdbWsM+)Hu$d-c!UF~3UFbwUNOCopUO)-VxF2^`C za1LkOdBp9qwE|UbV?s4pm)EDogf;lFhWWYALew#Xjso;fp7jXIRBxf}b)(@=wwtq> zBC3cB;YMf63cGVwrX0u?2AuaTX(uc6y*<{($+tlWc42kOeaOC%g(bfZU_m=N<(pAR zqfgQ-eg>o1oL7MPWytvghUaIVUw&dsI=6Lu`{eEJ=RMQAotK>#Qg>fXI&|A*lIq7_ zm-%nuP7Uo5y3w}r(1&jfi+N778I@yfeiwp=;QO^TuqvVu8v&r>0@wJ_+pAxmuKj4w zFX=|cl-ZZ>mQ&tCo1912ombk$0jCok<)cJiJ&Jbirs4UQH=L0_Cm#Pd0TLajo~cSM zz-qR3ahQb%BZS#=I87Ox2}{Nbt7GYQb77Og>t`HBQMD77UgY-le5fj3wbY#3S#YGh zSuvcTD1;H=bVf!^1hdPxzBx)SN$9r9MO6-N{jC9(J^@a%s$PEpebYAwZU@$0b>_cv zI1Kf8e-nzjZ(WExHY(OvZz<|dt}nX9tE(l@@Xs8E*MCMgfxo?vwmX#jbXFpd=UdKt zvNkIIt_G`eJCwH#d@bH=YmkKA-4w{+?h%mY;FK0S5zUoVShj?<6(f(acdcP2ASjRIx(od501on5CbzjB(_-h zC4!VLKR`gned*t4XV>ARr98Ot@Lzx7J|W$=1}CCUt52!~e-BVNdZ_O|p4!KX=(Q_J zjnicJ$EE7O{NYfRTB!iuc1?*9Gd@nU2)mX<;xYU0vB8&tj!OqqcRDY-tQ-Ts6n7MA z$r0kuk&V1lXj3pr&MDFIhRn?w$;98t5m9jsbb|hn^GH{&*f@0X!b0u zo^>37r%GDS@rI-1KtqSMF=ouD#luVl*HS1IXXhPEO{;|A@hV%jEZ;;f4NOV_P7*dhRgiv6rao$=gyLZ-vDWRKeNBb4>3)paz=TGNVZgL6tR%-tzqE0g zUqtG+*CpP_Nv61wlvll0pt#x5kor&0o$ZI?Q_91N+^LAobVJ2aWA>0tIUaUd(NsAB z2=;kea1|Va6Y88z8@)}b_xZ}A z0@au*`>bs>s>)}xvH&1uEmzgK_u8A-Z%5zxoY=+b^v_QtXrYuPZ<+^bmF*Oz8qLTb zkGz=9iD=O(8t?~wfisVvzke$A@7~+n51LCVC^6}u!zBS5 zNd5Mb%RH)-Eo~(xPh}4&vX6vc%`jCC*D8l(snSoDEJeK@WqF>oWVEQTra~;9j(ej1HW7 zNZ5^N&t@Qahygd0KIiB$PN5G879BclPBq`ll4MwAAqMtY7b^NjXyE3gaRHx`Up2x( zMAM3*6z%Ue+qHUr^vaONYf8#1U(d|G)M}u=?z`~;sgY9*cm*6{R*>{hw ze$6>hkTWRC?BBmGHB=t1RSb!82P4m<*VYbztnuRU^>tmP{07(X+?tx6D2`@QN<44h zrN6PEJ&kVAbnBSyBzYsi!}?|GzD)pmTebn$En4L%1}9iWo|qYTx=;Y;fWRKl&)tK6 z{^Ev>?R}cKC}tzm_6^h>Jp%UjqrmzfN(QiL*^Yp}hUm@%RGeo{ItXe!n4I`C5ScjNP_e0Uv#H-cH>3Jg|8x zXDlOcEb@Ys7ulj=N>!s!gXssdu5u2T-$ecn9!puZ&~U{ag#4iYX4PC&L5s<_Z=K0$ z@elv6$^p&MjZC^#BU{ph̍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 diff --git a/assets/inter-italic-vietnamese.6ce511fb.woff2 b/assets/inter-italic-vietnamese.6ce511fb.woff2 deleted file mode 100644 index e4f788ee02bb687bc1d5045483ff0d381e7654e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8784 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 G0002QVTgqQ diff --git a/assets/inter-italic-vietnamese.BSbpV94h.woff2 b/assets/inter-italic-vietnamese.BSbpV94h.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1eec0775a64a8fffc1fe071d33705646708e47c5 GIT binary patch literal 14884 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�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