├── LICENSE ├── README.md ├── client ├── Cargo.toml ├── Dockerfile ├── Dockerfile.amd64 ├── Dockerfile.arm64 ├── build.rs ├── cloudpub.py ├── entrypoint.sh ├── locales │ ├── en.ftl │ └── ru.ftl └── src │ ├── base.rs │ ├── client.rs │ ├── commands.rs │ ├── config.rs │ ├── i18n.rs │ ├── lib.rs │ ├── main.rs │ ├── ping.rs │ ├── plugins │ ├── httpd.rs │ ├── minecraft │ │ ├── mod.rs │ │ └── server.properties │ ├── mod.rs │ ├── onec │ │ ├── default.vrd │ │ ├── httpd.conf │ │ └── mod.rs │ ├── plugin_trait.rs │ ├── registry.rs │ └── webdav │ │ ├── httpd.conf │ │ └── mod.rs │ ├── service │ ├── linux.rs │ ├── macos.rs │ ├── mod.rs │ └── windows.rs │ └── shell.rs ├── common ├── Cargo.toml ├── build.rs ├── roots │ └── GlobalSign_GCC_R3_DV_TLS_CA_2020.pem └── src │ ├── config.rs │ ├── constants.rs │ ├── lib.rs │ ├── logging.rs │ ├── protocol.proto │ ├── protocol.rs │ ├── transport │ ├── mod.rs │ ├── rustls.rs │ ├── tcp.rs │ └── websocket.rs │ ├── utils.rs │ └── version.rs └── docs ├── build ├── .nojekyll ├── 404.html ├── 404.html.gz ├── assets │ ├── css │ │ ├── styles.2d00718a.css │ │ └── styles.2d00718a.css.gz │ ├── images │ │ ├── login-form-94cccf4ab4f59c8714e77715927a58a4.png │ │ └── publication-0ae3de0a51e8cd4aebfe9362436ad7d0.png │ └── js │ │ ├── 0e384e19.4874dedf.js │ │ ├── 0e384e19.4874dedf.js.gz │ │ ├── 11b43341.83a6c715.js │ │ ├── 11b43341.83a6c715.js.gz │ │ ├── 151.1ec91b9d.js │ │ ├── 151.1ec91b9d.js.LICENSE.txt │ │ ├── 151.1ec91b9d.js.LICENSE.txt.gz │ │ ├── 151.1ec91b9d.js.gz │ │ ├── 17896441.152c9fe7.js │ │ ├── 17896441.152c9fe7.js.gz │ │ ├── 1a20bc57.049e6787.js │ │ ├── 1a20bc57.049e6787.js.gz │ │ ├── 1b70f4c4.e5d9cf89.js │ │ ├── 1b70f4c4.e5d9cf89.js.gz │ │ ├── 254e54e8.17d8720b.js │ │ ├── 254e54e8.17d8720b.js.gz │ │ ├── 35408621.f546a790.js │ │ ├── 35408621.f546a790.js.gz │ │ ├── 42.0b64ebc5.js │ │ ├── 42.0b64ebc5.js.gz │ │ ├── 5e95c892.b907de86.js │ │ ├── 5e95c892.b907de86.js.gz │ │ ├── 913.1a07e874.js │ │ ├── 913.1a07e874.js.gz │ │ ├── 93234bd6.a62a19f9.js │ │ ├── 93234bd6.a62a19f9.js.gz │ │ ├── 9beb87c2.aa6ff69e.js │ │ ├── 9beb87c2.aa6ff69e.js.gz │ │ ├── 9f70d1c7.2d8489aa.js │ │ ├── 9f70d1c7.2d8489aa.js.gz │ │ ├── a7bd4aaa.ee424588.js │ │ ├── a7bd4aaa.ee424588.js.gz │ │ ├── a94703ab.892c3022.js │ │ ├── a94703ab.892c3022.js.gz │ │ ├── aba21aa0.9d11f6df.js │ │ ├── aba21aa0.9d11f6df.js.gz │ │ ├── cb769c5c.368c60a9.js │ │ ├── cb769c5c.368c60a9.js.gz │ │ ├── e228af67.92e2af36.js │ │ ├── e228af67.92e2af36.js.gz │ │ ├── main.34e78845.js │ │ ├── main.34e78845.js.LICENSE.txt │ │ ├── main.34e78845.js.LICENSE.txt.gz │ │ ├── main.34e78845.js.gz │ │ ├── runtime~main.da02a9a5.js │ │ └── runtime~main.da02a9a5.js.gz ├── auth │ ├── index.html │ └── index.html.gz ├── changelog │ ├── index.html │ └── index.html.gz ├── cli │ ├── index.html │ └── index.html.gz ├── docker │ ├── index.html │ └── index.html.gz ├── http │ ├── index.html │ └── index.html.gz ├── img │ ├── 1c-publish0.png │ ├── 1c-publish1.png │ ├── 1c-publish2.png │ ├── 1c-publish3.png │ ├── 1c-publish4.png │ ├── 1c-server.jpg │ ├── 1c-server.png │ ├── card1.png │ ├── card2.png │ ├── card3.png │ ├── card4.png │ ├── card5.png │ ├── clouds.jpeg │ ├── django_logo.png │ ├── django_publish.png │ ├── favicon.ico │ ├── inspector.png │ ├── login-form.png │ ├── logo.svg │ ├── logo.svg.gz │ ├── minecraft-server.jpg │ ├── publication.png │ ├── publish-cam.png │ ├── rich-gui.png │ ├── rtsp.jpg │ ├── tunnel.jpeg │ ├── view-cam.png │ └── welcome.png ├── index.html ├── index.html.gz ├── minecraft │ ├── index.html │ └── index.html.gz ├── rtsp │ ├── index.html │ └── index.html.gz ├── sitemap.xml ├── tcp │ ├── index.html │ └── index.html.gz └── webdav │ ├── index.html │ └── index.html.gz ├── en ├── .env ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── auth.md │ ├── changelog.md │ ├── cli.md │ ├── docker.md │ ├── http.md │ ├── intro.md │ ├── minecraft.md │ ├── rtsp.md │ ├── tcp.md │ └── webdav.md ├── docusaurus.config.ts ├── package-lock.json ├── package.json ├── sidebars.ts ├── src │ └── css │ │ └── custom.css ├── static │ ├── .nojekyll │ └── img │ │ ├── 1c-publish0.png │ │ ├── 1c-publish1.png │ │ ├── 1c-publish2.png │ │ ├── 1c-publish3.png │ │ ├── 1c-publish4.png │ │ ├── 1c-server.jpg │ │ ├── 1c-server.png │ │ ├── card1.png │ │ ├── card2.png │ │ ├── card3.png │ │ ├── card4.png │ │ ├── card5.png │ │ ├── clouds.jpeg │ │ ├── django_logo.png │ │ ├── django_publish.png │ │ ├── favicon.ico │ │ ├── inspector.png │ │ ├── login-form.png │ │ ├── logo.svg │ │ ├── minecraft-server.jpg │ │ ├── publication.png │ │ ├── publish-cam.png │ │ ├── rich-gui.png │ │ ├── rtsp.jpg │ │ ├── tunnel.jpeg │ │ ├── view-cam.png │ │ └── welcome.png └── tsconfig.json └── ru ├── .env ├── .gitignore ├── README.md ├── babel.config.js ├── blog ├── 2024-09-01-welcome.md ├── 2024-09-30-create-tunnel.md ├── 2024-10-04-1c-publishing.md ├── 2024-10-11-minecraft.md ├── 2024-10-17-logs.md ├── 2024-11-10-version-1.2.md ├── 2024-11-25-django.md ├── 2024-12-17-version-1.3.md ├── 2025-01-30-rtsp.md └── 2025-04-09-version-1.5.md ├── docs ├── 1c.md ├── auth.md ├── changelog.md ├── cli.md ├── docker.md ├── http.md ├── intro.md ├── minecraft.md ├── rtsp.md ├── tcp.md └── webdav.md ├── docusaurus.config.ts ├── marketing └── anounce-post.md ├── package-lock.json ├── package.json ├── sidebars.ts ├── src └── css │ └── custom.css ├── static ├── .nojekyll └── img │ ├── 1c-publish0.png │ ├── 1c-publish1.png │ ├── 1c-publish2.png │ ├── 1c-publish3.png │ ├── 1c-publish4.png │ ├── 1c-server.jpg │ ├── 1c-server.png │ ├── card1.png │ ├── card2.png │ ├── card3.png │ ├── card4.png │ ├── card5.png │ ├── clouds.jpeg │ ├── django_logo.png │ ├── django_publish.png │ ├── favicon.ico │ ├── inspector.png │ ├── login-form.png │ ├── logo.svg │ ├── minecraft-server.jpg │ ├── publication.png │ ├── publish-cam.png │ ├── rich-gui.png │ ├── rtsp.jpg │ ├── tunnel.jpeg │ ├── view-cam.png │ └── welcome.png └── tsconfig.json /README.md: -------------------------------------------------------------------------------- 1 | # CloudPub 2 | 3 | Это репозиторий для клиентской части сервиса CloudPub, который является открытым и распространяется под лицензией Apache 2.0. 4 | 5 | https://cloudpub.ru 6 | 7 | [![Звезды на GitHub](https://img.shields.io/github/stars/ermak-dev/cloudpub)](https://github.com/ermak-dev/cloudpub/stargazers) 8 | [![Лицензия](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 9 | 10 | Мощный, надежный и эффективный обратный прокси для преодоления NAT, разработанный на Rust 11 | 12 | CloudPub, подобно ngrok (https://github.com/inconshreveable/ngrok), облегчает предоставление услуг устройств, находящихся за NAT, в Интернете, используя сервер с общедоступным IP-адресом. 13 | 14 | ## Что такое CloudPub 15 | 16 | CloudPub – это отечественная альтернатива известному инструменту Ngrok, представляющая собой комбинацию прокси-сервера, шлюза и туннеля в локальную сеть. Его основная задача заключается в предоставлении публичного доступа к локальным ресурсам, таким как веб-приложения, базы данных, игровые сервера и другие сервисы, запущенные на вашем компьютере или в локальной сети. 17 | 18 | ## Быстрый старт 19 | 20 | Пожалуйста, посмотрите https://cloudpub.ru/docs 21 | 22 | ## Благодарности 23 | 24 | На основе [RatHole](https://github.com/rapiz1/rathole) от [Юджиа Цяо](https://github.com/rapiz1) 25 | -------------------------------------------------------------------------------- /client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "1.7.0" 4 | edition = "2021" 5 | authors = ["Anton Ermak "] 6 | 7 | [package.metadata.winres] 8 | OriginalFilename = "clo.exe" 9 | FileDescription = "CloudPub client" 10 | ProductName = "CloudPub" 11 | 12 | [lib] 13 | name = "client" 14 | path = "src/lib.rs" 15 | 16 | [[bin]] 17 | name = "client" 18 | path = "src/main.rs" 19 | 20 | [features] 21 | default = ["plugins", "windows-service"] 22 | plugins = ["zip"] 23 | 24 | [build-dependencies] 25 | fluent = "0.16" 26 | fluent-bundle = "0.15" 27 | unic-langid = "0.9" 28 | 29 | [dependencies] 30 | common = { path = "../common", features = ["rustls"] } 31 | tracing = "0.1" 32 | tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time", "local-time"] } 33 | tokio = { version = "1", features = ["full"] } 34 | futures = "0.3" 35 | bytes = { version = "1", features = ["serde"] } 36 | clap = { version = "4.5.7", features = ["derive", "env"] } 37 | fdlimit = "0.2" 38 | serde = { version = "1.0", features = ["derive"] } 39 | anyhow = { version = "1.0" } 40 | lazy_static = "1.4" 41 | backoff = { version = "0.4", features = ["tokio"] } 42 | dirs = "3.0.2" 43 | reqwest = { default-features = false, version = "0.11", features = ["stream", "rustls-tls-manual-roots", "rustls-tls"]} 44 | indicatif = { version = "0.17.8", features = ["tokio", "improved_unicode"]} 45 | zip = { version = "2.2.1", optional = true } 46 | toml = "0.5" 47 | walkdir = { version="2.3" } 48 | uuid = { version = "1.8.0", features = ["v4"] } 49 | parking_lot = "0.12.3" 50 | hostname = "0.4.0" 51 | url = "2.5.2" 52 | xml-rs = "0.8.22" 53 | ctrlc = "3.4.5" 54 | regex = "1.11.0" 55 | machineid-rs = "1.2.4" 56 | windows-service = { version = "0.8.0", optional = true } 57 | async-trait.workspace = true 58 | rpassword = "7.4.0" 59 | 60 | # Localization 61 | fluent = "0.16" 62 | fluent-bundle = "0.15" 63 | unic-langid = "0.9" 64 | 65 | [target.'cfg(windows)'.dependencies] 66 | winreg = "0.55.0" 67 | -------------------------------------------------------------------------------- /client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim AS dev 2 | 3 | ENV HOME="/home/cloudpub" 4 | ENV NODE_VERSION=22.11.0 5 | ENV NVM_DIR=$HOME/.nvm 6 | 7 | USER root 8 | 9 | RUN mkdir -p $HOME && \ 10 | adduser cloudpub --home $HOME --shell /bin/bash && \ 11 | chown -R cloudpub:cloudpub $HOME 12 | 13 | # Base dependencies 14 | RUN apt-get update 15 | RUN apt-get install -y sudo file curl libcap2-bin libxml2 mime-support git-core 16 | 17 | # Support of i686 build 18 | RUN dpkg --add-architecture i386 && apt-get update 19 | 20 | # Common dependencie 21 | RUN apt install -y build-essential cmake 22 | 23 | # Tauri dependencies 24 | RUN apt install -y libwebkit2gtk-4.0-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev 25 | 26 | # Install ARM and i686 toolchains 27 | RUN apt install -y libc6:i386 libncurses5:i386 libstdc++6:i386 gcc-i686-linux-gnu g++-i686-linux-gnu gcc-12-multilib 28 | RUN apt install -y gcc-arm-linux-gnueabi g++-arm-linux-gnueabi 29 | RUN apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 30 | 31 | USER cloudpub:cloudpub 32 | 33 | RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 34 | 35 | RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION} 36 | RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION} 37 | RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION} 38 | 39 | ENV PATH="$PATH:$HOME/.cargo/bin:$HOME/.nvm/versions/node/v${NODE_VERSION}/bin" 40 | 41 | RUN npm install -g yarn 42 | 43 | RUN curl https://sh.rustup.rs -sSf | bash -s -- -y 44 | 45 | RUN cargo install cargo-chef 46 | 47 | # Install i686 and ARM toolchains 48 | RUN rustup target add i686-unknown-linux-musl 49 | RUN rustup target add arm-unknown-linux-musleabi 50 | RUN rustup target add armv5te-unknown-linux-musleabi 51 | RUN rustup target add aarch64-unknown-linux-musl 52 | 53 | ########################################## 54 | FROM dev AS planner 55 | COPY --chown=cloudpub:cloudpub . $HOME 56 | 57 | WORKDIR $HOME 58 | RUN cargo chef prepare --recipe-path recipe.json 59 | 60 | ########################################## 61 | FROM dev AS builder 62 | COPY --from=planner $HOME/recipe.json $HOME/recipe.json 63 | 64 | ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=/usr/bin/arm-linux-gnueabihf-gcc 65 | 66 | WORKDIR $HOME 67 | RUN cargo chef cook --bin server --release --recipe-path $HOME/recipe.json 68 | 69 | RUN cargo chef cook --bin client --profile minimal --target x86_64-unknown-linux-gnu --recipe-path $HOME/recipe.json 70 | RUN cargo chef cook --bin client --profile minimal --target i686-unknown-linux-gnu --recipe-path $HOME/recipe.json 71 | RUN cargo chef cook --bin client --profile minimal --target arm-unknown-linux-gnueabihf --recipe-path $HOME/recipe.json 72 | 73 | RUN mkdir -p $HOME/backend $HOME/frontend $HOME/docs 74 | 75 | COPY --chown=cloudpub:cloudpub frontend/package.json $HOME/frontend/package.json 76 | COPY --chown=cloudpub:cloudpub frontend/yarn.lock $HOME/frontend/yarn.lock 77 | WORKDIR $HOME/frontend 78 | RUN yarn install 79 | 80 | COPY --chown=cloudpub:cloudpub docs/package.json $HOME/docs/package.json 81 | COPY --chown=cloudpub:cloudpub docs/package-lock.json $HOME/docs/package-lock.json 82 | WORKDIR $HOME/docs 83 | RUN npm install 84 | 85 | COPY --chown=cloudpub:cloudpub backend/pyproject.toml $HOME/backend/pyproject.toml 86 | WORKDIR $HOME 87 | RUN python -m venv venv && \ 88 | . venv/bin/activate && \ 89 | cd backend && \ 90 | pip install . 91 | 92 | COPY --chown=cloudpub:cloudpub . $HOME 93 | 94 | ENV PATH="$PATH:$HOME/bin" 95 | 96 | RUN clo build clients 97 | -------------------------------------------------------------------------------- /client/Dockerfile.amd64: -------------------------------------------------------------------------------- 1 | FROM bitnami/minideb 2 | 3 | COPY artifacts/linux/x86_64/clo /clo 4 | COPY client/entrypoint.sh / 5 | 6 | RUN mkdir -p /home/cloudpub && \ 7 | adduser cloudpub --home /home/cloudpub --shell /bin/bash && \ 8 | chown -R cloudpub:cloudpub /home/cloudpub && \ 9 | chmod +x /entrypoint.sh 10 | 11 | RUN apt update 12 | 13 | RUN apt install -y libpcre3 libapr1 libaprutil1 14 | 15 | USER cloudpub:cloudpub 16 | 17 | ENTRYPOINT ["/entrypoint.sh"] 18 | -------------------------------------------------------------------------------- /client/Dockerfile.arm64: -------------------------------------------------------------------------------- 1 | FROM bitnami/minideb:latest-arm64 2 | 3 | COPY artifacts/linux/aarch64/clo /clo 4 | COPY client/entrypoint.sh / 5 | 6 | RUN mkdir -p /home/cloudpub && \ 7 | adduser cloudpub --home /home/cloudpub --shell /bin/bash && \ 8 | chown -R cloudpub:cloudpub /home/cloudpub && \ 9 | chmod +x /entrypoint.sh 10 | 11 | RUN apt update 12 | 13 | RUN apt install -y libpcre3 libapr1 libaprutil1 14 | 15 | USER cloudpub:cloudpub 16 | 17 | ENTRYPOINT ["/entrypoint.sh"] 18 | -------------------------------------------------------------------------------- /client/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::path::Path; 4 | 5 | fn main() { 6 | println!("cargo:rerun-if-changed=locales/"); 7 | println!("cargo:rustc-check-cfg=cfg(locale, values(\"ru\", \"en\"))"); 8 | 9 | let out_dir = env::var("OUT_DIR").unwrap(); 10 | let dest_path = Path::new(&out_dir).join("locale.ftl"); 11 | 12 | // Get locale from environment variable, default to "ru" 13 | let locale = env::var("NEXT_PUBLIC_LANGUAGE").unwrap_or_else(|_| "ru".to_string()); 14 | 15 | let locale_file = match locale.as_str() { 16 | "ru" => "locales/ru.ftl", 17 | "en" => "locales/en.ftl", 18 | _ => { 19 | println!( 20 | "cargo:warning=Unknown locale '{}', falling back to 'ru'", 21 | locale 22 | ); 23 | "locales/ru.ftl" 24 | } 25 | }; 26 | 27 | if Path::new(locale_file).exists() { 28 | fs::copy(locale_file, dest_path).unwrap(); 29 | } else { 30 | panic!("Locale file {} not found", locale_file); 31 | } 32 | 33 | // Set a cfg flag for the locale 34 | println!("cargo:rustc-cfg=locale=\"{}\"", locale); 35 | } 36 | -------------------------------------------------------------------------------- /client/cloudpub.py: -------------------------------------------------------------------------------- 1 | import subprocess, threading, sys, re, time 2 | 3 | def run_cloudpub(command): 4 | process = subprocess.Popen( 5 | command, 6 | stdout=subprocess.PIPE, 7 | stderr=subprocess.PIPE, 8 | text=True, 9 | shell=True, 10 | bufsize=1, 11 | ) 12 | 13 | # Variable to store the extracted URL 14 | extracted_url = [None] 15 | 16 | def monitor(stream_in, stream_out, extract_url=False): 17 | def reader(): 18 | with stream_in: 19 | for line in stream_in: 20 | stream_out.write(line) 21 | 22 | # Check for the publication message and extract URL 23 | if extract_url: 24 | match = re.search(r'.+ -> (.+)', line) 25 | if match: 26 | extracted_url[0] = match.group(1) 27 | return reader 28 | 29 | threading.Thread(target=monitor(process.stdout, sys.stdout, True), daemon=True).start() 30 | threading.Thread(target=monitor(process.stderr, sys.stderr), daemon=True).start() 31 | 32 | # Wait for the process to complete or timeout 33 | while True: 34 | if extracted_url[0]: 35 | return extracted_url[0] 36 | time.sleep(1) 37 | 38 | # Run the command and get the URL 39 | url = run_cloudpub("./clo publish http 8080") 40 | print(f"Published URL: {url}") 41 | 42 | # Wait for key press to exit 43 | input("Press Enter to exit...") 44 | -------------------------------------------------------------------------------- /client/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -n "$TOKEN" ]; then 3 | /clo set token $TOKEN 4 | fi 5 | 6 | if [ -n "$SERVER" ]; then 7 | /clo set server $SERVER 8 | fi 9 | 10 | if [ -n "$HTTP" ]; then 11 | for i in $(echo $HTTP | tr "," "\n") 12 | do 13 | echo "Add HTTP port $i" 14 | /clo register http $i 15 | done 16 | fi 17 | 18 | if [ -n "$HTTPS" ]; then 19 | for i in $(echo $HTTPS | tr "," "\n") 20 | do 21 | echo "Add HTTPS port $i" 22 | /clo register https $i 23 | done 24 | fi 25 | 26 | if [ -n "$MINECRAFT" ]; then 27 | for i in $(echo $MINECRAFT | tr "," "\n") 28 | do 29 | echo "Add MINECRAFT port $i" 30 | /clo register minecraft $i 31 | done 32 | fi 33 | 34 | if [ -n "$WEBDAV" ]; then 35 | for i in $(echo $WEBDAV | tr "," "\n") 36 | do 37 | echo "Add WEBDAV port $i" 38 | /clo register webdav $i 39 | done 40 | fi 41 | 42 | if [ -n "$TCP" ]; then 43 | for i in $(echo $TCP | tr "," "\n") 44 | do 45 | echo "Add TCP port $i" 46 | /clo register tcp $i 47 | done 48 | fi 49 | 50 | if [ -n "$UDP" ]; then 51 | for i in $(echo $UDP | tr "," "\n") 52 | do 53 | echo "Add UDP port $i" 54 | /clo register udp $i 55 | done 56 | fi 57 | 58 | /clo "$@" 59 | -------------------------------------------------------------------------------- /client/locales/en.ftl: -------------------------------------------------------------------------------- 1 | server = https://cloudpub.online 2 | # Error messages 3 | error-network = Network error, trying again. 4 | error-process-terminated = Server process was unexpectedly terminated 5 | error-auth-missing = Authorization token is missing 6 | error-measurement = Measurement error 7 | 8 | # Connection states 9 | connecting = Connecting to server... 10 | measuring-speed = Measuring connection speed... 11 | 12 | # Progress messages 13 | downloading-webserver = Downloading web server 14 | unpacking-webserver = Unpacking web server 15 | downloading-vcpp = Downloading VC++ components 16 | installing-vcpp = Installing VC++ components 17 | 18 | # Progress templates 19 | progress-files = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} files 20 | progress-files-eta = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} files ({"{"}eta{"}"}) 21 | progress-bytes = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} bytes ({"{"}eta{"}"}) 22 | 23 | # Minecraft plugin messages 24 | downloading-jdk = Downloading JDK 25 | installing-jdk = Installing JDK 26 | downloading-minecraft-server = Downloading Minecraft server 27 | error-downloading-jdk = Error downloading JDK 28 | error-unpacking-jdk = Error unpacking JDK 29 | error-copying-minecraft-server = Error copying Minecraft server: {$path} 30 | error-invalid-minecraft-jar-directory = Invalid path to Minecraft server JAR file: {$path} (directory) 31 | error-downloading-minecraft-server = Error downloading Minecraft server: {$url} 32 | error-invalid-minecraft-path = Invalid path or URL to Minecraft server: {$path} 33 | error-creating-server-directory = Error creating server directory 34 | error-creating-server-properties = Error creating server.properties 35 | error-creating-eula-file = Error creating eula.txt file 36 | error-reading-server-properties = Error reading server.properties 37 | error-writing-server-properties = Error writing server.properties 38 | error-getting-java-path = Error getting path to java 39 | 40 | # Error contexts 41 | error-downloading-webserver = Error downloading web server 42 | error-unpacking-webserver = Error unpacking web server 43 | error-downloading-vcpp = Error downloading VC++ components 44 | error-installing-vcpp = Error installing VC++ components 45 | error-setting-permissions = Error setting execution permissions 46 | error-creating-marker = Error creating marker file 47 | error-writing-httpd-conf = Error writing httpd.conf 48 | 49 | # Service messages 50 | service-published = Service published: {$endpoint} 51 | service-registered = Service registered: {$endpoint} 52 | service-stopped = Service stopped: {$guid} 53 | service-removed = Service removed: {$guid} 54 | no-registered-services = No registered services 55 | all-services-removed = All services removed 56 | 57 | # Authentication 58 | enter-email = Enter email:{" "} 59 | enter-password = Enter password:{" "} 60 | session-terminated = Session terminated, authorization token reset 61 | client-authorized = Client successfully authorized 62 | upgrade-available = New version available: {$version} 63 | 64 | # Ping statistics 65 | ping-time-percentiles = Ping time (percentiles): 66 | 67 | # Invalid formats 68 | invalid-url = Invalid URL 69 | invalid-protocol = Invalid protocol 70 | invalid-address = Invalid address: {$address} 71 | invalid-address-error = Invalid address ({$error}): {$address} 72 | port-required = Port is required for this protocol 73 | -------------------------------------------------------------------------------- /client/locales/ru.ftl: -------------------------------------------------------------------------------- 1 | server = https://cloudpub.ru 2 | # Error messages 3 | error-network = Ошибка сети, пробуем еще раз. 4 | error-process-terminated = Процесс сервера был неожиданно завершен 5 | error-auth-missing = Отсутствует токен авторизации 6 | error-measurement = Ошибка измерения 7 | 8 | # Connection states 9 | connecting = Подключение к серверу... 10 | measuring-speed = Измеряем скорость подключения... 11 | 12 | # Progress messages 13 | downloading-webserver = Загрузка веб сервера 14 | unpacking-webserver = Распаковка веб-сервера 15 | downloading-vcpp = Загрузка компонентов VC++ 16 | installing-vcpp = Установка компонентов VC++ 17 | 18 | # Progress templates 19 | progress-files = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} файлов 20 | progress-files-eta = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} файлов ({"{"}eta{"}"}) 21 | progress-bytes = [{"{"}elapsed_precise{"}"}] {"{"}bar:40.cyan/blue{"}"} {"{"}pos{"}"}/{"{"}len{"}"} байт ({"{"}eta{"}"}) 22 | 23 | # Minecraft plugin messages 24 | downloading-jdk = Загрузка JDK 25 | installing-jdk = Установка JDK 26 | downloading-minecraft-server = Загрузка сервера Minecraft 27 | error-downloading-jdk = Ошибка загрузки JDK 28 | error-unpacking-jdk = Ошибка распаковки JDK 29 | error-copying-minecraft-server = Ошибка копирования сервера Minecraft: {$path} 30 | error-invalid-minecraft-jar-directory = Неверный путь к JAR файлу сервера Minecraft: {$path} (директория) 31 | error-downloading-minecraft-server = Ошибка загрузки сервера Minecraft: {$url} 32 | error-invalid-minecraft-path = Неверный путь или URL к серверу Minecraft: {$path} 33 | error-creating-server-directory = Ошибка создания директории сервера 34 | error-creating-server-properties = Ошибка создания server.properties 35 | error-creating-eula-file = Ошибка создания файла eula.txt 36 | error-reading-server-properties = Ошибка чтения server.properties 37 | error-writing-server-properties = Ошибка записи server.properties 38 | error-getting-java-path = Ошибка получения пути к java 39 | 40 | # Error contexts 41 | error-downloading-webserver = Ошибка загрузки веб сервера 42 | error-unpacking-webserver = Ошибка распаковки веб сервера 43 | error-downloading-vcpp = Ошибка загрузки компонентов VC++ 44 | error-installing-vcpp = Ошибка установки компонентов VC++ 45 | error-setting-permissions = Ошибка установки прав на исполнение 46 | error-creating-marker = Ошибка создания файла метки 47 | error-writing-httpd-conf = Ошибка записи httpd.conf 48 | 49 | # Service messages 50 | service-published = Сервис опубликован: {$endpoint} 51 | service-registered = Сервис зарегистрирован: {$endpoint} 52 | service-stopped = Сервис остановлен: {$guid} 53 | service-removed = Сервис удален: {$guid} 54 | no-registered-services = Нет зарегистрированных сервисов 55 | all-services-removed = Все сервисы удалены 56 | 57 | # Authentication 58 | enter-email = Введите email:{" "} 59 | enter-password = Введите пароль:{" "} 60 | session-terminated = Сессия завершена, токен авторизации сброшен 61 | client-authorized = Клиент успешно авторизован 62 | upgrade-available = Доступна новая версия: {$version} 63 | 64 | # Ping statistics 65 | ping-time-percentiles = Время пинга (процентили): 66 | 67 | # Invalid formats 68 | invalid-url = Неверный URL 69 | invalid-protocol = Неверный протокол 70 | invalid-address = Неправильно указан адрес: {$address} 71 | invalid-address-error = Неправильно указан адрес ({$error}): {$address} 72 | port-required = Для этого прокола нужно указать порт 73 | -------------------------------------------------------------------------------- /client/src/i18n.rs: -------------------------------------------------------------------------------- 1 | use fluent::{FluentBundle, FluentResource}; 2 | use fluent_bundle::FluentArgs; 3 | use std::sync::Mutex; 4 | use unic_langid::LanguageIdentifier; 5 | 6 | pub struct Localizer { 7 | bundle: Mutex>, 8 | } 9 | 10 | unsafe impl Sync for Localizer {} 11 | unsafe impl Send for Localizer {} 12 | 13 | impl Default for Localizer { 14 | fn default() -> Self { 15 | Self::new() 16 | } 17 | } 18 | 19 | impl Localizer { 20 | pub fn new() -> Self { 21 | let locale_content = include_str!(concat!(env!("OUT_DIR"), "/locale.ftl")); 22 | let resource = FluentResource::try_new(locale_content.to_string()) 23 | .expect("Failed to parse locale resource"); 24 | 25 | let langid: LanguageIdentifier = if cfg!(locale = "ru") { 26 | "ru".parse().expect("Failed to parse language identifier") 27 | } else { 28 | "en".parse().expect("Failed to parse language identifier") 29 | }; 30 | 31 | let mut bundle = FluentBundle::new(vec![langid]); 32 | bundle.set_use_isolating(false); // Disable BiDi isolation 33 | bundle 34 | .add_resource(resource) 35 | .expect("Failed to add resource to bundle"); 36 | 37 | Self { 38 | bundle: Mutex::new(bundle), 39 | } 40 | } 41 | 42 | pub fn get(&self, key: &str) -> String { 43 | self.get_with_args(key, None) 44 | } 45 | 46 | pub fn get_with_args(&self, key: &str, args: Option<&FluentArgs>) -> String { 47 | let bundle = self.bundle.lock().unwrap(); 48 | let msg = bundle 49 | .get_message(key) 50 | .unwrap_or_else(|| panic!("Message '{}' not found", key)); 51 | 52 | let pattern = msg 53 | .value() 54 | .unwrap_or_else(|| panic!("Message '{}' has no value", key)); 55 | 56 | let mut errors = vec![]; 57 | let formatted = bundle.format_pattern(pattern, args, &mut errors); 58 | 59 | if !errors.is_empty() { 60 | eprintln!("Localization errors for key '{}': {:?}", key, errors); 61 | } 62 | 63 | formatted.to_string() 64 | } 65 | } 66 | 67 | lazy_static::lazy_static! { 68 | pub static ref LOCALIZER: Localizer = Localizer::new(); 69 | } 70 | 71 | // Convenience macros for localization 72 | #[macro_export] 73 | macro_rules! t { 74 | ($key:expr) => { 75 | $crate::i18n::LOCALIZER.get($key) 76 | }; 77 | ($key:expr, $($arg_key:expr => $arg_value:expr),*) => {{ 78 | let mut args = fluent_bundle::FluentArgs::new(); 79 | $( 80 | args.set($arg_key, $arg_value); 81 | )* 82 | $crate::i18n::LOCALIZER.get_with_args($key, Some(&args)) 83 | }}; 84 | } 85 | -------------------------------------------------------------------------------- /client/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use {anyhow, clap, parking_lot, serde, tokio, tracing}; 2 | 3 | pub mod base; 4 | pub mod client; 5 | pub mod commands; 6 | pub mod config; 7 | pub mod i18n; 8 | pub mod ping; 9 | #[cfg(feature = "plugins")] 10 | pub mod plugins; 11 | pub mod service; 12 | pub mod shell; 13 | -------------------------------------------------------------------------------- /client/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context, Result}; 2 | use clap::Parser; 3 | use client::base::{cli_main, init, Cli}; 4 | use tracing::error; 5 | 6 | pub fn main() -> Result<()> { 7 | // Check if we're being run as a service on Windows 8 | #[cfg(target_os = "windows")] 9 | { 10 | use std::env; 11 | if env::args().any(|arg| arg == "--run-as-service") { 12 | return client::service::run_as_service(); 13 | } 14 | } 15 | 16 | let cli = Cli::parse(); 17 | let (_guard, config) = init(&cli, false).context("Failed to initialize config")?; 18 | if let Err(err) = cli_main(cli, config) { 19 | error!("Exiting with error: {}", err); 20 | eprintln!("{}", err); 21 | std::process::exit(1); 22 | } else { 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/src/plugins/minecraft/server.properties: -------------------------------------------------------------------------------- 1 | #Minecraft server properties 2 | #Sat Oct 05 11:05:08 GMT+07:00 2024 3 | accepts-transfers=false 4 | allow-flight=false 5 | allow-nether=true 6 | broadcast-console-to-ops=true 7 | broadcast-rcon-to-ops=true 8 | bug-report-link= 9 | difficulty=easy 10 | enable-command-block=false 11 | enable-jmx-monitoring=false 12 | enable-query=false 13 | enable-rcon=false 14 | enable-status=true 15 | enforce-secure-profile=true 16 | enforce-whitelist=false 17 | entity-broadcast-range-percentage=100 18 | force-gamemode=false 19 | function-permission-level=2 20 | gamemode=survival 21 | generate-structures=true 22 | generator-settings={} 23 | hardcore=false 24 | hide-online-players=false 25 | initial-disabled-packs= 26 | initial-enabled-packs=vanilla 27 | level-name=world 28 | level-seed= 29 | level-type=minecraft\:normal 30 | log-ips=true 31 | max-chained-neighbor-updates=1000000 32 | max-players=20 33 | max-tick-time=60000 34 | max-world-size=29999984 35 | motd=A Minecraft Server 36 | network-compression-threshold=256 37 | online-mode=true 38 | op-permission-level=4 39 | player-idle-timeout=0 40 | prevent-proxy-connections=false 41 | pvp=true 42 | query.port=25565 43 | rate-limit=0 44 | rcon.password= 45 | rcon.port=25575 46 | region-file-compression=deflate 47 | require-resource-pack=false 48 | resource-pack= 49 | resource-pack-id= 50 | resource-pack-prompt= 51 | resource-pack-sha1= 52 | server-ip= 53 | server-port=25565 54 | simulation-distance=10 55 | spawn-animals=true 56 | spawn-monsters=true 57 | spawn-npcs=true 58 | spawn-protection=16 59 | sync-chunk-writes=true 60 | text-filtering-config= 61 | use-native-transport=true 62 | view-distance=10 63 | white-list=false 64 | eula=true 65 | -------------------------------------------------------------------------------- /client/src/plugins/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod httpd; 2 | pub mod minecraft; 3 | pub mod onec; 4 | pub mod plugin_trait; 5 | pub mod registry; 6 | pub mod webdav; 7 | 8 | pub use plugin_trait::Plugin; 9 | -------------------------------------------------------------------------------- /client/src/plugins/onec/default.vrd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /client/src/plugins/onec/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::config::{ClientConfig, EnvConfig, ENV_CONFIG}; 2 | use crate::plugins::httpd::{setup_httpd, start_httpd}; 3 | use crate::plugins::Plugin; 4 | use crate::shell::{find, get_cache_dir, SubProcess}; 5 | use anyhow::{bail, Context, Result}; 6 | use async_trait::async_trait; 7 | use common::protocol::message::Message; 8 | use common::protocol::ServerEndpoint; 9 | use common::utils::free_port_for_bind; 10 | use parking_lot::RwLock; 11 | use std::path::PathBuf; 12 | use std::sync::Arc; 13 | use tokio::sync::broadcast; 14 | use xml::escape::escape_str_attribute; 15 | 16 | #[cfg(target_os = "windows")] 17 | const WSAP_MODULE: &str = "wsap24.dll"; 18 | 19 | #[cfg(all(unix, debug_assertions))] 20 | const WSAP_MODULE: &str = "wsap24t.so"; 21 | 22 | #[cfg(all(unix, not(debug_assertions)))] 23 | const WSAP_MODULE: &str = "wsap24.so"; 24 | 25 | pub const ONEC_SUBDIR: &str = "1c"; 26 | const ONEC_CONFIG: &str = include_str!("httpd.conf"); 27 | const DEFAULT_VRD: &str = include_str!("default.vrd"); 28 | 29 | fn detect_platform() -> Option { 30 | for patform in ENV_CONFIG.iter() { 31 | if std::path::Path::new(&patform.1.home_1c).exists() { 32 | return Some((*patform.1).clone()); 33 | } 34 | } 35 | None 36 | } 37 | 38 | fn check_enviroment(config: Arc>) -> Result { 39 | let env = if let Some(platform) = config.read().one_c_platform.as_ref() { 40 | ENV_CONFIG.get(platform).cloned() 41 | } else { 42 | detect_platform() 43 | }; 44 | 45 | let mut env = if let Some(env) = env { 46 | env 47 | } else { 48 | bail!("Платформа 1C не найдена, укажите ее битность (x32/x64) и путь в настройках"); 49 | }; 50 | 51 | if let Some(one_c_home) = &config.read().one_c_home { 52 | env.home_1c = PathBuf::from(one_c_home); 53 | } 54 | 55 | if !std::path::Path::new(&env.home_1c).exists() { 56 | bail!( 57 | "Путь до платформы 1C ({}) не найден, укажите его в настройках", 58 | env.home_1c.to_str().unwrap() 59 | ); 60 | } 61 | Ok(env) 62 | } 63 | 64 | pub struct OneCPlugin; 65 | 66 | #[async_trait] 67 | impl Plugin for OneCPlugin { 68 | fn name(&self) -> &'static str { 69 | "onec" 70 | } 71 | 72 | async fn setup( 73 | &self, 74 | config: Arc>, 75 | command_rx: broadcast::Receiver, 76 | result_tx: broadcast::Sender, 77 | ) -> Result<()> { 78 | let env = check_enviroment(config.clone())?; 79 | setup_httpd(config, command_rx, result_tx, env).await 80 | } 81 | 82 | async fn publish( 83 | &self, 84 | endpoint: &mut ServerEndpoint, 85 | config: Arc>, 86 | result_tx: broadcast::Sender, 87 | ) -> Result { 88 | let env = check_enviroment(config.clone())?; 89 | 90 | let one_c_publish_dir = config 91 | .read() 92 | .one_c_publish_dir 93 | .as_ref() 94 | .map(PathBuf::from) 95 | .unwrap_or_else(|| get_cache_dir(ONEC_SUBDIR).unwrap()); 96 | 97 | let publish_dir = one_c_publish_dir.join(&endpoint.guid); 98 | 99 | std::fs::create_dir_all(publish_dir.clone()).context("Can't create publish dir")?; 100 | 101 | let mut default_vrd = publish_dir.clone(); 102 | default_vrd.push("default.vrd"); 103 | 104 | let wsap_error = format!( 105 | "Модуль {} на найден в {}. Проверьте настройки и убедитесь что у вас установлены модули расширения веб-сервера для 1С", WSAP_MODULE, &env.home_1c.to_str().unwrap()); 106 | 107 | let wsap = if let Some(wsap) = 108 | find(&env.home_1c, &PathBuf::from(WSAP_MODULE)).context(wsap_error.clone())? 109 | { 110 | wsap 111 | } else { 112 | bail!(wsap_error); 113 | }; 114 | 115 | let local_addr = endpoint.client.as_ref().unwrap().local_addr.clone(); 116 | // if local_addr is existing path and folder, append File= else use as is 117 | let ib = if std::path::Path::new(&local_addr).exists() { 118 | format!("File=\"{}\"", local_addr) 119 | } else { 120 | local_addr.clone() 121 | }; 122 | 123 | let vrd_config = DEFAULT_VRD.replace("[[IB]]", &escape_str_attribute(&ib)); 124 | 125 | if !default_vrd.exists() { 126 | std::fs::write(&default_vrd, vrd_config).context("Ошибка записи default.vrd")?; 127 | } 128 | 129 | let httpd_config = ONEC_CONFIG.replace("[[WSAP_MODULE]]", wsap.to_str().unwrap()); 130 | free_port_for_bind(endpoint).await?; 131 | 132 | start_httpd( 133 | endpoint, 134 | &httpd_config, 135 | ONEC_SUBDIR, 136 | publish_dir.to_str().unwrap(), 137 | env, 138 | result_tx, 139 | ) 140 | .await 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /client/src/plugins/plugin_trait.rs: -------------------------------------------------------------------------------- 1 | use crate::config::ClientConfig; 2 | use crate::shell::SubProcess; 3 | use anyhow::Result; 4 | use async_trait::async_trait; 5 | use common::protocol::message::Message; 6 | use common::protocol::ServerEndpoint; 7 | use parking_lot::RwLock; 8 | use std::sync::Arc; 9 | use tokio::sync::broadcast; 10 | 11 | #[async_trait] 12 | pub trait Plugin: Send + Sync { 13 | /// Name of the plugin 14 | fn name(&self) -> &'static str; 15 | 16 | /// Setup the plugin environment 17 | async fn setup( 18 | &self, 19 | config: Arc>, 20 | command_rx: broadcast::Receiver, 21 | result_tx: broadcast::Sender, 22 | ) -> Result<()>; 23 | 24 | /// Publish a service using this plugin 25 | async fn publish( 26 | &self, 27 | endpoint: &mut ServerEndpoint, 28 | config: Arc>, 29 | result_tx: broadcast::Sender, 30 | ) -> Result; 31 | } 32 | -------------------------------------------------------------------------------- /client/src/plugins/registry.rs: -------------------------------------------------------------------------------- 1 | use crate::plugins::{minecraft::MinecraftPlugin, onec::OneCPlugin, webdav::WebdavPlugin, Plugin}; 2 | use common::protocol::Protocol; 3 | use std::collections::HashMap; 4 | use std::sync::Arc; 5 | 6 | pub struct PluginRegistry { 7 | plugins: HashMap>, 8 | } 9 | 10 | impl Default for PluginRegistry { 11 | fn default() -> Self { 12 | Self::new() 13 | } 14 | } 15 | 16 | impl PluginRegistry { 17 | pub fn new() -> Self { 18 | let mut registry = Self { 19 | plugins: HashMap::new(), 20 | }; 21 | 22 | // Register all available plugins 23 | registry.register(Protocol::Webdav, Arc::new(WebdavPlugin)); 24 | registry.register(Protocol::OneC, Arc::new(OneCPlugin)); 25 | registry.register(Protocol::Minecraft, Arc::new(MinecraftPlugin)); 26 | 27 | registry 28 | } 29 | 30 | pub fn register(&mut self, protocol: Protocol, plugin: Arc) { 31 | self.plugins.insert(protocol, plugin); 32 | } 33 | 34 | pub fn get(&self, protocol: Protocol) -> Option> { 35 | self.plugins.get(&protocol).cloned() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /client/src/plugins/webdav/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::config::ClientConfig; 2 | use crate::plugins::httpd::{setup_httpd, start_httpd}; 3 | use crate::plugins::Plugin; 4 | use crate::shell::SubProcess; 5 | use anyhow::Result; 6 | use async_trait::async_trait; 7 | use common::protocol::message::Message; 8 | use common::protocol::ServerEndpoint; 9 | use common::utils::free_port_for_bind; 10 | use parking_lot::RwLock; 11 | use std::sync::Arc; 12 | use tokio::sync::broadcast; 13 | 14 | const WEBDAV_CONFIG: &str = include_str!("httpd.conf"); 15 | const WEBDAV_SUBDIR: &str = "webdav"; 16 | 17 | pub struct WebdavPlugin; 18 | 19 | #[async_trait] 20 | impl Plugin for WebdavPlugin { 21 | fn name(&self) -> &'static str { 22 | "webdav" 23 | } 24 | 25 | async fn setup( 26 | &self, 27 | config: Arc>, 28 | command_rx: broadcast::Receiver, 29 | result_tx: broadcast::Sender, 30 | ) -> Result<()> { 31 | setup_httpd(config, command_rx, result_tx, Default::default()).await 32 | } 33 | 34 | async fn publish( 35 | &self, 36 | endpoint: &mut ServerEndpoint, 37 | _config: Arc>, 38 | result_tx: broadcast::Sender, 39 | ) -> Result { 40 | let publish_dir = endpoint.client.as_ref().unwrap().local_addr.clone(); 41 | let env = Default::default(); 42 | 43 | free_port_for_bind(endpoint).await?; 44 | 45 | start_httpd( 46 | endpoint, 47 | WEBDAV_CONFIG, 48 | WEBDAV_SUBDIR, 49 | &publish_dir, 50 | env, 51 | result_tx, 52 | ) 53 | .await 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/src/service/linux.rs: -------------------------------------------------------------------------------- 1 | use crate::service::{ServiceConfig, ServiceManager, ServiceStatus}; 2 | use anyhow::{Context, Result}; 3 | use std::fs; 4 | use std::path::Path; 5 | use std::process::Command; 6 | 7 | pub struct LinuxServiceManager { 8 | config: ServiceConfig, 9 | } 10 | 11 | impl LinuxServiceManager { 12 | pub fn new(config: ServiceConfig) -> Self { 13 | Self { config } 14 | } 15 | 16 | fn service_file_path(&self) -> String { 17 | format!("/etc/systemd/system/{}.service", self.config.name) 18 | } 19 | 20 | fn create_service_file(&self) -> Result<()> { 21 | let executable = self.config.executable_path.to_string_lossy(); 22 | let args = self.config.args.join(" "); 23 | 24 | let service_content = format!( 25 | r#"[Unit] 26 | Description={} 27 | After=network.target 28 | 29 | [Service] 30 | Type=simple 31 | ExecStart={} {} 32 | Restart=on-failure 33 | RestartSec=5s 34 | 35 | [Install] 36 | WantedBy=multi-user.target 37 | "#, 38 | self.config.description, executable, args 39 | ); 40 | 41 | fs::write(self.service_file_path(), service_content) 42 | .context("Failed to write systemd service file") 43 | } 44 | } 45 | 46 | impl ServiceManager for LinuxServiceManager { 47 | fn install(&self) -> Result<()> { 48 | // Create the service file 49 | self.create_service_file()?; 50 | 51 | // Reload systemd to recognize the new service 52 | Command::new("systemctl") 53 | .args(["daemon-reload"]) 54 | .status() 55 | .context("Failed to reload systemd")?; 56 | 57 | // Enable the service to start on boot 58 | Command::new("systemctl") 59 | .args(["enable", &self.config.name]) 60 | .status() 61 | .context("Failed to enable service")?; 62 | 63 | Ok(()) 64 | } 65 | 66 | fn uninstall(&self) -> Result<()> { 67 | // Stop the service if it's running 68 | let _ = self.stop(); 69 | 70 | // Disable the service 71 | Command::new("systemctl") 72 | .args(["disable", &self.config.name]) 73 | .status() 74 | .context("Failed to disable service")?; 75 | 76 | // Remove the service file 77 | if Path::new(&self.service_file_path()).exists() { 78 | fs::remove_file(self.service_file_path()).context("Failed to remove service file")?; 79 | } 80 | 81 | // Reload systemd 82 | Command::new("systemctl") 83 | .args(["daemon-reload"]) 84 | .status() 85 | .context("Failed to reload systemd")?; 86 | 87 | Ok(()) 88 | } 89 | 90 | fn start(&self) -> Result<()> { 91 | Command::new("systemctl") 92 | .args(["start", &self.config.name]) 93 | .status() 94 | .context("Failed to start service")?; 95 | Ok(()) 96 | } 97 | 98 | fn stop(&self) -> Result<()> { 99 | Command::new("systemctl") 100 | .args(["stop", &self.config.name]) 101 | .status() 102 | .context("Failed to stop service")?; 103 | Ok(()) 104 | } 105 | 106 | fn status(&self) -> Result { 107 | let service_path = self.service_file_path(); 108 | let service_file = Path::new(&service_path); 109 | if !service_file.exists() { 110 | return Ok(ServiceStatus::NotInstalled); 111 | } 112 | 113 | let output = Command::new("systemctl") 114 | .args(["is-active", &self.config.name]) 115 | .output() 116 | .context("Failed to check service status")?; 117 | 118 | let status_str = String::from_utf8_lossy(&output.stdout).trim().to_string(); 119 | 120 | match status_str.as_str() { 121 | "active" => Ok(ServiceStatus::Running), 122 | "inactive" => Ok(ServiceStatus::Stopped), 123 | _ => Ok(ServiceStatus::Unknown), 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /client/src/service/macos.rs: -------------------------------------------------------------------------------- 1 | use crate::service::{ServiceConfig, ServiceManager, ServiceStatus}; 2 | use anyhow::{Context, Result}; 3 | use std::fs; 4 | use std::path::PathBuf; 5 | use std::process::Command; 6 | 7 | pub struct MacOSServiceManager { 8 | config: ServiceConfig, 9 | } 10 | 11 | impl MacOSServiceManager { 12 | pub fn new(config: ServiceConfig) -> Self { 13 | Self { config } 14 | } 15 | 16 | fn plist_path(&self) -> PathBuf { 17 | PathBuf::from(format!("/Library/LaunchDaemons/{}.plist", self.config.name)) 18 | } 19 | 20 | fn create_plist_file(&self) -> Result<()> { 21 | let executable = self.config.executable_path.to_string_lossy(); 22 | 23 | // Convert args to XML array elements 24 | let args_xml = self 25 | .config 26 | .args 27 | .iter() 28 | .map(|arg| format!("\t\t{}", arg)) 29 | .collect::>() 30 | .join("\n"); 31 | 32 | let program_args = format!("\t\t{}\n{}", executable, args_xml); 33 | 34 | let plist_content = format!( 35 | r#" 36 | 37 | 38 | 39 | Label 40 | {} 41 | ProgramArguments 42 | 43 | {} 44 | 45 | RunAtLoad 46 | 47 | KeepAlive 48 | 49 | StandardErrorPath 50 | /tmp/{}.err 51 | StandardOutPath 52 | /tmp/{}.out 53 | 54 | "#, 55 | self.config.name, program_args, self.config.name, self.config.name 56 | ); 57 | 58 | fs::write(self.plist_path(), plist_content) 59 | .context("Failed to write LaunchDaemon plist file") 60 | } 61 | } 62 | 63 | impl ServiceManager for MacOSServiceManager { 64 | fn install(&self) -> Result<()> { 65 | // Create the plist file 66 | self.create_plist_file()?; 67 | 68 | // Set the correct permissions 69 | Command::new("chmod") 70 | .args(["644", self.plist_path().to_str().unwrap()]) 71 | .status() 72 | .context("Failed to set permissions on plist file")?; 73 | 74 | // Load the service 75 | Command::new("launchctl") 76 | .args(["load", self.plist_path().to_str().unwrap()]) 77 | .status() 78 | .context("Failed to load service")?; 79 | 80 | Ok(()) 81 | } 82 | 83 | fn uninstall(&self) -> Result<()> { 84 | // Unload the service if it exists 85 | if self.plist_path().exists() { 86 | let _ = Command::new("launchctl") 87 | .args(["unload", self.plist_path().to_str().unwrap()]) 88 | .status(); 89 | } 90 | 91 | // Remove the plist file 92 | if self.plist_path().exists() { 93 | fs::remove_file(self.plist_path()).context("Failed to remove plist file")?; 94 | } 95 | 96 | Ok(()) 97 | } 98 | 99 | fn start(&self) -> Result<()> { 100 | Command::new("launchctl") 101 | .args(["start", &self.config.name]) 102 | .status() 103 | .context("Failed to start service")?; 104 | Ok(()) 105 | } 106 | 107 | fn stop(&self) -> Result<()> { 108 | Command::new("launchctl") 109 | .args(["stop", &self.config.name]) 110 | .status() 111 | .context("Failed to stop service")?; 112 | Ok(()) 113 | } 114 | 115 | fn status(&self) -> Result { 116 | if !self.plist_path().exists() { 117 | return Ok(ServiceStatus::NotInstalled); 118 | } 119 | 120 | let output = Command::new("launchctl") 121 | .args(["list"]) 122 | .output() 123 | .context("Failed to list services")?; 124 | 125 | let output_str = String::from_utf8_lossy(&output.stdout); 126 | 127 | if output_str.contains(&self.config.name) { 128 | Ok(ServiceStatus::Running) 129 | } else { 130 | Ok(ServiceStatus::Stopped) 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /client/src/service/mod.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::path::PathBuf; 3 | 4 | #[cfg(target_os = "windows")] 5 | mod windows; 6 | #[cfg(target_os = "windows")] 7 | pub use windows::*; 8 | 9 | #[cfg(target_os = "linux")] 10 | mod linux; 11 | #[cfg(target_os = "linux")] 12 | pub use linux::*; 13 | 14 | #[cfg(target_os = "macos")] 15 | mod macos; 16 | #[cfg(target_os = "macos")] 17 | pub use macos::*; 18 | 19 | // Common service trait 20 | pub trait ServiceManager { 21 | fn install(&self) -> Result<()>; 22 | fn uninstall(&self) -> Result<()>; 23 | fn start(&self) -> Result<()>; 24 | fn stop(&self) -> Result<()>; 25 | fn status(&self) -> Result; 26 | } 27 | 28 | #[allow(dead_code)] 29 | pub enum ServiceStatus { 30 | Running, 31 | Stopped, 32 | NotInstalled, 33 | Unknown, 34 | } 35 | 36 | #[allow(dead_code)] 37 | pub struct ServiceConfig { 38 | pub name: String, 39 | pub display_name: String, 40 | pub description: String, 41 | pub executable_path: PathBuf, 42 | pub args: Vec, 43 | pub config_path: Option, 44 | } 45 | 46 | pub fn create_service_manager(config: ServiceConfig) -> Box { 47 | #[cfg(target_os = "windows")] 48 | { 49 | Box::new(WindowsServiceManager::new(config)) 50 | } 51 | #[cfg(target_os = "linux")] 52 | { 53 | Box::new(LinuxServiceManager::new(config)) 54 | } 55 | #[cfg(target_os = "macos")] 56 | { 57 | Box::new(MacOSServiceManager::new(config)) 58 | } 59 | #[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "macos")))] 60 | { 61 | panic!("Unsupported platform for service management"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "common" 3 | version = "1.7.0" 4 | edition = "2021" 5 | authors = ["Anton Ermak "] 6 | description = "Common code for the client, server, and GUI" 7 | include = ["src/**/*", "build.rs"] 8 | 9 | [features] 10 | default = [] 11 | english = [] 12 | 13 | # TLS support 14 | rustls = [ 15 | "tokio-rustls", 16 | "tokio-tungstenite/rustls", 17 | "tokio-tungstenite/rustls-tls-native-roots", 18 | "rustls-pemfile", 19 | "rustls-native-certs", 20 | "p12", 21 | ] 22 | 23 | [build-dependencies] 24 | prost-build = "0.12.3" 25 | 26 | [dependencies] 27 | tokio = { version = "1", features = ["full"] } 28 | tokio-unix-tcp = { git="https://github.com/ermakus/tokio-unix-tcp.git", branch="master" } 29 | bytes = { version = "1", features = ["serde"] } 30 | clap = { version = "4.5.7", features = ["derive"] } 31 | serde = { version = "1.0", features = ["derive"] } 32 | anyhow = { version = "1.0" } 33 | bincode = "1" 34 | lazy_static = "1.4" 35 | backoff = { version = "0.4", features = ["tokio"] } 36 | rand = "0.8" 37 | prost = "0.13.5" 38 | 39 | # Server tracing 40 | tracing = "0.1" 41 | tracing-subscriber = { version = "0.3.18", features = ["env-filter", "time", "local-time"] } 42 | tracing-appender = "0.2.3" 43 | tracing-log = "0.2.0" 44 | log-panics = { version = "2", features = ["with-backtrace"]} 45 | rolling-file = "0.2.0" 46 | 47 | time = "0.3.36" 48 | socket2 = { version = "0.4", features = ["all"] } 49 | async-trait = "0.1" 50 | base64 = { version = "0.13", optional = true } 51 | notify = { version = "5.0.0-pre.13", optional = true } 52 | async-http-proxy = { version = "1.2", features = [ 53 | "runtime-tokio", 54 | "basic-auth", 55 | ] } 56 | async-socks5 = "0.5" 57 | url = { version = "2.5.4", features = ["serde"] } 58 | tokio-tungstenite = { version = "0.21.0", features = ["connect"] } 59 | tokio-util = { version = "0.7.9", features = ["io", "net"] } 60 | futures-core = { version = "0.3.28" } 61 | futures-sink = { version = "0.3.28" } 62 | serde_json = "1.0.117" 63 | 64 | tokio-rustls = { version = "0.25.0", optional = true } 65 | rustls-native-certs = { version = "0.7", optional = true } 66 | rustls-pemfile = { version = "2.0", optional = true } 67 | p12 = { version = "0.6.3", optional = true } 68 | libc = "0.2.158" 69 | parking_lot = "0.12.3" 70 | 71 | dirs = "3.0.2" 72 | urlencoding = "2.1.3" 73 | 74 | # Localization 75 | fluent = "0.16" 76 | fluent-bundle = "0.15" 77 | unic-langid = "0.9" 78 | -------------------------------------------------------------------------------- /common/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | // Tell Cargo to rerun this build script if the .proto file changes 3 | println!("cargo:rerun-if-changed=src/protocol.proto"); 4 | 5 | // Configure prost-build with experimental proto3 optional support 6 | let mut config = prost_build::Config::new(); 7 | config.protoc_arg("--experimental_allow_proto3_optional"); 8 | 9 | // Compile the .proto file 10 | config.type_attribute(".", "#[derive(serde::Serialize,serde::Deserialize)]"); 11 | config.compile_protos(&["src/protocol.proto"], &["src/"])?; 12 | 13 | // Post process the generated code 14 | let out_dir = std::env::var("OUT_DIR")?; 15 | let mut generated = std::fs::read_to_string(format!("{}/protocol.rs", out_dir))?; 16 | 17 | // Remove PartialEq from ClientEndpoint derive attributes 18 | for name in ["ClientEndpoint", "ServerEndpoint"] { 19 | generated = generated.replace( 20 | format!( 21 | "#[derive(Clone, PartialEq, ::prost::Message)] 22 | pub struct {} {{", 23 | name 24 | ) 25 | .as_str(), 26 | format!( 27 | "#[derive(Clone, ::prost::Message)] 28 | pub struct {} {{", 29 | name 30 | ) 31 | .as_str(), 32 | ); 33 | } 34 | 35 | std::fs::write(format!("{}/protocol.rs", out_dir), generated)?; 36 | 37 | Ok(()) 38 | } 39 | -------------------------------------------------------------------------------- /common/roots/GlobalSign_GCC_R3_DV_TLS_CA_2020.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEsDCCA5igAwIBAgIQd70OB0LV2enQSdd00CpvmjANBgkqhkiG9w0BAQsFADBM 3 | MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv 4 | YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMDA3MjgwMDAwMDBaFw0y 5 | OTAzMTgwMDAwMDBaMFMxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu 6 | IG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWduIEdDQyBSMyBEViBUTFMgQ0EgMjAy 7 | MDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKxnlJV/de+OpwyvCXAJ 8 | IcxPCqkFPh1lttW2oljS3oUqPKq8qX6m7K0OVKaKG3GXi4CJ4fHVUgZYE6HRdjqj 9 | hhnuHY6EBCBegcUFgPG0scB12Wi8BHm9zKjWxo3Y2bwhO8Fvr8R42pW0eINc6OTb 10 | QXC0VWFCMVzpcqgz6X49KMZowAMFV6XqtItcG0cMS//9dOJs4oBlpuqX9INxMTGp 11 | 6EASAF9cnlAGy/RXkVS9nOLCCa7pCYV+WgDKLTF+OK2Vxw3RUJ/p8009lQeUARv2 12 | UCcNNPCifYX1xIspvarkdjzLwzOdLahDdQbJON58zN4V+lMj0msg+c0KnywPIRp3 13 | BMkCAwEAAaOCAYUwggGBMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEF 14 | BQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUDZjA 15 | c3+rvb3ZR0tJrQpKDKw+x3wwHwYDVR0jBBgwFoAUj/BLf6guRSSuTVD6Y5qL3uLd 16 | G7wwewYIKwYBBQUHAQEEbzBtMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcDIuZ2xv 17 | YmFsc2lnbi5jb20vcm9vdHIzMDsGCCsGAQUFBzAChi9odHRwOi8vc2VjdXJlLmds 18 | b2JhbHNpZ24uY29tL2NhY2VydC9yb290LXIzLmNydDA2BgNVHR8ELzAtMCugKaAn 19 | hiVodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL3Jvb3QtcjMuY3JsMEcGA1UdIARA 20 | MD4wPAYEVR0gADA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu 21 | LmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAy8j/c550ea86oCkf 22 | r2W+ptTCYe6iVzvo7H0V1vUEADJOWelTv07Obf+YkEatdN1Jg09ctgSNv2h+LMTk 23 | KRZdAXmsE3N5ve+z1Oa9kuiu7284LjeS09zHJQB4DJJJkvtIbjL/ylMK1fbMHhAW 24 | i0O194TWvH3XWZGXZ6ByxTUIv1+kAIql/Mt29PmKraTT5jrzcVzQ5A9jw16yysuR 25 | XRrLODlkS1hyBjsfyTNZrmL1h117IFgntBA5SQNVl9ckedq5r4RSAU85jV8XK5UL 26 | REjRZt2I6M9Po9QL7guFLu4sPFJpwR1sPJvubS2THeo7SxYoNDtdyBHs7euaGcMa 27 | D/fayQ== 28 | -----END CERTIFICATE----- 29 | -----BEGIN CERTIFICATE----- 30 | MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G 31 | A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp 32 | Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 33 | MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG 34 | A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI 35 | hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 36 | RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT 37 | gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm 38 | KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd 39 | QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ 40 | XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw 41 | DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o 42 | LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU 43 | RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp 44 | jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK 45 | 6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX 46 | mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs 47 | Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH 48 | WD9f 49 | -----END CERTIFICATE----- 50 | -------------------------------------------------------------------------------- /common/src/config.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use serde::{Deserialize, Serialize}; 3 | use std::fmt::{Debug, Formatter}; 4 | use std::ops::Deref; 5 | use url::Url; 6 | 7 | use crate::constants::{DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_KEEPALIVE_SECS, DEFAULT_NODELAY}; 8 | 9 | pub use crate::protocol::Protocol; 10 | 11 | /// String with Debug implementation that emits "MASKED" 12 | /// Used to mask sensitive strings when logging 13 | #[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone)] 14 | pub struct MaskedString(pub String); 15 | 16 | impl Debug for MaskedString { 17 | fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { 18 | if self.0.is_empty() { 19 | f.write_str("EMPTY") 20 | } else { 21 | #[cfg(debug_assertions)] 22 | f.write_str(&self.0)?; 23 | #[cfg(not(debug_assertions))] 24 | f.write_str("MASKED")?; 25 | Ok(()) 26 | } 27 | } 28 | } 29 | 30 | impl Deref for MaskedString { 31 | type Target = str; 32 | fn deref(&self) -> &Self::Target { 33 | &self.0 34 | } 35 | } 36 | 37 | impl From<&str> for MaskedString { 38 | fn from(s: &str) -> MaskedString { 39 | MaskedString(String::from(s)) 40 | } 41 | } 42 | 43 | #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq, Default)] 44 | pub enum TransportType { 45 | #[serde(rename = "websocket")] 46 | #[default] 47 | Websocket, 48 | #[serde(rename = "tcp")] 49 | Tcp, 50 | #[cfg(feature = "rustls")] 51 | #[serde(rename = "tls")] 52 | Tls, 53 | } 54 | 55 | #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] 56 | #[serde(deny_unknown_fields)] 57 | #[derive(Default)] 58 | pub struct TlsConfig { 59 | pub hostname: Option, 60 | pub trusted_root: Option, 61 | pub pkcs12: Option, 62 | pub pkcs12_password: Option, 63 | pub danger_ignore_certificate_verification: Option, 64 | } 65 | 66 | #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] 67 | #[serde(deny_unknown_fields)] 68 | pub struct WebsocketConfig { 69 | pub tls: bool, 70 | } 71 | 72 | impl Default for WebsocketConfig { 73 | fn default() -> Self { 74 | Self { tls: true } 75 | } 76 | } 77 | 78 | #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] 79 | #[serde(deny_unknown_fields)] 80 | pub struct TcpConfig { 81 | pub nodelay: bool, 82 | pub keepalive_secs: u64, 83 | pub keepalive_interval: u64, 84 | pub proxy: Option, 85 | } 86 | 87 | impl Default for TcpConfig { 88 | fn default() -> Self { 89 | Self { 90 | nodelay: DEFAULT_NODELAY, 91 | keepalive_secs: DEFAULT_KEEPALIVE_SECS, 92 | keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, 93 | proxy: None, 94 | } 95 | } 96 | } 97 | 98 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] 99 | #[serde(deny_unknown_fields)] 100 | pub struct TransportConfig { 101 | #[serde(rename = "type")] 102 | pub transport_type: TransportType, 103 | pub tcp: TcpConfig, 104 | pub tls: Option, 105 | pub websocket: Option, 106 | } 107 | 108 | impl Default for TransportConfig { 109 | fn default() -> Self { 110 | Self { 111 | transport_type: TransportType::Websocket, 112 | tcp: TcpConfig::default(), 113 | tls: TlsConfig::default().into(), 114 | websocket: WebsocketConfig::default().into(), 115 | } 116 | } 117 | } 118 | 119 | impl TransportConfig { 120 | pub fn validate(config: &TransportConfig, _is_server: bool) -> Result<()> { 121 | config 122 | .tcp 123 | .proxy 124 | .as_ref() 125 | .map_or(Ok(()), |u| match u.scheme() { 126 | "socks5" => Ok(()), 127 | "http" => Ok(()), 128 | _ => Err(anyhow!(format!("Unknown proxy scheme: {}", u.scheme()))), 129 | })?; 130 | match config.transport_type { 131 | TransportType::Tcp => Ok(()), 132 | #[cfg(feature = "rustls")] 133 | TransportType::Tls => { 134 | let tls_config = config 135 | .tls 136 | .as_ref() 137 | .ok_or_else(|| anyhow!("Missing TLS configuration"))?; 138 | if _is_server { 139 | tls_config 140 | .pkcs12 141 | .as_ref() 142 | .and(tls_config.pkcs12_password.as_ref()) 143 | .ok_or_else(|| anyhow!("Missing `pkcs12` or `pkcs12_password`"))?; 144 | } 145 | Ok(()) 146 | } 147 | TransportType::Websocket => Ok(()), 148 | } 149 | } 150 | 151 | pub fn notls() -> Self { 152 | Self { 153 | transport_type: TransportType::Websocket, 154 | tcp: TcpConfig::default(), 155 | tls: None, 156 | websocket: WebsocketConfig { tls: false }.into(), 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /common/src/constants.rs: -------------------------------------------------------------------------------- 1 | use backoff::ExponentialBackoff; 2 | use std::time::Duration; 3 | 4 | /// Application-layer heartbeat interval in secs 5 | pub const DEFAULT_HEARTBEAT_INTERVAL_SECS: u64 = 30; 6 | pub const DEFAULT_HEARTBEAT_TIMEOUT_SECS: u64 = 40; 7 | 8 | /// Client 9 | pub const DEFAULT_CLIENT_RETRY_INTERVAL_SECS: u64 = 60; 10 | 11 | /// Server 12 | pub const BACKLOG_SIZE: usize = 1024; // The capacity TCP incoming conn backlog 13 | pub const HANDSHAKE_TIMEOUT: u64 = 5; // Timeout for transport handshake 14 | 15 | /// TCP 16 | pub const DEFAULT_NODELAY: bool = true; 17 | pub const DEFAULT_KEEPALIVE_SECS: u64 = 20; 18 | pub const DEFAULT_KEEPALIVE_INTERVAL: u64 = 8; 19 | 20 | // FIXME: Determine reasonable size 21 | /// UDP MTU. Currently far larger than necessary 22 | pub const UDP_BUFFER_SIZE: usize = 2048; 23 | pub const UDP_SENDQ_SIZE: usize = 1024; 24 | pub const UDP_TIMEOUT: u64 = 60; 25 | 26 | // Pingora service param 27 | pub const LISTENERS_PER_FD: usize = 1; 28 | 29 | pub fn listen_backoff() -> ExponentialBackoff { 30 | ExponentialBackoff { 31 | max_elapsed_time: None, 32 | max_interval: Duration::from_secs(1), 33 | ..Default::default() 34 | } 35 | } 36 | 37 | pub fn run_control_chan_backoff(interval: u64) -> ExponentialBackoff { 38 | ExponentialBackoff { 39 | randomization_factor: 0.2, 40 | max_elapsed_time: None, 41 | multiplier: 3.0, 42 | max_interval: Duration::from_secs(interval), 43 | ..Default::default() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /common/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod config; 2 | pub mod constants; 3 | pub mod logging; 4 | pub mod protocol; 5 | pub mod transport; 6 | pub mod utils; 7 | pub mod version; 8 | 9 | #[cfg(feature = "rustls")] 10 | pub use rustls_pemfile; 11 | #[cfg(feature = "rustls")] 12 | pub use tokio_rustls; 13 | pub use {prost, serde_json, tokio_tungstenite}; 14 | -------------------------------------------------------------------------------- /common/src/logging.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{Context as _, Result}; 2 | use rolling_file::{BasicRollingFileAppender, RollingConditionBasic}; 3 | use std::path::Path; 4 | use tracing::debug; 5 | pub use tracing_appender::non_blocking::WorkerGuard; 6 | use tracing_log::LogTracer; 7 | use tracing_subscriber::fmt; 8 | use tracing_subscriber::prelude::*; 9 | 10 | pub fn init_log( 11 | level: &str, 12 | log_file: &Path, 13 | stderr: bool, 14 | max_size: usize, 15 | max_files: usize, 16 | ) -> Result { 17 | let file_appender = BasicRollingFileAppender::new( 18 | log_file, 19 | RollingConditionBasic::new().max_size(max_size as u64), // 10 MB 20 | max_files, 21 | ) 22 | .context("Failed to create rolling file appender")?; 23 | 24 | let (file_writer, guard) = tracing_appender::non_blocking(file_appender); 25 | 26 | let trace_cfg = format!( 27 | "{},hyper=info,tokio_postgres=info,pingora_core=info,pingora_proxy=info,{}", 28 | level, 29 | std::env::var("RUST_LOG").unwrap_or_default() 30 | ); 31 | 32 | let timer = time::format_description::parse( 33 | "[year]-[month padding:zero]-[day padding:zero] [hour]:[minute]:[second]", 34 | ) 35 | .context("Failed to parse time format")?; 36 | 37 | let time_offset = time::UtcOffset::current_local_offset().unwrap_or(time::UtcOffset::UTC); 38 | let timer = fmt::time::OffsetTime::new(time_offset, timer); 39 | 40 | // Create the file layer with common settings 41 | let file_layer = fmt::Layer::default() 42 | .with_timer(timer.clone()) 43 | .with_ansi(false) 44 | .with_writer(file_writer); 45 | 46 | // Build a registry with the file layer and conditional stderr layer 47 | let registry = tracing_subscriber::registry() 48 | .with(tracing_subscriber::EnvFilter::new(trace_cfg)) 49 | .with(file_layer); 50 | 51 | // Add stderr layer only if requested 52 | if stderr { 53 | let stderr_layer = fmt::Layer::default() 54 | .with_timer(timer) 55 | .with_ansi(cfg!(unix)) 56 | .with_writer(std::io::stderr); 57 | 58 | tracing::subscriber::set_global_default(registry.with(stderr_layer)) 59 | .context("Failed to set global default subscriber")?; 60 | } else { 61 | tracing::subscriber::set_global_default(registry) 62 | .context("Failed to set global default subscriber")?; 63 | } 64 | 65 | LogTracer::init().context("Failed to initialize log tracer")?; 66 | log_panics::init(); 67 | 68 | debug!("Tracing initialized ({})", level); 69 | Ok(guard) 70 | } 71 | -------------------------------------------------------------------------------- /common/src/protocol.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package protocol; 4 | 5 | enum Protocol { 6 | HTTP = 0; 7 | HTTPS = 1; 8 | TCP = 2; 9 | UDP = 3; 10 | ONE_C = 4; 11 | MINECRAFT = 5; 12 | WEBDAV = 6; 13 | RTSP = 7; 14 | } 15 | 16 | enum Auth { 17 | NONE = 0; 18 | BASIC = 1; 19 | FORM = 2; 20 | } 21 | 22 | enum Role { 23 | NOBODY = 0; 24 | ADMIN = 1; 25 | READER = 2; 26 | WRITER = 3; 27 | } 28 | 29 | enum ErrorKind { 30 | AUTH_FAILED = 0; 31 | FATAL = 1; 32 | HANDSHAKE_FAILED = 2; 33 | PERMISSION_DENIED = 3; 34 | PUBLISH_FAILED = 4; 35 | EXECUTE_FAILED = 5; 36 | } 37 | 38 | enum ConnectState { 39 | CONNECTING = 0; 40 | CONNECTED = 1; 41 | DISCONNECTED = 2; 42 | } 43 | 44 | message Acl { 45 | string user = 1; 46 | Role role = 2; 47 | } 48 | 49 | message Header { 50 | string name = 1; 51 | string value = 2; 52 | } 53 | 54 | message ClientEndpoint { 55 | Protocol local_proto = 1; 56 | string local_addr = 2; 57 | uint32 local_port = 3; 58 | string local_path = 4; 59 | optional bool nodelay = 5; 60 | optional string description = 6; 61 | Auth auth = 7; 62 | repeated Acl acl = 8; 63 | string username = 9; 64 | string password = 10; 65 | repeated Header headers = 11; 66 | } 67 | 68 | message ServerEndpoint { 69 | optional string status = 1; 70 | string guid = 2; 71 | Protocol remote_proto = 3; 72 | string remote_addr = 4; 73 | uint32 remote_port = 5; 74 | ClientEndpoint client = 6; 75 | int64 id = 7; 76 | string bind_addr = 8; 77 | } 78 | 79 | message AgentInfo { 80 | string agent_id = 1; 81 | string token = 2; 82 | string hostname = 3; 83 | string version = 4; 84 | bool gui = 5; 85 | string platform = 6; 86 | string hwid = 7; 87 | string server_host_and_port = 8; 88 | string email = 9; 89 | string password = 10; 90 | } 91 | 92 | message DataChannelInfo { 93 | string agent_id = 1; 94 | string guid = 2; 95 | } 96 | 97 | message UpgradeInfo { 98 | string version = 1; 99 | string url = 2; 100 | } 101 | 102 | message ErrorInfo { 103 | ErrorKind kind = 1; 104 | string message = 2; 105 | } 106 | 107 | message ProgressInfo { 108 | string message = 1; 109 | string template = 2; 110 | uint32 current = 3; 111 | uint32 total = 4; 112 | } 113 | 114 | message AgentAck { 115 | string token = 1; 116 | } 117 | 118 | message HeartBeat { 119 | } 120 | 121 | message StartForwardTcp { 122 | } 123 | 124 | message StartForwardUdp { 125 | } 126 | 127 | message Break { 128 | } 129 | 130 | message Stop { 131 | } 132 | 133 | message EndpointList { 134 | } 135 | 136 | message EndpointClear { 137 | } 138 | 139 | message EndpointClearAck { 140 | } 141 | 142 | message EndpointListAck { 143 | repeated ServerEndpoint endpoints = 1; 144 | } 145 | 146 | message Redirect { 147 | string host_and_port = 1; 148 | } 149 | 150 | message EndpointStop { 151 | string guid = 1; 152 | } 153 | 154 | message EndpointStopAck { 155 | string guid = 1; 156 | } 157 | 158 | message EndpointRemove { 159 | string guid = 1; 160 | } 161 | 162 | 163 | message EndpointRemoveAck { 164 | string guid = 1; 165 | } 166 | 167 | message EndpointStartAll { 168 | } 169 | 170 | // Message wrapper 171 | message Message { 172 | oneof message { 173 | AgentInfo agent_hello = 1; 174 | AgentAck agent_ack = 2; 175 | ClientEndpoint endpoint_start = 3; 176 | ServerEndpoint endpoint_ack = 4; 177 | EndpointStop endpoint_stop = 5; 178 | DataChannelInfo data_channel_hello = 6; 179 | ServerEndpoint create_data_channel = 7; 180 | HeartBeat heart_beat = 8; 181 | StartForwardTcp start_forward_tcp = 9; 182 | StartForwardUdp start_forward_udp = 10; 183 | ErrorInfo error = 11; 184 | UpgradeInfo upgrade_available = 12; 185 | Redirect redirect = 13; 186 | EndpointRemove endpoint_remove = 14; 187 | Break break = 15; 188 | Stop stop = 16; 189 | ConnectState connect_state = 17; 190 | ProgressInfo progress = 18; 191 | EndpointList endpoint_list = 19; 192 | EndpointListAck endpoint_list_ack = 20; 193 | EndpointClear endpoint_clear = 21; 194 | EndpointClearAck endpoint_clear_ack = 22; 195 | EndpointStartAll endpoint_start_all = 23; 196 | EndpointStopAck endpoint_stop_ack = 24; 197 | EndpointRemoveAck endpoint_remove_ack = 25; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /common/src/transport/tcp.rs: -------------------------------------------------------------------------------- 1 | use crate::config::{TcpConfig, TransportConfig}; 2 | 3 | use super::{AddrMaybeCached, SocketOpts, Transport}; 4 | use crate::utils::host_port_pair; 5 | use anyhow::Result; 6 | use async_http_proxy::{http_connect_tokio, http_connect_tokio_with_basic_auth}; 7 | use async_trait::async_trait; 8 | use socket2::{SockRef, TcpKeepalive}; 9 | #[cfg(unix)] 10 | use std::os::fd::{AsRawFd, RawFd}; 11 | use std::str::FromStr; 12 | use std::time::Duration; 13 | use tokio::net::TcpStream; 14 | pub use tokio_unix_tcp::{Listener, NamedSocketAddr, SocketAddr, Stream}; 15 | use tracing::trace; 16 | use url::Url; 17 | 18 | #[derive(Debug)] 19 | pub struct TcpTransport { 20 | socket_opts: SocketOpts, 21 | cfg: TcpConfig, 22 | } 23 | 24 | #[async_trait] 25 | impl Transport for TcpTransport { 26 | type Acceptor = Listener; 27 | type Stream = Stream; 28 | type RawStream = Stream; 29 | 30 | fn new(config: &TransportConfig) -> Result { 31 | Ok(TcpTransport { 32 | socket_opts: SocketOpts::from_cfg(&config.tcp), 33 | cfg: config.tcp.clone(), 34 | }) 35 | } 36 | 37 | #[cfg(unix)] 38 | fn as_raw_fd(conn: &Self::Stream) -> RawFd { 39 | match conn { 40 | Stream::Tcp(conn) => conn.as_raw_fd(), 41 | Stream::Unix(conn) => conn.as_raw_fd(), 42 | } 43 | } 44 | 45 | fn hint(conn: &Self::Stream, opt: SocketOpts) { 46 | opt.apply(conn); 47 | } 48 | 49 | async fn bind(&self, addr: NamedSocketAddr) -> Result { 50 | Ok(Listener::bind(&addr).await?) 51 | } 52 | 53 | async fn accept(&self, a: &Self::Acceptor) -> Result<(Self::RawStream, SocketAddr)> { 54 | let (s, addr) = a.accept().await?; 55 | self.socket_opts.apply(&s); 56 | Ok((s, addr)) 57 | } 58 | 59 | async fn handshake(&self, conn: Self::RawStream) -> Result { 60 | Ok(conn) 61 | } 62 | 63 | async fn connect(&self, addr: &AddrMaybeCached) -> Result { 64 | let s = tcp_connect_with_proxy(addr, self.cfg.proxy.as_ref()).await?; 65 | self.socket_opts.apply(&s); 66 | Ok(s) 67 | } 68 | } 69 | 70 | // Tokio hesitates to expose this option...So we have to do it on our own :( 71 | // The good news is that using socket2 it can be easily done, without losing portability. 72 | // See https://github.com/tokio-rs/tokio/issues/3082 73 | pub fn try_set_tcp_keepalive( 74 | conn: &TcpStream, 75 | keepalive_duration: Duration, 76 | keepalive_interval: Duration, 77 | ) -> Result<()> { 78 | let s = SockRef::from(conn); 79 | let keepalive = TcpKeepalive::new() 80 | .with_time(keepalive_duration) 81 | .with_interval(keepalive_interval); 82 | 83 | trace!( 84 | "Set TCP keepalive {:?} {:?}", 85 | keepalive_duration, 86 | keepalive_interval 87 | ); 88 | 89 | Ok(s.set_tcp_keepalive(&keepalive)?) 90 | } 91 | 92 | /// Create a TcpStream using a proxy 93 | /// e.g. socks5://user:pass@127.0.0.1:1080 http://127.0.0.1:8080 94 | pub async fn tcp_connect_with_proxy(addr: &AddrMaybeCached, proxy: Option<&Url>) -> Result { 95 | if let Some(url) = proxy { 96 | let addr = &addr.addr; 97 | let mut s = TcpStream::connect(( 98 | url.host_str().expect("proxy url should have host field"), 99 | url.port().expect("proxy url should have port field"), 100 | )) 101 | .await?; 102 | 103 | let auth = if !url.username().is_empty() || url.password().is_some() { 104 | Some(async_socks5::Auth { 105 | username: url.username().into(), 106 | password: url.password().unwrap_or("").into(), 107 | }) 108 | } else { 109 | None 110 | }; 111 | match url.scheme() { 112 | "socks5" => { 113 | async_socks5::connect(&mut s, host_port_pair(addr)?, auth).await?; 114 | } 115 | "http" => { 116 | let (host, port) = host_port_pair(addr)?; 117 | match auth { 118 | Some(auth) => { 119 | http_connect_tokio_with_basic_auth( 120 | &mut s, 121 | host, 122 | port, 123 | &auth.username, 124 | &auth.password, 125 | ) 126 | .await? 127 | } 128 | None => http_connect_tokio(&mut s, host, port).await?, 129 | } 130 | } 131 | _ => panic!("unknown proxy scheme"), 132 | } 133 | Ok(Stream::Tcp(s)) 134 | } else { 135 | Ok(match addr.socket_addr.as_ref() { 136 | Some(s) => Stream::connect(s).await?, 137 | None => Stream::connect(&NamedSocketAddr::from_str(&addr.addr)?).await?, 138 | }) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /common/src/version.rs: -------------------------------------------------------------------------------- 1 | pub const VERSION: &str = "1.7.0"; 2 | pub const BUILD: &str = "0"; 3 | pub const LONG_VERSION: &str = "1.7.0 build 0"; 4 | -------------------------------------------------------------------------------- /docs/build/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/.nojekyll -------------------------------------------------------------------------------- /docs/build/404.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/404.html.gz -------------------------------------------------------------------------------- /docs/build/assets/css/styles.2d00718a.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/css/styles.2d00718a.css.gz -------------------------------------------------------------------------------- /docs/build/assets/images/login-form-94cccf4ab4f59c8714e77715927a58a4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/images/login-form-94cccf4ab4f59c8714e77715927a58a4.png -------------------------------------------------------------------------------- /docs/build/assets/images/publication-0ae3de0a51e8cd4aebfe9362436ad7d0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/images/publication-0ae3de0a51e8cd4aebfe9362436ad7d0.png -------------------------------------------------------------------------------- /docs/build/assets/js/0e384e19.4874dedf.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/0e384e19.4874dedf.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/11b43341.83a6c715.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[256],{5293:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Quick Start","href":"/docs/","docId":"intro","unlisted":false},{"type":"link","label":"HTTP and HTTPS Services","href":"/docs/http","docId":"http","unlisted":false},{"type":"link","label":"TCP and UDP Services","href":"/docs/tcp","docId":"tcp","unlisted":false},{"type":"link","label":"File Publishing","href":"/docs/webdav","docId":"webdav","unlisted":false},{"type":"link","label":"Minecraft Server","href":"/docs/minecraft","docId":"minecraft","unlisted":false},{"type":"link","label":"RTSP Video Streams","href":"/docs/rtsp","docId":"rtsp","unlisted":false},{"type":"link","label":"Authentication and Access Control","href":"/docs/auth","docId":"auth","unlisted":false},{"type":"link","label":"Docker Image","href":"/docs/docker","docId":"docker","unlisted":false},{"type":"link","label":"Command Line Parameters","href":"/docs/cli","docId":"cli","unlisted":false},{"type":"link","label":"Version History","href":"/docs/changelog","docId":"changelog","unlisted":false}]},"docs":{"auth":{"id":"auth","title":"Authentication and Access Control","description":"Authentication Types","sidebar":"tutorialSidebar"},"changelog":{"id":"changelog","title":"Version History","description":"1.7.0 (May 29, 2025)","sidebar":"tutorialSidebar"},"cli":{"id":"cli","title":"Command Line Parameters","description":"clo provides the following command line parameters:","sidebar":"tutorialSidebar"},"docker":{"id":"docker","title":"Docker Image","description":"Using CloudPub with Docker","sidebar":"tutorialSidebar"},"http":{"id":"http","title":"HTTP and HTTPS Services","description":"Publishing HTTP Services","sidebar":"tutorialSidebar"},"intro":{"id":"intro","title":"Quick Start","description":"How to start using CloudPub in 5 minutes.","sidebar":"tutorialSidebar"},"minecraft":{"id":"minecraft","title":"Minecraft Server","description":"Publishing Minecraft Server on the Internet","sidebar":"tutorialSidebar"},"rtsp":{"id":"rtsp","title":"RTSP Video Streams","description":"With CloudPub you can publish RTSP video streams from surveillance cameras.","sidebar":"tutorialSidebar"},"tcp":{"id":"tcp","title":"TCP and UDP Services","description":"Publishing TCP Services","sidebar":"tutorialSidebar"},"webdav":{"id":"webdav","title":"File Publishing","description":"With CloudPub you can publish files and folders to share them with other users.","sidebar":"tutorialSidebar"}}}}')}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/11b43341.83a6c715.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/11b43341.83a6c715.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/151.1ec91b9d.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license React 3 | * react-is.production.min.js 4 | * 5 | * Copyright (c) Facebook, Inc. and its affiliates. 6 | * 7 | * This source code is licensed under the MIT license found in the 8 | * LICENSE file in the root directory of this source tree. 9 | */ 10 | 11 | /** @license React v16.13.1 12 | * react-is.production.min.js 13 | * 14 | * Copyright (c) Facebook, Inc. and its affiliates. 15 | * 16 | * This source code is licensed under the MIT license found in the 17 | * LICENSE file in the root directory of this source tree. 18 | */ 19 | -------------------------------------------------------------------------------- /docs/build/assets/js/151.1ec91b9d.js.LICENSE.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/151.1ec91b9d.js.LICENSE.txt.gz -------------------------------------------------------------------------------- /docs/build/assets/js/151.1ec91b9d.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/151.1ec91b9d.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/17896441.152c9fe7.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/17896441.152c9fe7.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/1a20bc57.049e6787.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/1a20bc57.049e6787.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/1b70f4c4.e5d9cf89.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[792],{4736:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>t,metadata:()=>s,toc:()=>a});const s=JSON.parse('{"id":"tcp","title":"TCP and UDP Services","description":"Publishing TCP Services","source":"@site/docs/tcp.md","sourceDirName":".","slug":"/tcp","permalink":"/docs/tcp","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"sidebar_position":3,"slug":"/tcp"},"sidebar":"tutorialSidebar","previous":{"title":"HTTP and HTTPS Services","permalink":"/docs/http"},"next":{"title":"File Publishing","permalink":"/docs/webdav"}}');var r=i(4848),c=i(8453);const t={sidebar_position:3,slug:"/tcp"},o="TCP and UDP Services",l={},a=[{value:"Publishing TCP Services",id:"publishing-tcp-services",level:2},{value:"Publishing UDP Services",id:"publishing-udp-services",level:2}];function d(e){const n={code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,c.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"tcp-and-udp-services",children:"TCP and UDP Services"})}),"\n",(0,r.jsx)(n.h2,{id:"publishing-tcp-services",children:"Publishing TCP Services"}),"\n",(0,r.jsx)(n.p,{children:"Publishing a service running on TCP protocol is done similarly to publishing an HTTP service, but with specifying the TCP protocol:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"clo publish tcp 22\n"})}),"\n",(0,r.jsx)(n.p,{children:"In this example, we are publishing a service running on port 22 (SSH)."}),"\n",(0,r.jsxs)(n.p,{children:["Unlike HTTP services, TCP services do not get a unique domain name and are only available at the address ",(0,r.jsx)(n.code,{children:"tcp.cloudpub.online"})," with a unique port."]}),"\n",(0,r.jsx)(n.p,{children:"Just like with HTTP services, you can specify the address of any host in the local network:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"clo publish tcp myserver:3389\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In this example, we are publishing a service running on port 3389 (RDP) on host ",(0,r.jsx)(n.code,{children:"myserver"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"publishing-udp-services",children:"Publishing UDP Services"}),"\n",(0,r.jsx)(n.p,{children:"Publishing a service running on UDP protocol is done similarly to publishing a TCP service, but with specifying the UDP protocol:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"clo publish udp 53\n"})}),"\n",(0,r.jsx)(n.p,{children:"In this example, we are publishing a service running on port 53 (DNS)."})]})}function p(e={}){const{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>t,x:()=>o});var s=i(6540);const r={},c=s.createContext(r);function t(e){const n=s.useContext(c);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:t(e.components),s.createElement(c.Provider,{value:n},e.children)}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/1b70f4c4.e5d9cf89.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/1b70f4c4.e5d9cf89.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/254e54e8.17d8720b.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[581],{783:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"rtsp","title":"RTSP Video Streams","description":"With CloudPub you can publish RTSP video streams from surveillance cameras.","source":"@site/docs/rtsp.md","sourceDirName":".","slug":"/rtsp","permalink":"/docs/rtsp","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"sidebar_position":7,"slug":"/rtsp"},"sidebar":"tutorialSidebar","previous":{"title":"Minecraft Server","permalink":"/docs/minecraft"},"next":{"title":"Authentication and Access Control","permalink":"/docs/auth"}}');var s=n(4848),i=n(8453);const o={sidebar_position:7,slug:"/rtsp"},a="RTSP Video Streams",c={},l=[{value:"RTSP Protocol",id:"rtsp-protocol",level:2},{value:"Graphical Interface Application",id:"graphical-interface-application",level:3},{value:"Command Line",id:"command-line",level:3}];function d(e){const r={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.header,{children:(0,s.jsx)(r.h1,{id:"rtsp-video-streams",children:"RTSP Video Streams"})}),"\n",(0,s.jsx)(r.p,{children:"With CloudPub you can publish RTSP video streams from surveillance cameras."}),"\n",(0,s.jsx)(r.p,{children:"This allows you to access your cameras from the internet without opening ports on your router."}),"\n",(0,s.jsx)(r.p,{children:"Additionally, you can view video streams in your personal account or the CloudPub application."}),"\n",(0,s.jsx)(r.h2,{id:"rtsp-protocol",children:"RTSP Protocol"}),"\n",(0,s.jsx)(r.p,{children:"Video streams are published using the RTSP protocol."}),"\n",(0,s.jsx)(r.p,{children:"This means you can use any RTSP player to access the video streams."}),"\n",(0,s.jsx)(r.p,{children:"For example, in Windows 10 this can be done through VLC Media Player, in macOS - through QuickTime Player."}),"\n",(0,s.jsx)(r.p,{children:"Simply open the player and enter the RTSP stream address provided by CloudPub."}),"\n",(0,s.jsx)(r.h3,{id:"graphical-interface-application",children:"Graphical Interface Application"}),"\n",(0,s.jsxs)(r.p,{children:["Select the publication type ",(0,s.jsx)(r.code,{children:"Surveillance Camera (RTSP)"})," and enter the URL of your RTSP stream."]}),"\n",(0,s.jsx)(r.h3,{id:"command-line",children:"Command Line"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-bash",children:'clo publish rtsp "[RTSP stream URL]"\n'})}),"\n",(0,s.jsx)(r.p,{children:"After this, you will be provided with a URL where your RTSP video stream will be accessible."}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-bash",children:"Service published: rtsp://192.168.0.100:554/stream0 -> rtsp://rtsp.cloudpub.online:51243/stream0\n"})}),"\n",(0,s.jsx)(r.p,{children:"The address specified after the arrow will be accessible from the internet."}),"\n",(0,s.jsx)(r.p,{children:'You can view published streams in the "Video Streams" section of your personal account or application.'})]})}function p(e={}){const{wrapper:r}={...(0,i.R)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,r,n)=>{n.d(r,{R:()=>o,x:()=>a});var t=n(6540);const s={},i=t.createContext(s);function o(e){const r=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(i.Provider,{value:r},e.children)}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/254e54e8.17d8720b.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/254e54e8.17d8720b.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/35408621.f546a790.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[950],{4222:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>a,contentTitle:()=>c,default:()=>d,frontMatter:()=>l,metadata:()=>n,toc:()=>h});const n=JSON.parse('{"id":"http","title":"HTTP and HTTPS Services","description":"Publishing HTTP Services","source":"@site/docs/http.md","sourceDirName":".","slug":"/http","permalink":"/docs/http","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2,"slug":"/http"},"sidebar":"tutorialSidebar","previous":{"title":"Quick Start","permalink":"/docs/"},"next":{"title":"TCP and UDP Services","permalink":"/docs/tcp"}}');var t=i(4848),r=i(8453);const l={sidebar_position:2,slug:"/http"},c="HTTP and HTTPS Services",a={},h=[{value:"Publishing HTTP Services",id:"publishing-http-services",level:2},{value:"Publishing HTTPS Services",id:"publishing-https-services",level:2},{value:"HTTP and HTTPS Request Headers",id:"http-and-https-request-headers",level:2}];function o(e){const s={code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.header,{children:(0,t.jsx)(s.h1,{id:"http-and-https-services",children:"HTTP and HTTPS Services"})}),"\n",(0,t.jsx)(s.h2,{id:"publishing-http-services",children:"Publishing HTTP Services"}),"\n",(0,t.jsx)(s.p,{children:"To publish a local HTTP server running on a local interface, simply execute the command:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"clo publish http 8080\n"})}),"\n",(0,t.jsx)(s.p,{children:"where 8080 is the port on which your server is running."}),"\n",(0,t.jsx)(s.p,{children:"After executing the command, you will receive a message that your service has been published:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"Service published: http://localhost:8080 -> https://wildly-suitable-fish.cloudpub.online\n"})}),"\n",(0,t.jsx)(s.p,{children:"The service will be publicly available via HTTPS protocol, and we will automatically generate a certificate for this domain."}),"\n",(0,t.jsx)(s.p,{children:"If you need to publish a service running on another host in the local network, you can specify the IP address or host when publishing:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"clo publish http 192.168.1.1:80\n"})}),"\n",(0,t.jsx)(s.p,{children:"In this case, the service will be published on the specified IP address and port (in this example, it could be your router's admin panel)"}),"\n",(0,t.jsx)(s.h2,{id:"publishing-https-services",children:"Publishing HTTPS Services"}),"\n",(0,t.jsx)(s.p,{children:"Publishing HTTPS services is similar to publishing HTTP services, but with specifying the HTTPS protocol:"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"clo publish https 443\n"})}),"\n",(0,t.jsx)(s.h2,{id:"http-and-https-request-headers",children:"HTTP and HTTPS Request Headers"}),"\n",(0,t.jsx)(s.p,{children:"When publishing HTTP and HTTPS services, you can override or specify additional headers that will be added to requests sent to your local server."}),"\n",(0,t.jsxs)(s.p,{children:["This can be useful if your server requires certain headers to work, for example, a ",(0,t.jsx)(s.code,{children:"Host"})," header matching the local server address (",(0,t.jsx)(s.code,{children:"localhost"}),")"]}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-bash",children:"clo publish -H Host:localhost https 443\n"})})]})}function d(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},8453:(e,s,i)=>{i.d(s,{R:()=>l,x:()=>c});var n=i(6540);const t={},r=n.createContext(t);function l(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/35408621.f546a790.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/35408621.f546a790.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/42.0b64ebc5.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[42],{3042:(e,t,n)=>{n.r(t),n.d(t,{default:()=>d});n(6540);var o=n(539),i=n(1769),s=n(1410),r=n(5932),a=n(4848);function d(){const e=(0,o.T)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.be,{title:e}),(0,a.jsx)(s.A,{children:(0,a.jsx)(r.A,{})})]})}},5932:(e,t,n)=>{n.d(t,{A:()=>a});n(6540);var o=n(4164),i=n(539),s=n(9303),r=n(4848);function a(e){let{className:t}=e;return(0,r.jsx)("main",{className:(0,o.A)("container margin-vert--xl",t),children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(s.A,{as:"h1",className:"hero__title",children:(0,r.jsx)(i.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,r.jsx)("p",{children:(0,r.jsx)(i.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,r.jsx)("p",{children:(0,r.jsx)(i.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/42.0b64ebc5.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/42.0b64ebc5.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/5e95c892.b907de86.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[647],{8122:(e,s,u)=>{u.r(s),u.d(s,{default:()=>n});u(6540);var c=u(4164),r=u(1769),d=u(204),a=u(2831),l=u(1410),o=u(4848);function n(e){return(0,o.jsx)(r.e3,{className:(0,c.A)(d.G.wrapper.docsPages),children:(0,o.jsx)(l.A,{children:(0,a.v)(e.route.routes)})})}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/5e95c892.b907de86.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/5e95c892.b907de86.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/913.1a07e874.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/913.1a07e874.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/93234bd6.a62a19f9.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/93234bd6.a62a19f9.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/9beb87c2.aa6ff69e.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/9beb87c2.aa6ff69e.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/9f70d1c7.2d8489aa.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[148],{8453:(e,n,r)=>{r.d(n,{R:()=>a,x:()=>c});var t=r(6540);const i={},s=t.createContext(i);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),t.createElement(s.Provider,{value:n},e.children)}},8949:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>t,toc:()=>l});const t=JSON.parse('{"id":"minecraft","title":"Minecraft Server","description":"Publishing Minecraft Server on the Internet","source":"@site/docs/minecraft.md","sourceDirName":".","slug":"/minecraft","permalink":"/docs/minecraft","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"sidebar_position":6,"slug":"/minecraft"},"sidebar":"tutorialSidebar","previous":{"title":"File Publishing","permalink":"/docs/webdav"},"next":{"title":"RTSP Video Streams","permalink":"/docs/rtsp"}}');var i=r(4848),s=r(8453);const a={sidebar_position:6,slug:"/minecraft"},c="Minecraft Server",o={},l=[{value:"Publishing Minecraft Server on the Internet",id:"publishing-minecraft-server-on-the-internet",level:2},{value:"Graphical Interface Application",id:"graphical-interface-application",level:3},{value:"Command Line",id:"command-line",level:3},{value:"Server with Mods",id:"server-with-mods",level:3}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"minecraft-server",children:"Minecraft Server"})}),"\n",(0,i.jsx)(n.h2,{id:"publishing-minecraft-server-on-the-internet",children:"Publishing Minecraft Server on the Internet"}),"\n",(0,i.jsx)(n.p,{children:"CloudPub allows you to publish Minecraft servers on the internet so your friends can connect to it from anywhere in the world."}),"\n",(0,i.jsx)(n.p,{children:"If you're not using mods, this is very simple. You need to specify the path to the Minecraft server folder, and CloudPub will automatically configure all necessary parameters."}),"\n",(0,i.jsx)(n.h3,{id:"graphical-interface-application",children:"Graphical Interface Application"}),"\n",(0,i.jsxs)(n.p,{children:["Select the publication type ",(0,i.jsx)(n.code,{children:"minecraft"})," and specify the path to the folder where the server will be installed."]}),"\n",(0,i.jsx)(n.h3,{id:"command-line",children:"Command Line"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"clo publish minecraft [path to server folder]\n"})}),"\n",(0,i.jsx)(n.p,{children:"After this, you will be provided with a URL where your server will be accessible on the internet, for example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"Service published: minecraft://C:\\Minecraft -> minecraft://minecraft.cloudpub.online:32123\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The address specified after the arrow (",(0,i.jsx)(n.code,{children:"-> minecraft://"}),") is the address that players need to enter the game."]}),"\n",(0,i.jsxs)(n.p,{children:["In the example above, this is ",(0,i.jsx)(n.code,{children:"minecraft.cloudpub.online:32123"})]}),"\n",(0,i.jsx)(n.h3,{id:"server-with-mods",children:"Server with Mods"}),"\n",(0,i.jsxs)(n.p,{children:["If you're using a server with mods, use the ",(0,i.jsx)(n.a,{href:"/docs/tcp",children:"TCP service publication instructions"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The port that needs to be opened for connecting to the Minecraft server is 25565 by default, but can be changed in the server settings."}),"\n",(0,i.jsxs)(n.p,{children:["This is described in more detail in the ",(0,i.jsx)(n.a,{href:"https://minecraft.fandom.com/wiki/Tutorials/Setting_up_a_server",children:"official Minecraft documentation"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/9f70d1c7.2d8489aa.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/9f70d1c7.2d8489aa.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/a7bd4aaa.ee424588.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[98],{7419:(n,e,s)=>{s.r(e),s.d(e,{default:()=>a});s(6540);var r=s(1769);function o(n,e){return`docs-${n}-${e}`}var c=s(1858),t=s(2831),u=s(7220),i=s(4848);function d(n){const{version:e}=n;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(u.A,{version:e.version,tag:o(e.pluginId,e.version)}),(0,i.jsx)(r.be,{children:e.noIndex&&(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(n){const{version:e,route:s}=n;return(0,i.jsx)(r.e3,{className:e.className,children:(0,i.jsx)(c.n,{version:e,children:(0,t.v)(s.routes)})})}function a(n){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(d,{...n}),(0,i.jsx)(l,{...n})]})}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/a7bd4aaa.ee424588.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/a7bd4aaa.ee424588.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/a94703ab.892c3022.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/a94703ab.892c3022.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/aba21aa0.9d11f6df.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[742],{7093:u=>{u.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/aba21aa0.9d11f6df.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/aba21aa0.9d11f6df.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/cb769c5c.368c60a9.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/cb769c5c.368c60a9.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/e228af67.92e2af36.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_cloudpub_docs=self.webpackChunk_cloudpub_docs||[]).push([[472],{5658:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"webdav","title":"File Publishing","description":"With CloudPub you can publish files and folders to share them with other users.","source":"@site/docs/webdav.md","sourceDirName":".","slug":"/webdav","permalink":"/docs/webdav","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"sidebar_position":5,"slug":"/webdav"},"sidebar":"tutorialSidebar","previous":{"title":"TCP and UDP Services","permalink":"/docs/tcp"},"next":{"title":"Minecraft Server","permalink":"/docs/minecraft"}}');var o=i(4848),s=i(8453);const t={sidebar_position:5,slug:"/webdav"},l="File Publishing",a={},c=[{value:"WebDAV Protocol",id:"webdav-protocol",level:2},{value:"Graphical Interface Application",id:"graphical-interface-application",level:3},{value:"Command Line",id:"command-line",level:3}];function d(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"file-publishing",children:"File Publishing"})}),"\n",(0,o.jsx)(n.p,{children:"With CloudPub you can publish files and folders to share them with other users."}),"\n",(0,o.jsx)(n.p,{children:"Additionally, this allows you to manage your files without uploading them to third-party services."}),"\n",(0,o.jsx)(n.h2,{id:"webdav-protocol",children:"WebDAV Protocol"}),"\n",(0,o.jsx)(n.p,{children:"Files are published using the WebDAV protocol."}),"\n",(0,o.jsx)(n.p,{children:"This means you can use any WebDAV client to access the files."}),"\n",(0,o.jsx)(n.p,{children:"For example, in Windows 10 this can be done through File Explorer, in macOS - through Finder."}),"\n",(0,o.jsx)(n.p,{children:"Simply open File Explorer or Finder, enter the address provided by CloudPub, and enter your login and password."}),"\n",(0,o.jsx)(n.p,{children:"After that, you will be able to work with files just like regular files on your computer."}),"\n",(0,o.jsx)(n.h3,{id:"graphical-interface-application",children:"Graphical Interface Application"}),"\n",(0,o.jsxs)(n.p,{children:["Select the publication type ",(0,o.jsx)(n.code,{children:"File Folder (WebDAV)"})," and specify the path to the folder where the server will be installed."]}),"\n",(0,o.jsx)(n.h3,{id:"command-line",children:"Command Line"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:'clo publish webdav "[folder path]"\n'})}),"\n",(0,o.jsx)(n.p,{children:"After this, you will be provided with a URL where your files will be accessible."}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"Service published: webdav://C:\\Users\\Administrator -> https://indelibly-fearless-jackdaw.cloudpub.local\n"})}),"\n",(0,o.jsx)(n.p,{children:"The address specified after the arrow will be accessible from the internet."}),"\n",(0,o.jsx)(n.p,{children:"To access files, you will need to enter a login and password. Your email is used as the login, and the password matches your account password."}),"\n",(0,o.jsx)(n.p,{children:'You can manage files from the "File Manager" section in your personal account.'}),"\n",(0,o.jsx)(n.p,{children:"If you need to provide access to a file to other users, you can generate a download link for the file there."})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>t,x:()=>l});var r=i(6540);const o={},s=r.createContext(o);function t(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]); -------------------------------------------------------------------------------- /docs/build/assets/js/e228af67.92e2af36.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/e228af67.92e2af36.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/main.34e78845.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress 2 | * @license MIT */ 3 | 4 | /*! Bundled license information: 5 | 6 | prismjs/prism.js: 7 | (** 8 | * Prism: Lightweight, robust, elegant syntax highlighting 9 | * 10 | * @license MIT 11 | * @author Lea Verou 12 | * @namespace 13 | * @public 14 | *) 15 | */ 16 | 17 | /** 18 | * @license React 19 | * react-dom.production.min.js 20 | * 21 | * Copyright (c) Facebook, Inc. and its affiliates. 22 | * 23 | * This source code is licensed under the MIT license found in the 24 | * LICENSE file in the root directory of this source tree. 25 | */ 26 | 27 | /** 28 | * @license React 29 | * react-jsx-runtime.production.min.js 30 | * 31 | * Copyright (c) Facebook, Inc. and its affiliates. 32 | * 33 | * This source code is licensed under the MIT license found in the 34 | * LICENSE file in the root directory of this source tree. 35 | */ 36 | 37 | /** 38 | * @license React 39 | * react.production.min.js 40 | * 41 | * Copyright (c) Facebook, Inc. and its affiliates. 42 | * 43 | * This source code is licensed under the MIT license found in the 44 | * LICENSE file in the root directory of this source tree. 45 | */ 46 | 47 | /** 48 | * @license React 49 | * scheduler.production.min.js 50 | * 51 | * Copyright (c) Facebook, Inc. and its affiliates. 52 | * 53 | * This source code is licensed under the MIT license found in the 54 | * LICENSE file in the root directory of this source tree. 55 | */ 56 | 57 | /** @license React v16.13.1 58 | * react-is.production.min.js 59 | * 60 | * Copyright (c) Facebook, Inc. and its affiliates. 61 | * 62 | * This source code is licensed under the MIT license found in the 63 | * LICENSE file in the root directory of this source tree. 64 | */ 65 | -------------------------------------------------------------------------------- /docs/build/assets/js/main.34e78845.js.LICENSE.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/main.34e78845.js.LICENSE.txt.gz -------------------------------------------------------------------------------- /docs/build/assets/js/main.34e78845.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/assets/js/main.34e78845.js.gz -------------------------------------------------------------------------------- /docs/build/assets/js/runtime~main.da02a9a5.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e,t,r,a,o,n={},c={};function i(e){var t=c[e];if(void 0!==t)return t.exports;var r=c[e]={id:e,loaded:!1,exports:{}};return n[e].call(r.exports,r,r.exports,i),r.loaded=!0,r.exports}i.m=n,i.c=c,e=[],i.O=(t,r,a,o)=>{if(!r){var n=1/0;for(u=0;u=o)&&Object.keys(i.O).every((e=>i.O[e](r[d])))?r.splice(d--,1):(c=!1,o0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[r,a,o]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,i.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var o=Object.create(null);i.r(o);var n={};t=t||[null,r({}),r([]),r(r)];for(var c=2&a&&e;"object"==typeof c&&!~t.indexOf(c);c=r(c))Object.getOwnPropertyNames(c).forEach((t=>n[t]=()=>e[t]));return n.default=()=>e,i.d(o,n),o},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((t,r)=>(i.f[r](e,t),t)),[])),i.u=e=>"assets/js/"+({48:"a94703ab",98:"a7bd4aaa",114:"1a20bc57",148:"9f70d1c7",256:"11b43341",401:"17896441",407:"cb769c5c",458:"93234bd6",472:"e228af67",539:"9beb87c2",581:"254e54e8",647:"5e95c892",742:"aba21aa0",792:"1b70f4c4",950:"35408621",976:"0e384e19"}[e]||e)+"."+{42:"0b64ebc5",48:"892c3022",98:"ee424588",114:"049e6787",148:"2d8489aa",151:"1ec91b9d",256:"83a6c715",401:"152c9fe7",407:"368c60a9",458:"a62a19f9",472:"92e2af36",539:"aa6ff69e",581:"17d8720b",647:"b907de86",742:"9d11f6df",792:"e5d9cf89",913:"1a07e874",950:"f546a790",976:"4874dedf"}[e]+".js",i.miniCssF=e=>{},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a={},o="@cloudpub/docs:",i.l=(e,t,r,n)=>{if(a[e])a[e].push(t);else{var c,d;if(void 0!==r)for(var f=document.getElementsByTagName("script"),u=0;u{c.onerror=c.onload=null,clearTimeout(s);var o=a[e];if(delete a[e],c.parentNode&&c.parentNode.removeChild(c),o&&o.forEach((e=>e(r))),t)return t(r)},s=setTimeout(b.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=b.bind(null,c.onerror),c.onload=b.bind(null,c.onload),d&&document.head.appendChild(c)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="/docs/",i.gca=function(e){return e={17896441:"401",35408621:"950",a94703ab:"48",a7bd4aaa:"98","1a20bc57":"114","9f70d1c7":"148","11b43341":"256",cb769c5c:"407","93234bd6":"458",e228af67:"472","9beb87c2":"539","254e54e8":"581","5e95c892":"647",aba21aa0:"742","1b70f4c4":"792","0e384e19":"976"}[e]||e,i.p+i.u(e)},(()=>{var e={354:0,869:0};i.f.j=(t,r)=>{var a=i.o(e,t)?e[t]:void 0;if(0!==a)if(a)r.push(a[2]);else if(/^(354|869)$/.test(t))e[t]=0;else{var o=new Promise(((r,o)=>a=e[t]=[r,o]));r.push(a[2]=o);var n=i.p+i.u(t),c=new Error;i.l(n,(r=>{if(i.o(e,t)&&(0!==(a=e[t])&&(e[t]=void 0),a)){var o=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;c.message="Loading chunk "+t+" failed.\n("+o+": "+n+")",c.name="ChunkLoadError",c.type=o,c.request=n,a[1](c)}}),"chunk-"+t,t)}},i.O.j=t=>0===e[t];var t=(t,r)=>{var a,o,n=r[0],c=r[1],d=r[2],f=0;if(n.some((t=>0!==e[t]))){for(a in c)i.o(c,a)&&(i.m[a]=c[a]);if(d)var u=d(i)}for(t&&t(r);f 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/build/img/inspector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/inspector.png -------------------------------------------------------------------------------- /docs/build/img/login-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/login-form.png -------------------------------------------------------------------------------- /docs/build/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/build/img/logo.svg.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/logo.svg.gz -------------------------------------------------------------------------------- /docs/build/img/minecraft-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/minecraft-server.jpg -------------------------------------------------------------------------------- /docs/build/img/publication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/publication.png -------------------------------------------------------------------------------- /docs/build/img/publish-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/publish-cam.png -------------------------------------------------------------------------------- /docs/build/img/rich-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/rich-gui.png -------------------------------------------------------------------------------- /docs/build/img/rtsp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/rtsp.jpg -------------------------------------------------------------------------------- /docs/build/img/tunnel.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/tunnel.jpeg -------------------------------------------------------------------------------- /docs/build/img/view-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/view-cam.png -------------------------------------------------------------------------------- /docs/build/img/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/img/welcome.png -------------------------------------------------------------------------------- /docs/build/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/index.html.gz -------------------------------------------------------------------------------- /docs/build/minecraft/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/minecraft/index.html.gz -------------------------------------------------------------------------------- /docs/build/rtsp/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/rtsp/index.html.gz -------------------------------------------------------------------------------- /docs/build/sitemap.xml: -------------------------------------------------------------------------------- 1 | https://cloudpub.online/docs/authweekly0.5https://cloudpub.online/docs/changelogweekly0.5https://cloudpub.online/docs/cliweekly0.5https://cloudpub.online/docs/dockerweekly0.5https://cloudpub.online/docs/httpweekly0.5https://cloudpub.online/docs/minecraftweekly0.5https://cloudpub.online/docs/rtspweekly0.5https://cloudpub.online/docs/tcpweekly0.5https://cloudpub.online/docs/webdavweekly0.5https://cloudpub.online/docs/weekly0.5 -------------------------------------------------------------------------------- /docs/build/tcp/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/tcp/index.html.gz -------------------------------------------------------------------------------- /docs/build/webdav/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/build/webdav/index.html.gz -------------------------------------------------------------------------------- /docs/en/.env: -------------------------------------------------------------------------------- 1 | # Nothing here 2 | -------------------------------------------------------------------------------- /docs/en/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/en/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /docs/en/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/en/docs/auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 15 3 | slug: /auth 4 | --- 5 | 6 | # Authentication and Access Control 7 | 8 | ## Authentication Types 9 | 10 | CloudPub supports two types of authentication: 11 | 12 | ### Basic Auth 13 | 14 | Basic Auth is a standard HTTP authentication method (RFC 7617) that: 15 | 16 | - Is supported by all protocols 17 | - Allows connection through both browser and other clients 18 | - Is ideal for WebDAV, allowing mounting as a network drive 19 | - Requires credentials to be transmitted with each request 20 | 21 | ### Form Auth 22 | 23 | Form Auth is authentication through an HTML form that: 24 | 25 | - Is supported by HTTP, HTTPS, and 1C protocols 26 | - Is designed for access through web browser 27 | - Can be used with WebDAV, but then access will only be possible through browser 28 | - Is more convenient for end users 29 | 30 | ## Authentication Support by Protocol 31 | 32 | | Protocol | Basic Auth | Form Auth | 33 | |----------|------------|-----------| 34 | | HTTP | ✓ | ✓ | 35 | | HTTPS | ✓ | ✓ | 36 | | WebDAV | ✓ | ✓* | 37 | | 1C | ✓ | ✓ | 38 | | TCP | ✓ | ✗ | 39 | | UDP | ✓ | ✗ | 40 | 41 | \* WebDAV with Form Auth is only accessible through browser 42 | 43 | ## Access Control (ACL) 44 | 45 | For each published resource, you can configure access rules by specifying: 46 | 47 | - User email 48 | - User role 49 | 50 | ### User Roles 51 | 52 | | Role | Description | 53 | |------|-------------| 54 | | admin | Full access to resource | 55 | | reader | Read-only access | 56 | | writer | Read and write access (only for WebDAV) | 57 | 58 | ### Rule Configuration 59 | 60 | Access rules are set when publishing a resource through the `--acl` parameter in the format `email:role`. 61 | You can specify multiple rules for different users. 62 | 63 | Example: 64 | ```bash 65 | clo publish --acl user@example.com:reader --acl admin@example.com:admin http 8080 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/en/docs/docker.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 98 3 | description: Using CloudPub with Docker 4 | slug: /docker 5 | --- 6 | 7 | # Docker Image 8 | 9 | ## Using CloudPub with Docker 10 | 11 | You can use the ready-made [Docker image](https://hub.docker.com/repository/docker/cloudpub/cloudpub/general) for the CloudPub agent. 12 | 13 | Example command to run a tunnel to port 8080 on the host machine looks like this: 14 | 15 | ```bash 16 | docker run --net=host -it -e TOKEN=xyz cloudpub/cloudpub:latest publish http 8080 17 | ``` 18 | 19 | :::tip 20 | The Docker version uses the same command line parameters as the regular version. 21 | ::: 22 | 23 | For macOS or Windows users, the `--net=host` option will not work. 24 | 25 | You will need to use the special URL host.docker.internal, as described in the Docker [documentation](https://docs.docker.com/desktop/mac/networking/#use-cases-and-workarounds). 26 | 27 | ```bash 28 | docker run --net=host -it -e TOKEN=xyz cloudpub/cloudpub:latest \ 29 | publish http host.docker.internal:8080 30 | ``` 31 | 32 | ## Preserving Settings on Container Restart 33 | 34 | When starting a container, CloudPub creates a new agent and a new unique URL for tunnel access. 35 | 36 | To preserve settings on container restart, you should create a volume for storing configuration and cache: 37 | 38 | ```bash 39 | docker volume create cloudpub-config 40 | ``` 41 | 42 | Then, when starting the container, you should use this volume: 43 | 44 | ```bash 45 | docker run -v cloudpub-config:/home/cloudpub --net=host -it -e TOKEN=xyz \ 46 | cloudpub/cloudpub:latest publish http 8080 47 | ``` 48 | 49 | In this case, all agent settings will be saved in the `cloudpub-config` volume and will be available on the next container start. 50 | 51 | ## Publishing Multiple Resources at Once 52 | 53 | You can specify multiple resources for publication in environment variables, separating them with commas: 54 | 55 | ```bash 56 | docker run -v cloudpub-config:/home/cloudpub --net=host -it\ 57 | -e TOKEN=xyz \ 58 | -e HTTP=8080,8081 \ 59 | -e HTTPS=192.168.1.1:80 \ 60 | cloudpub/cloudpub:latest run 61 | ``` 62 | 63 | The environment variable name matches the protocol name. The following protocols are available: 64 | 65 | * HTTP 66 | * HTTPS 67 | * TCP 68 | * UDP 69 | * WEBDAV 70 | * MINECRAFT 71 | 72 | ## Version for ARM Processors 73 | 74 | For ARM processors, the image `cloudpub/cloudpub:latest-arm64` is available 75 | -------------------------------------------------------------------------------- /docs/en/docs/http.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | slug: /http 4 | --- 5 | 6 | # HTTP and HTTPS Services 7 | 8 | ## Publishing HTTP Services 9 | 10 | To publish a local HTTP server running on a local interface, simply execute the command: 11 | 12 | ```bash 13 | clo publish http 8080 14 | ``` 15 | 16 | where 8080 is the port on which your server is running. 17 | 18 | After executing the command, you will receive a message that your service has been published: 19 | 20 | ```bash 21 | Service published: http://localhost:8080 -> https://wildly-suitable-fish.cloudpub.online 22 | ``` 23 | 24 | The service will be publicly available via HTTPS protocol, and we will automatically generate a certificate for this domain. 25 | 26 | If you need to publish a service running on another host in the local network, you can specify the IP address or host when publishing: 27 | 28 | ```bash 29 | clo publish http 192.168.1.1:80 30 | ``` 31 | 32 | In this case, the service will be published on the specified IP address and port (in this example, it could be your router's admin panel) 33 | 34 | ## Publishing HTTPS Services 35 | 36 | Publishing HTTPS services is similar to publishing HTTP services, but with specifying the HTTPS protocol: 37 | 38 | ```bash 39 | clo publish https 443 40 | ``` 41 | 42 | ## HTTP and HTTPS Request Headers 43 | 44 | When publishing HTTP and HTTPS services, you can override or specify additional headers that will be added to requests sent to your local server. 45 | 46 | This can be useful if your server requires certain headers to work, for example, a `Host` header matching the local server address (`localhost`) 47 | 48 | ```bash 49 | clo publish -H Host:localhost https 443 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/en/docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: / 4 | --- 5 | 6 | import { Downloads, getUrl, getFile } from 'src/app/components/downloads'; 7 | import CodeBlock from '@theme/CodeBlock'; 8 | 9 | # Quick Start 10 | 11 | How to start using **CloudPub in 5 minutes**. 12 | 13 | ## Install the Client 14 | 15 | 16 | 17 | ## Graphical Interface Application 18 | 19 | - Create an account in the [personal account](https://cloudpub.online/dashboard) 20 | - Launch the application (executable file is called `cloudpub`) 21 | - Authenticate: 22 | 23 | ![Authentication](/img/login-form.png) 24 | 25 | - Click the `New Publication` button 26 | - Select the type of resource you want to publish 27 | - Enter the required data: 28 | 29 | ![Publication](/img/publication.png) 30 | 31 | - Click the `Publish` button 32 | - After this, you will be provided with a URL where the resource will be accessible on the internet 33 | 34 | ## Command Line Utility 35 | 36 | ### Windows {#windows} 37 | 38 | - Download the archive: {getFile('windows', 'x86_64')} 39 | - Extract the archive to any folder. For convenience, we recommend extracting the archive and adding the folder path to the PATH variable. 40 | - Press `Win + R` 41 | - Type `cmd.exe` and press `Enter` 42 | - In the opened window, type `cd ` and press `Enter`* 43 | 44 | * This step is not required if you added the folder path to the PATH variable. 45 | 46 | #### Adding Path to PATH Variable 47 | 48 | To add the folder path to the PATH variable, follow these steps: 49 | 50 | - Right-click on "My Computer" and select "Properties". 51 | - In the opened system properties window, click on "Advanced system settings" on the left. 52 | - In the system properties window, click the "Environment Variables" button. 53 | - In the environment variables window, under "System Variables" or "User Variables" select the "Path" variable and click "Edit". 54 | - In the environment variable edit window, click "New" and add the path to the folder where you extracted the archive. For example, if the path is `C:\path\to\your\folder`, add `C:\path\to\your\folder` as a new entry. 55 | - Click "OK" in all windows to save the changes. 56 | - To apply the changes, you may need to restart all open command prompt windows. 57 | 58 | ### Linux {#linux} 59 | 60 | - Open terminal 61 | - Download the archive using the command 62 | 63 | wget {getUrl('linux', 'x86_64')} 64 | 65 | - Extract the archive using the command 66 | 67 | tar -xvf {getFile('linux', 'x86_64')} 68 | 69 | ### MacOS {#macos} 70 | 71 | - Open terminal 72 | - Download and extract the archive for your architecture: 73 | 74 | #### Apple Silicon: 75 | 76 | curl {getUrl('macos', 'aarch64')} -o {getFile('macos', 'aarch64')} 77 | tar -xvf {getFile('macos', 'aarch64')} 78 | 79 | #### Intel: 80 | 81 | curl {getUrl('macos', 'x86_64')} -o {getFile('macos', 'x86_64')} 82 | tar -xvf {getFile('macos', 'x86_64')} 83 | 84 | ## Link Your Account 85 | 86 | If you haven't done so already, create an account in the [personal account](https://cloudpub.online/dashboard). After that, link your account to the client by executing the following command: 87 | 88 | ```bash 89 | clo set token 90 | ``` 91 | 92 | You can find your token on the main page in the personal account after registration. 93 | 94 | Starting from client version 1.6, you can authenticate using the command: 95 | 96 | ```bash 97 | clo login 98 | ``` 99 | 100 | :::note 101 | On Linux and MacOS, you need to specify the path to the `clo` file, even if it's in the current directory: 102 | 103 | ```bash 104 | ./clo login 105 | ``` 106 | ::: 107 | 108 | ## Publish Your First Resource 109 | 110 | To publish a local HTTP server running on port 8080, execute the command: 111 | 112 | ```bash 113 | clo publish http 8080 114 | ``` 115 | 116 | After this, you will be provided with a URL where your resource will be accessible on the internet, for example: 117 | 118 | ```bash 119 | Service published: http://localhost:8080 -> https://wildly-suitable-fish.cloudpub.online 120 | ``` 121 | 122 | In this case, your resource will be accessible at `https://wildly-suitable-fish.cloudpub.online`. 123 | 124 | Your resource URL will differ from the one shown in the example. 125 | -------------------------------------------------------------------------------- /docs/en/docs/minecraft.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | slug: /minecraft 4 | --- 5 | 6 | # Minecraft Server 7 | 8 | ## Publishing Minecraft Server on the Internet 9 | 10 | CloudPub allows you to publish Minecraft servers on the internet so your friends can connect to it from anywhere in the world. 11 | 12 | If you're not using mods, this is very simple. You need to specify the path to the Minecraft server folder, and CloudPub will automatically configure all necessary parameters. 13 | 14 | ### Graphical Interface Application 15 | 16 | Select the publication type `minecraft` and specify the path to the folder where the server will be installed. 17 | 18 | ### Command Line 19 | 20 | ```bash 21 | clo publish minecraft [path to server folder] 22 | ``` 23 | 24 | After this, you will be provided with a URL where your server will be accessible on the internet, for example: 25 | 26 | ```bash 27 | Service published: minecraft://C:\Minecraft -> minecraft://minecraft.cloudpub.online:32123 28 | ``` 29 | 30 | The address specified after the arrow (`-> minecraft://`) is the address that players need to enter the game. 31 | 32 | In the example above, this is `minecraft.cloudpub.online:32123` 33 | 34 | ### Server with Mods 35 | 36 | If you're using a server with mods, use the [TCP service publication instructions](/docs/tcp). 37 | 38 | The port that needs to be opened for connecting to the Minecraft server is 25565 by default, but can be changed in the server settings. 39 | 40 | This is described in more detail in the [official Minecraft documentation](https://minecraft.fandom.com/wiki/Tutorials/Setting_up_a_server). 41 | -------------------------------------------------------------------------------- /docs/en/docs/rtsp.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | slug: /rtsp 4 | --- 5 | 6 | # RTSP Video Streams 7 | 8 | With CloudPub you can publish RTSP video streams from surveillance cameras. 9 | 10 | This allows you to access your cameras from the internet without opening ports on your router. 11 | 12 | Additionally, you can view video streams in your personal account or the CloudPub application. 13 | 14 | ## RTSP Protocol 15 | 16 | Video streams are published using the RTSP protocol. 17 | 18 | This means you can use any RTSP player to access the video streams. 19 | 20 | For example, in Windows 10 this can be done through VLC Media Player, in macOS - through QuickTime Player. 21 | 22 | Simply open the player and enter the RTSP stream address provided by CloudPub. 23 | 24 | ### Graphical Interface Application 25 | 26 | Select the publication type `Surveillance Camera (RTSP)` and enter the URL of your RTSP stream. 27 | 28 | ### Command Line 29 | 30 | ```bash 31 | clo publish rtsp "[RTSP stream URL]" 32 | ``` 33 | 34 | After this, you will be provided with a URL where your RTSP video stream will be accessible. 35 | 36 | ```bash 37 | Service published: rtsp://192.168.0.100:554/stream0 -> rtsp://rtsp.cloudpub.online:51243/stream0 38 | ``` 39 | 40 | The address specified after the arrow will be accessible from the internet. 41 | 42 | You can view published streams in the "Video Streams" section of your personal account or application. 43 | -------------------------------------------------------------------------------- /docs/en/docs/tcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | slug: /tcp 4 | --- 5 | 6 | # TCP and UDP Services 7 | 8 | ## Publishing TCP Services 9 | 10 | Publishing a service running on TCP protocol is done similarly to publishing an HTTP service, but with specifying the TCP protocol: 11 | 12 | ```bash 13 | clo publish tcp 22 14 | ``` 15 | 16 | In this example, we are publishing a service running on port 22 (SSH). 17 | 18 | Unlike HTTP services, TCP services do not get a unique domain name and are only available at the address `tcp.cloudpub.online` with a unique port. 19 | 20 | Just like with HTTP services, you can specify the address of any host in the local network: 21 | 22 | ```bash 23 | clo publish tcp myserver:3389 24 | ``` 25 | 26 | In this example, we are publishing a service running on port 3389 (RDP) on host `myserver`. 27 | 28 | ## Publishing UDP Services 29 | 30 | Publishing a service running on UDP protocol is done similarly to publishing a TCP service, but with specifying the UDP protocol: 31 | 32 | ```bash 33 | clo publish udp 53 34 | ``` 35 | 36 | In this example, we are publishing a service running on port 53 (DNS). 37 | -------------------------------------------------------------------------------- /docs/en/docs/webdav.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | slug: /webdav 4 | --- 5 | 6 | # File Publishing 7 | 8 | With CloudPub you can publish files and folders to share them with other users. 9 | 10 | Additionally, this allows you to manage your files without uploading them to third-party services. 11 | 12 | ## WebDAV Protocol 13 | 14 | Files are published using the WebDAV protocol. 15 | 16 | This means you can use any WebDAV client to access the files. 17 | 18 | For example, in Windows 10 this can be done through File Explorer, in macOS - through Finder. 19 | 20 | Simply open File Explorer or Finder, enter the address provided by CloudPub, and enter your login and password. 21 | 22 | After that, you will be able to work with files just like regular files on your computer. 23 | 24 | ### Graphical Interface Application 25 | 26 | Select the publication type `File Folder (WebDAV)` and specify the path to the folder where the server will be installed. 27 | 28 | ### Command Line 29 | 30 | ```bash 31 | clo publish webdav "[folder path]" 32 | ``` 33 | 34 | After this, you will be provided with a URL where your files will be accessible. 35 | 36 | ```bash 37 | Service published: webdav://C:\Users\Administrator -> https://indelibly-fearless-jackdaw.cloudpub.local 38 | ``` 39 | 40 | The address specified after the arrow will be accessible from the internet. 41 | 42 | To access files, you will need to enter a login and password. Your email is used as the login, and the password matches your account password. 43 | 44 | You can manage files from the "File Manager" section in your personal account. 45 | 46 | If you need to provide access to a file to other users, you can generate a download link for the file there. 47 | -------------------------------------------------------------------------------- /docs/en/docusaurus.config.ts: -------------------------------------------------------------------------------- 1 | import { themes as prismThemes } from "prism-react-renderer"; 2 | import type { Config } from "@docusaurus/types"; 3 | import type * as Preset from "@docusaurus/preset-classic"; 4 | import path from "path"; 5 | 6 | process.env.IS_PREACT = "false"; 7 | 8 | const config: Config = { 9 | title: "CloudPub", 10 | tagline: "From local to global with one click", 11 | favicon: "img/favicon.ico", 12 | 13 | // Set the production url of your site here 14 | url: "https://cloudpub.online", 15 | // Set the // pathname under which your site is served 16 | // For GitHub pages deployment, it is often '//' 17 | baseUrl: "/docs/", 18 | 19 | // GitHub pages deployment config. 20 | // If you aren't using GitHub pages, you don't need these. 21 | organizationName: "cloudpub", // Usually your GitHub org/user name. 22 | projectName: "cloudpub", // Usually your repo name. 23 | 24 | onBrokenLinks: "throw", 25 | onBrokenMarkdownLinks: "warn", 26 | 27 | staticDirectories: ["public", "static"], 28 | 29 | // Even if you don't use internationalization, you can use this field to set 30 | // useful metadata like html lang. For example, if your site is Chinese, you 31 | // may want to replace "en" with "zh-Hans". 32 | i18n: { 33 | defaultLocale: "en", 34 | locales: ["en"], 35 | }, 36 | plugins: [ 37 | [ 38 | "docusaurus-plugin-module-alias", 39 | { 40 | alias: { 41 | src: path.resolve(__dirname, "../../frontend/src"), 42 | }, 43 | }, 44 | ], 45 | [ 46 | "docusaurus-plugin-dotenv", 47 | { 48 | path: "./.env", 49 | systemvars: true, 50 | }, 51 | ], 52 | ], 53 | presets: [ 54 | [ 55 | "classic", 56 | { 57 | docs: { 58 | sidebarPath: "./sidebars.ts", 59 | routeBasePath: "/", 60 | }, 61 | theme: { 62 | customCss: "./src/css/custom.css", 63 | }, 64 | } satisfies Preset.Options, 65 | ], 66 | ], 67 | 68 | themeConfig: { 69 | image: "img/welcome.png", 70 | navbar: { 71 | title: "CloudPub", 72 | logo: { 73 | alt: "CloudPub Logo", 74 | src: "img/logo.svg", 75 | href: "https://cloudpub.online", 76 | target: "_self", 77 | }, 78 | items: [ 79 | { 80 | type: "docSidebar", 81 | sidebarId: "tutorialSidebar", 82 | position: "left", 83 | label: "Documentation", 84 | }, 85 | ], 86 | }, 87 | footer: { 88 | style: "dark", 89 | copyright: `Copyright © ${new Date().getFullYear()} CloudPub`, 90 | }, 91 | prism: { 92 | theme: prismThemes.github, 93 | darkTheme: prismThemes.dracula, 94 | }, 95 | } satisfies Preset.ThemeConfig, 96 | }; 97 | 98 | export default config; 99 | -------------------------------------------------------------------------------- /docs/en/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cloudpub/docs", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "^3.7.0", 19 | "@docusaurus/preset-classic": "^3.7.0", 20 | "@mdx-js/react": "^3.0.0", 21 | "clsx": "^2.0.0", 22 | "prism-react-renderer": "^2.3.0", 23 | "react": "^18.0.0", 24 | "react-dom": "^18.0.0" 25 | }, 26 | "devDependencies": { 27 | "@cloudpub/frontend": "file:../frontend/dist", 28 | "@docusaurus/module-type-aliases": "^3.7.0", 29 | "@docusaurus/tsconfig": "^3.7.0", 30 | "@docusaurus/types": "^3.7.0", 31 | "docusaurus-plugin-dotenv": "^1.0.1", 32 | "docusaurus-plugin-module-alias": "^0.0.2", 33 | "typescript": "~5.5.2" 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.5%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 3 chrome version", 43 | "last 3 firefox version", 44 | "last 5 safari version" 45 | ] 46 | }, 47 | "engines": { 48 | "node": ">=18.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/en/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; 2 | import { TEST } from '@cloudpub/frontend'; 3 | 4 | /** 5 | * Creating a sidebar enables you to: 6 | - create an ordered group of docs 7 | - render a sidebar for each doc of that group 8 | - provide next/previous navigation 9 | 10 | The sidebars can be generated from the filesystem, or explicitly defined here. 11 | 12 | Create as many sidebars as you want. 13 | */ 14 | const sidebars: SidebarsConfig = { 15 | // By default, Docusaurus generates a sidebar from the docs folder structure 16 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 17 | 18 | // But you can create a sidebar manually 19 | /* 20 | tutorialSidebar: [ 21 | 'intro', 22 | 'hello', 23 | { 24 | type: 'category', 25 | label: 'Tutorial', 26 | items: ['tutorial-basics/create-a-document'], 27 | }, 28 | ], 29 | */ 30 | }; 31 | 32 | export default sidebars; 33 | -------------------------------------------------------------------------------- /docs/en/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | 32 | img[src*='#center'] { 33 | display: block; 34 | margin: auto; 35 | } 36 | -------------------------------------------------------------------------------- /docs/en/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/.nojekyll -------------------------------------------------------------------------------- /docs/en/static/img/1c-publish0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-publish0.png -------------------------------------------------------------------------------- /docs/en/static/img/1c-publish1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-publish1.png -------------------------------------------------------------------------------- /docs/en/static/img/1c-publish2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-publish2.png -------------------------------------------------------------------------------- /docs/en/static/img/1c-publish3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-publish3.png -------------------------------------------------------------------------------- /docs/en/static/img/1c-publish4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-publish4.png -------------------------------------------------------------------------------- /docs/en/static/img/1c-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-server.jpg -------------------------------------------------------------------------------- /docs/en/static/img/1c-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/1c-server.png -------------------------------------------------------------------------------- /docs/en/static/img/card1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/card1.png -------------------------------------------------------------------------------- /docs/en/static/img/card2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/card2.png -------------------------------------------------------------------------------- /docs/en/static/img/card3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/card3.png -------------------------------------------------------------------------------- /docs/en/static/img/card4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/card4.png -------------------------------------------------------------------------------- /docs/en/static/img/card5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/card5.png -------------------------------------------------------------------------------- /docs/en/static/img/clouds.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/clouds.jpeg -------------------------------------------------------------------------------- /docs/en/static/img/django_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/django_logo.png -------------------------------------------------------------------------------- /docs/en/static/img/django_publish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/django_publish.png -------------------------------------------------------------------------------- /docs/en/static/img/favicon.ico: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/en/static/img/inspector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/inspector.png -------------------------------------------------------------------------------- /docs/en/static/img/login-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/login-form.png -------------------------------------------------------------------------------- /docs/en/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/en/static/img/minecraft-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/minecraft-server.jpg -------------------------------------------------------------------------------- /docs/en/static/img/publication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/publication.png -------------------------------------------------------------------------------- /docs/en/static/img/publish-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/publish-cam.png -------------------------------------------------------------------------------- /docs/en/static/img/rich-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/rich-gui.png -------------------------------------------------------------------------------- /docs/en/static/img/rtsp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/rtsp.jpg -------------------------------------------------------------------------------- /docs/en/static/img/tunnel.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/tunnel.jpeg -------------------------------------------------------------------------------- /docs/en/static/img/view-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/view-cam.png -------------------------------------------------------------------------------- /docs/en/static/img/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/en/static/img/welcome.png -------------------------------------------------------------------------------- /docs/en/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/ru/.env: -------------------------------------------------------------------------------- 1 | # Nothing here 2 | -------------------------------------------------------------------------------- /docs/ru/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/ru/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /docs/ru/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-09-01-welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CloudPub — отечественная альтернатива ngrok 3 | description: CloudPub — российский сервис для безопасного туннелирования и удаленного доступа к локальным серверам. Идеальная альтернатива ngrok для разработчиков и компаний в России. 4 | slug: welcome 5 | --- 6 | 7 | ![CloudPub](/img/welcome.png#center) 8 | 9 | Потрясающая новость для всего отечественного ИТ-сообщества - совсем недавно появился полноценный российский аналог популярного зарубежного сервиса ngrok. CloudPub является надежным проводником для ваших проектов, делая их доступными и видимыми. 10 | 11 | 12 | 13 | CloudPub — это инновационная платформа для соединения ваших приложений и API с внешним миром. 14 | 15 | Сервис способен похвастаться целым рядом преимуществ: 16 | 17 | - простота использования: забудьте о сложных настройках, CloudPub делает процесс простым и интуитивно понятным; 18 | - бесплатная версия CloudPub доступна для всех новых пользователей; 19 | - безопасная передача данных с использованием протокола HTTPS, которая обеспечивая надежность и защиту. 20 | 21 | Для запуска CloudPub можно воспользоваться простой пошаговой инструкцией: 22 | 23 | 1. Для начала зарегистрируйтесь на сайте https://cloudpub.ru 24 | 1. Затем скачайте и установите приложение на ваш компьютер. 25 | 1. С запуском CloudPub перед вами откроется множество новых возможностей, позволяющих получить удаленный доступ к вашим проектам. 26 | 27 | CloudPub — это безопасность и качество российской разработки, несущие минимум рисков. 28 | 29 | CloudPub был создан в России, что обеспечивает беспрецедентную стабильность и надежность в работе с вашими местными проектами. Это также позволяет избежать рисков, связанных с ограничениями и санкциями. 30 | 31 | Если у вас остались какие-либо дополнительные вопросы, более подробно с сервисом CloudPub вы можете ознакомиться непосредственно на сайте https://cloudpub.ru 32 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-10-11-minecraft.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cвой сервер Minecraft за одну минуту 3 | description: "Как опубликовать сервер Minecraft в интернете с помощью CloudPub" 4 | slug: minecraft 5 | --- 6 | 7 | ![Minecraft](/img/minecraft-server.jpg) 8 | 9 | # Самый простой способ публикации сервера Minecraft 10 | 11 | Каждый фанат Minecraft хотя бы раз задумывался о создании собственного серверного мира, где можно пригласить друзей и играть вместе. Однако многие сталкиваются с проблемой публикации сервера в интернете. С помощью CloudPub это становится простым и доступным процессом. 12 | 13 | 14 | 15 | ## Публикация сервера Minecraft в интернете 16 | 17 | CloudPub — это удобный инструмент, который позволяет сделать ваш Minecraft сервер доступным в интернете, чтобы ваши друзья могли подключаться к нему из любой точки мира. Основным преимуществом CloudPub является его простота и скорость. Независимо от уровня вашего технического опыта, вы сможете быстро и легко настроить свой сервер. 18 | 19 | ### Как опубликовать сервер, если вы не используете моды 20 | 21 | Если вы планируете запустить стандартный сервер Minecraft без модов, то процесс будет максимально простым. 22 | 23 | #### Процесс публикации 24 | 25 | 1. Укажите путь к серверу: Сначала укажите путь к пустой папке, в которой будет установлен ваш новый сервер Minecraft. Это можно сделать с помощью графического интерфейса или командной строки. 26 | 27 | 2. Использование графического интерфейса: 28 | - Откройте приложение CloudPub. 29 | - Выберите тип публикации "minecraft". 30 | - Укажите путь к папке для установки сервера Minecraft. 31 | 32 | 3. Командная строка: 33 | 34 | - Выполните команду в терминале: 35 | 36 | ``` 37 | clo publish minecraft [путь к папке с сервером] 38 | ``` 39 | 40 | 41 | После выполнения этих действий CloudPub самостоятельно настроит все необходимые параметры. Вам будет предоставлен URL, с помощью которого сервер станет доступен в интернете. Например: 42 | 43 | ``` 44 | Service published: minecraft://C:\Minecraft -> minecraft://minecraft.cloudpub.ru:32123 45 | ``` 46 | 47 | Адрес, который следует использовать для входа в игру, указан после стрелки. В данном примере это `minecraft.cloudpub.ru:32123`. Просто делитесь этим адресом с друзьями, и они смогут подключиться к вашему серверу. 48 | 49 | ### Публикация сервера с модами 50 | 51 | Если ваш сервер использует моды, вам потребуется немного иная настройка. Следуйте инструкции по [публикации TCP сервиса](/docs/tcp), доступной в документации CloudPub. Как правило, сервер Minecraft использует порт 25565, но вы можете изменить этот порт в настройках сервера, если потребуется. 52 | 53 | ### Полезные рекомендации 54 | 55 | - Убедитесь, что ваш сервер работает корректно перед публикацией. 56 | - Проверьте текущую версию Minecraft и моды на совместимость. 57 | - Ознакомьтесь с официальной документацией Minecraft для более детального понимания настройки серверов с модами. 58 | 59 | Воспользовавшись CloudPub, вы сможете наслаждаться игрой вместе с друзьями без лишних технических сложностей! 60 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-10-17-logs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Инспекция трафика 3 | description: Современный аналог PCAP в облаке. 4 | slug: inspector 5 | --- 6 | 7 | ![Инспектор трафика](/img/inspector.png) 8 | 9 | Одним из больших преимуществ использования шлюза между вашим приложением и интернетом является возможность анализа трафика. 10 | 11 | Возможность просмотра запросов, поступающих на ваш API или сервис, дает четкое понимание происходящего в вашей сети, позволяя быстро обнаруживать и устранять проблемы в вашем приложении с минимальным влиянием на клиентов. 12 | 13 | Сегодня мы рады объявить о нашем новом облачном инструменте, который доступен без ограничений для всех разработчиков. 14 | Он предоставляет вам полный обзор HTTP-трафика, проходящего через ваш аккаунт, прямо из панели управления. 15 | 16 | 17 | 18 | Для использования инспектора трафика вам необходимо включить его в настройках вашего аккаунта. После этого вы сможете просматривать все запросы, поступающие на ваше приложение, а также отправляемые им. 19 | 20 | Для включения инспектора трафика перейдите в раздел "Профиль", переключитесь на вкладку "Настройки" и включите опции: 21 | 22 | * Запись HTTP заголовков 23 | * Запись тела HTTP запроса 24 | 25 | С этого момента заголовки и тело HTTP запросов будут доступны в разделе [Инспектор запросов](https://cloudpub.ru/dashboard/logs/). 26 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-11-10-version-1.2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Новые функции в CloudPub 1.2 3 | description: "Презентация нового интерфейса приложения CloudPub: весь функционал в одном приложении!" 4 | slug: version-1.2 5 | image: /img/rich-gui.png 6 | --- 7 | 8 | ![Новый интерфейс](/img/rich-gui.png) 9 | 10 | # Презентация нового интерфейса приложения CloudPub: весь функционал в одном приложении! 11 | 12 | ## Дорогие пользователи! 13 | 14 | Мы рады представить вам долгожданное обновление нашего приложения CloudPub, которое теперь включает в себя весь функционал, ранее доступный только в WEB версии. Мы тщательно работали над улучшением пользовательского интерфейса и добавлением всех необходимых функций, чтобы сделать использование CloudPub ещё более удобным и эффективным. 15 | 16 | 17 | 18 | ## Что нового? 19 | 20 | ### Полный функционал в одном приложении 21 | 22 | Теперь вы можете наслаждаться всем спектром возможностей CloudPub в загружаемом приложении c графическим интерфейсом. Все инструменты и функции, которые вы привыкли использовать в веб-версии, теперь доступны локально. Это означает, что публикация ресурсов, инспекция трафика, управление аккаунтом и многое другое – у вас под рукой в любой момент, 23 | 24 | ### Поддержка WebDAV протокола 25 | 26 | В рамках обновления мы добавили поддержку [протокола WebDAV](/docs/webdav), что открывает новые возможности для интеграции и взаимодействия с другими сервисами и приложениями. WebDAV позволяет вам управлять файлами непосредственно в проводнике Windows и других приложениях, которые поддерживают этот протокол. 27 | 28 | Кроме того, теперь вы можете делится файлами с коллегами и друзьями, используя общие папки и доступ к файлам по ссылке. Это удобный способ обмениваться информацией и совместно работать над проектами, не теряя времени на сложные настройки и установку дополнительных программ. 29 | 30 | ### Образ для Docker 31 | 32 | Мы опубликовали [образ CloudPub для Docker](/docs/docker), который позволяет вам быстро и легко развернуть приложение на любом сервере, поддерживающем контейнеры. Это удобное решение для тех, кто хочет быстро начать использовать CloudPub без необходимости установки и настройки приложения вручную. 33 | 34 | ### Обновленный дизайн 35 | 36 | Мы пересмотрели дизайн приложения, чтобы сделать его более интуитивным и современным. Новый интерфейс отличается лёгкостью навигации и эстетичной простотой, что позволяет вам быстрее и удобнее выполнять повседневные задачи. 37 | 38 | ### Улучшенная производительность 39 | 40 | Мы оптимизировали приложение под различные устройства, чтобы обеспечить вам максимально плавную и быструю работу. Независимо от мощности вашего устройства, CloudPub будет работать стабильно и без сбоев. 41 | 42 | Новое обновление приложения CloudPub - это важный шаг к улучшению вашего опыта работы с нашими продуктами. Мы уверены, что теперь вы сможете выполнять свои задачи ещё быстрее и удобнее. Установите обновленную версию прямо сейчас и оцените все преимущества нашего приложения на практике! 43 | 44 | С благодарностью за ваше доверие и выбор CloudPub – команда разработчиков. 45 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-11-25-django.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Публикация локального сервера Django 3 | description: Инструкция по публикации локального сервера Django в интернет с помощью CloudPub. 4 | slug: django 5 | image: /img/django_logo.png 6 | --- 7 | 8 | # Публикация локального сервера Django в Интернет 9 | 10 | ![Django Logo](/img/django_logo.png) 11 | 12 | Используя туннель, можно без труда передавать информацию между различными сетями, обеспечивая безопасность данных. 13 | 14 | Это делает возможным соединение вашего локально подключенного компьютера с сайтом через интернет. 15 | 16 | В ситуациях, когда прямое соединение между двумя устройствами затруднено из-за сетевых ограничений, таких как брандмауэры, NAT или списки контроля доступа, применяется HTTP-туннелирование. Для установления такого соединения используется прокси-сервер, действующий как посредник. 17 | 18 | CloudPub представляет собой инструмент, который облегчает задачу создания туннелей, тем самым предоставляя возможность доступа к локальному порту напрямую из сети интернет, минуя необходимость настройки сетевых протоколов. 19 | 20 | 21 | 22 | Работа CloudPub заключается в формировании защищенного соединения между вашим личным компьютером и специализированным удаленным сервером, причем доступ к созданному туннелю осуществляется через уникальный сгенерированный сервисом домен. 23 | 24 | Для начала работы с утилитой достаточно пройти процедуру регистрации на официальном сайте сервиса, скачать и установить программное обеспечение на ваш ПК, а затем активировать процесс создания туннеля согласно предоставленной инструкции. 25 | 26 | Итак, начнем с того, что у нас уже имеется проект на Django, который успешно функционирует и доступен по адресу http://localhost:8080 в локальной сети. 27 | 28 | Шаги для дальнейших действий выглядят так: 29 | 30 | 1. Для начала, нам нужно посетить сайт https://cloudpub.ru/, который является официальным ресурсом. 31 | 32 | 2. Следующим шагом будет загрузка приложения, которое соответствует версии вашей операционной системы. Примером может служить система Windows 10 с 64-битной архитектурой. 33 | 34 | 3. Загрузите и запустите приложение с графическим интерфейсом, наиболее простое в использовании для начинающих пользователей. 35 | 36 | 4. В появившемся окне проходим процедуру регистрации и осуществляем подтверждение электронной почту. Приятно заметить, что этот этап не требует финансовых затрат. 37 | 38 | Почти готово. Осталось опубликовать ваш локальный сервер, создав новую публикацию: 39 | 40 | ![Публикация локального сервера](/img/django_publish.png) 41 | 42 | После выполнения появится список ваших публикаций, где в разделе «Публичный адрес» будет создана уникальная ссылка. 43 | 44 | Эта ссылка делает ваше Django-приложение, работающее на порте 8080, открытым для доступа извне. 45 | 46 | Следующий шаг — распространите ее среди коллег, клиентов или других заинтересованных сторон, чтобы они могли получить доступ к приложению. 47 | 48 | Ссылка остается активной до момента закрытия вашего сеанса в CloudPub. 49 | 50 | В заключение отмечу, что в интерфейсе CloudPub-клиента представлена возможность просмотра истории запросов, дающая понимание о полученных данных и ответах, а также позволяющая повторно отправить или изменить запросы среди прочих функций. 51 | 52 | С помощью CloudPub можно эффективно создавать туннели и делать локальный порт доступным в интернете, причем без особых сложностей. 53 | -------------------------------------------------------------------------------- /docs/ru/blog/2024-12-17-version-1.3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Новые функции в CloudPub 1.3 3 | description: "Новые функции CloudPub: Авторизация сервисов, поддержка новых архитектур, геолокация и улучшения безопасности." 4 | slug: version-1.3 5 | image: /img/clouds.jpeg 6 | --- 7 | 8 | ![CloudPub верcия 1.3](/img/clouds.jpeg) 9 | 10 | ## Обновление CloudPub: Новые горизонты для вашего сервиса 11 | 12 | Мы рады сообщить о последнем обновлении CloudPub — вашего надежного партнера для обеспечения защищенного и доступного доступа к локальным сервисам через интернет! За последние несколько недель мы активно работали над улучшением функциональности и расширением возможностей сервиса. Вот основные изменения, которые появились в облачном туннелировании с CloudPub. 13 | 14 | 15 | 16 | - **Поддержка собственных доменов:** Теперь вы можете подключать свои домены второго и третьего уровня для использования с CloudPub, а также автоматизировать генерацию сертификатов через Let's Encrypt. 17 | 18 | - **Приглашение пользователей в команду:** С легкостью добавляйте новых участников в вашу команду и управляйте доступом. 19 | 20 | - **Поддержка авторизации через HTML форму:** Теперь ваши сервисы могут использовать HTML формы для аутентификации пользователей, что значительно упрощает интеграцию и повышает безопасность. 21 | 22 | - **Basic авторизация:** Стандартый метод аутентификации позволяет безопасно монтировать WebDAV ресурсы 23 | 24 | - **Права доступа к WebDAV:** Управляйте правами доступа к вашим WebDAV ресурсам прямо через CloudPub. 25 | - **Поддержка новых архитектур:** Мы расширили поддержку Linux, добавив архитектуры `arm`,`armv5te` и `aarch64`. Это открывает двери для использования CloudPub на более широком круге устройств и систем, таких как камеры видеонаблюдения, микроконтроллеры и сервера synology. 26 | 27 | - **Геолокация в инспекторе трафика:** Теперь вы можете видеть откуда поступают запросы в реальном времени, что позволяет лучше анализировать и управлять потоками трафика. 28 | 29 | - **Поддержка локального jar для Minecraft:** Запуск вашего Minecraft сервера через CloudPub стал проще благодаря возможности указать локальный jar файл. 30 | 31 | - **Отслеживание ошибок сети клиента:** Теперь сервер может отслеживать сетевые ошибки клиента, что упрощает диагностику и исправление проблем. 32 | 33 | - **Опция unsafe_tls:** Для опытных пользователей добавлена опция игнорирования ошибок сертификата, позволяющая подключаться к серверам с нестандартными сертификатами. 34 | 35 | Эти обновления делают CloudPub еще более гибким и мощным инструментом для разработчиков и компаний, предоставляя улучшенные возможности управления и безопасности для ваших сервисов. Мы ценим ваш выбор CloudPub и продолжаем усердно работать над его улучшением. Ваши отзывы и предложения всегда помогают нам развиваться в правильном направлении. 36 | 37 | Присоединяйтесь к нам и следите за последними обновлениями на нашем блоге! Если у вас есть вопросы или предложения, не стесняйтесь обращаться в нашу службу поддержки. 38 | 39 | Всё лучшее — для вашего удобства и успеха! 40 | -------------------------------------------------------------------------------- /docs/ru/blog/2025-01-30-rtsp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Публикация камер наблюдения 3 | description: "" 4 | slug: rtsp 5 | image: /img/rtsp.jpg 6 | --- 7 | 8 | ![Публикация камер наблюдения](/img/rtsp.jpg) 9 | 10 | Мы рады сообщить о добавлении поддержки RTSP в CloudPub. Теперь вы можете безопасно и удобно транслировать видео с камер видеонаблюдения через интернет. 11 | 12 | 13 | 14 | ## Как опубликовать камеру наблюдения в CloudPub 15 | 16 | Для начала вам необходимо получить ссылку RTSP для вашей камеры наблюдения. Обычно она выглядит примерно так: `rtsp://username:password@ip_address:port/video_stream`. 17 | 18 | Затем вам нужно опубликовать эту ссылку в CloudPub. Проще всего это сделать в приложении: перейдите в раздел "Публикации" и вставьте ссылку RTSP в поле ввода. 19 | 20 | ![Публикация](/img/publish-cam.png) 21 | 22 | Нажмите кнопку "Опубликовать", и ваш видеопоток будет доступен по ссылке CloudPub. 23 | 24 | 25 | ## Просмотр видеопотока 26 | 27 | Просматривать видеопоток можно при помощи видеоплеера, который поддерживает RTSP, в приложении CloudPub или на сайте. 28 | 29 | Чтобы просмотреть видеопоток в видеоплеере, просто откройте в нем RTSP ссылку, которую вы получили после публикации. 30 | 31 | Для просмотра видеопотока на сайте CloudPub или в приложении, зайдите в раздел "Видеопотоки" и выберите нужный видеопоток: 32 | 33 | ![Видеопотоки](/img/view-cam.png) 34 | 35 | 36 | ## Преимущества использования RTSP в CloudPub 37 | 38 | 1. **Безопасность:** RTSP обеспечивает шифрование видеопотока, что делает передачу данных более безопасной. 39 | 2. **Простота использования:** С помощью CloudPub вы можете легко настроить трансляцию видео и делиться ею с другими пользователями. 40 | 3. **Надежность:** RTSP обеспечивает стабильную передачу видеопотока даже при низкой скорости интернета. 41 | 42 | ## Заключение 43 | 44 | Добавление поддержки RTSP в CloudPub открывает новые возможности для использования камер видеонаблюдения. Теперь вы можете контролировать происходящее вокруг вас, даже находясь вдали от дома или офиса. Попробуйте использовать RTSP в CloudPub уже сегодня! 45 | -------------------------------------------------------------------------------- /docs/ru/blog/2025-04-09-version-1.5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Новые функции в CloudPub 1.5 3 | description: "Новые функции CloudPub: Установка как сервис, инспектор HTTP-запросов, автоматическое декодирование сжатых данных и редактирование заголовков." 4 | slug: version-1.5 5 | image: /img/clouds.jpeg 6 | --- 7 | 8 | ![CloudPub верcия 1.5](/img/clouds.jpeg) 9 | # CloudPub: Новые возможности в последнем обновлении 10 | 11 | Рады сообщить о выходе новой версии платформы CloudPub, которая делает разработку и тестирование веб-приложений еще удобнее. В этом обновлении мы добавили несколько важных функций и улучшений, о которых давно просили наши пользователи. 12 | 13 | 14 | 15 | ## Установка CloudPub как сервис 16 | 17 | Теперь вы можете установить и запустить CloudPub как системный сервис! Это означает, что платформа будет автоматически запускаться при старте системы и работать в фоновом режиме. Больше не нужно вручную запускать приложение каждый раз – оно всегда готово к работе. 18 | 19 | Эта функция особенно полезна для разработчиков, которые используют CloudPub на постоянной основе или на серверах разработки и тестирования. 20 | 21 | ## Расширенные возможности инспектора HTTP-запросов 22 | 23 | Инспектор HTTP-запросов стал намного удобнее! Теперь вы можете просматривать перехваченные запросы в различных форматах: 24 | - HTML – с подсветкой синтаксиса 25 | - JSON – с форматированием и возможностью сворачивания узлов 26 | - XML – с структурированным отображением 27 | - Изображения – прямо в интерфейсе инспектора 28 | 29 | Это значительно упрощает анализ ответов API и отладку веб-приложений. 30 | 31 | ## Автоматическое декодирование сжатых данных 32 | 33 | Одно из самых улучшений – автоматическое декодирование сжатых HTTP-запросов и ответов. Теперь CloudPub автоматически распаковывает данные в форматах: 34 | - gzip 35 | - deflate 36 | - br (Brotli) 37 | 38 | Вам больше не придется использовать внешние инструменты для декодирования сжатого контента – всё происходит автоматически перед отображением в инспекторе. 39 | 40 | ## Новая команда для проверки скорости соединения 41 | 42 | Добавлена новая команда clo ping, которая позволяет быстро проверить скорость и качество подключения. Эта функция помогает диагностировать проблемы с сетью и оценивать производительность соединения, что особенно полезно при отладке проблем с производительностью. 43 | 44 | ## Редактирование HTTP-заголовков 45 | 46 | Теперь вы можете не только просматривать, но и редактировать HTTP-заголовки! Эта функция открывает новые возможности для тестирования: 47 | - Изменение заголовков авторизации 48 | - Тестирование различных значений User-Agent 49 | - Модификация Content-Type и других параметров 50 | 51 | Это незаменимый инструмент для тестирования безопасности и совместимости веб-приложений. 52 | 53 | ## Новая версия протокола 54 | 55 | Одно из нововведений – поддержка протокола версии 2, построенного на базе Protocol Buffers (protobuf). Это значительное улучшение обеспечивает: 56 | 57 | - **Высокую производительность** – сериализация и десериализация данных происходит в разы быстрее по сравнению с JSON 58 | - **Компактность передаваемых данных** – уменьшение объема трафика 59 | - **Строгую типизацию** – что снижает вероятность ошибок при обмене данными 60 | - **Обратную совместимость** – возможность легко обновлять структуры данных без нарушения работы существующих клиентов 61 | -------------------------------------------------------------------------------- /docs/ru/docs/1c.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | slug: /1c 4 | --- 5 | 6 | # База 1C 7 | 8 | ## Публикация базы 1С в интернете 9 | 10 | Наше приложение позволяет быстро и удобно публиковать базы 1С в интернете. 11 | Пользователи смогут получить доступ к базам данных через браузер, не устанавливая специальное программное обеспечение на своих компьютерах. 12 | 13 | Для публикации предварительно должны быть установлены `Модули расширения веб-севрера` 14 | 15 | ### Графический интерфейс 16 | 17 | Ознакомтесь со статьей [Веб публикация базы 1С](/blog/1c-publishing) для получения более подробной информации. 18 | 19 | ### Командная строка 20 | 21 | Если вы испоьзуете утилиту для командной строки, выполните следующую команду: 22 | 23 | 24 | ```bash 25 | clo publish 1c [Путь до базы 1С] 26 | ``` 27 | 28 | :::tip 29 | Если вы используете SQL сервер для хранения базы 1С, то вместо пути укажите строку подключения к базе. 30 | ::: 31 | 32 | После этого приложение автоматически скачает и установит необходимые компоненты, а также настроит веб-сервер для работы с базой 1С. 33 | 34 | Адрес для доступа к базе будет выведен в консоль. 35 | 36 | Если приложение не смогло автоматически найти установленное приложение 1С, то необходимо предварительно указать путь до каталога с 1С и ее битность в конфигурации: 37 | 38 | 39 | ```bash 40 | clo set 1c_platform [x86/x64] 41 | ``` 42 | 43 | ```bash 44 | clo set 1c_home [Путь до каталога, в который установлена 1С] 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/ru/docs/auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 15 3 | slug: /auth 4 | --- 5 | 6 | # Аутентификация и контроль доступа 7 | 8 | ## Типы аутентификации 9 | 10 | CloudPub поддерживает два типа аутентификации: 11 | 12 | ### Basic Auth 13 | 14 | Basic Auth - это стандартный метод аутентификации HTTP (RFC 7617), который: 15 | 16 | - Поддерживается всеми протоколами 17 | - Позволяет подключаться как через браузер, так и через другие клиенты 18 | - Идеально подходит для WebDAV, позволяя монтировать как сетевой диск 19 | - Требует передачи учетных данных при каждом запросе 20 | 21 | ### Form Auth 22 | 23 | Form Auth - это аутентификация через HTML-форму, которая: 24 | 25 | - Поддерживается протоколами HTTP, HTTPS и 1C 26 | - Предназначена для доступа через веб-браузер 27 | - Может использоваться с WebDAV, но тогда доступ будет возможен только через браузер 28 | - Более удобна для конечных пользователей 29 | 30 | ## Поддержка аутентификации по протоколам 31 | 32 | | Протокол | Basic Auth | Form Auth | 33 | |----------|------------|-----------| 34 | | HTTP | ✓ | ✓ | 35 | | HTTPS | ✓ | ✓ | 36 | | WebDAV | ✓ | ✓* | 37 | | 1C | ✓ | ✓ | 38 | | TCP | ✓ | ✗ | 39 | | UDP | ✓ | ✗ | 40 | 41 | \* WebDAV с Form Auth доступен только через браузер 42 | 43 | ## Контроль доступа (ACL) 44 | 45 | Для каждого опубликованного ресурса можно настроить правила доступа, указав: 46 | 47 | - Email пользователя 48 | - Роль пользователя 49 | 50 | ### Роли пользователей 51 | 52 | | Роль | Описание | 53 | |------|----------| 54 | | admin | Полный доступ к ресурсу | 55 | | reader | Доступ только для чтения | 56 | | writer | Доступ на чтение и запись (только для WebDAV) | 57 | 58 | ### Настройка правил 59 | 60 | Правила доступа задаются при публикации ресурса через параметр `--acl` в формате `email:роль`. 61 | Можно указать несколько правил для разных пользователей. 62 | 63 | Пример: 64 | ```bash 65 | clo publish --acl user@example.com:reader --acl admin@example.com:admin http 8080 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/ru/docs/docker.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 98 3 | description: Использование CloudPub с Docker 4 | slug: /docker 5 | --- 6 | 7 | # Образ Docker 8 | 9 | ## Использование CloudPub с Docker 10 | 11 | Вы можете использовать готовый [образ Docker](https://hub.docker.com/repository/docker/cloudpub/cloudpub/general) для агента CloudPub. 12 | 13 | Пример команды для запуска туннеля на порт 8080 на хост-машине выглядит следующим образом: 14 | 15 | ```bash 16 | docker run --net=host -it -e TOKEN=xyz cloudpub/cloudpub:latest publish http 8080 17 | ``` 18 | 19 | :::tip 20 | Docker-версия использует те же параметры командной строки, что и обычная версия. 21 | ::: 22 | 23 | Для пользователей MacOS или Windows, опция `--net=host` не будет работать. 24 | 25 | Вам нужно будет использовать специальный URL host.docker.internal, как описано в [документации](https://docs.docker.com/desktop/mac/networking/#use-cases-and-workarounds) Docker. 26 | 27 | ```bash 28 | docker run --net=host -it -e TOKEN=xyz cloudpub/cloudpub:latest \ 29 | publish http host.docker.internal:8080 30 | ``` 31 | 32 | ## Сохранение настроек при перезапуске контейнера 33 | 34 | При запуске контейнера, CloudPub создает новый агент и новый уникальный URL для доступа к туннелю. 35 | 36 | Что бы сохранить настройки при перезапуске контейнера, следует создать том для хранения конфигурации и кеша: 37 | 38 | 39 | ```bash 40 | docker volume create cloudpub-config 41 | ``` 42 | 43 | Затем, при запуске контейнера, следует использовать этот том: 44 | 45 | ```bash 46 | docker run -v cloudpub-config:/home/cloudpub --net=host -it -e TOKEN=xyz \ 47 | cloudpub/cloudpub:latest publish http 8080 48 | ``` 49 | 50 | В этом случае все настройки агента будут сохранены в томе `cloudpub-config` и будут доступны при следующем запуске контейнера. 51 | 52 | ## Публикация сразу нескольких ресурсов 53 | 54 | Вы можете указать несколько ресурсов для публикации в переменных окружения, разделяя их запятыми: 55 | 56 | ```bash 57 | docker run -v cloudpub-config:/home/cloudpub --net=host -it\ 58 | -e TOKEN=xyz \ 59 | -e HTTP=8080,8081 \ 60 | -e HTTPS=192.168.1.1:80 \ 61 | cloudpub/cloudpub:latest run 62 | ``` 63 | 64 | Названия переменной окружения совпадает с названием протокола. Доступны следующие протоколы: 65 | 66 | * HTTP 67 | * HTTPS 68 | * TCP 69 | * UDP 70 | * WEBDAV 71 | * MINECRAFT 72 | 73 | ## Версия для ARM процессоров 74 | 75 | Для ARM процессоров доступен образ `cloudpub/cloudpub:latest-arm64` 76 | -------------------------------------------------------------------------------- /docs/ru/docs/http.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | slug: /http 4 | --- 5 | 6 | # HTTP и HTTPS сервисы 7 | 8 | ## Публикация HTTP сервисов 9 | 10 | Для публикации локального HTTP сервера работающего на локальном интерфейсе, достаточно выполнить команду: 11 | 12 | ```bash 13 | clo publish http 8080 14 | ``` 15 | 16 | где 8080 это порт на котором работает ваш сервер. 17 | 18 | После выполнения команды, вы получите сообщение о том, что ваш сервис опубликован: 19 | 20 | ```bash 21 | Сервис опубликован: http://localhost:8080 -> https://wildly-suitable-fish.cloudpub.ru 22 | ``` 23 | 24 | Сервис будет доступен публично по протоколу HTTPS, при этом мы автоматически сгенерируем сертификат для этого домена. 25 | 26 | Если вам необходимо опубликовать сервис работающий на другом хосте в локальной сети, вы можете указать IP адрес или хост при публикации: 27 | 28 | ```bash 29 | clo publish http 192.168.1.1:80 30 | ``` 31 | 32 | В этом случае сервис будет опубликован на указанном IP адресе и порту (в этом примере это может быть панель администрирования вашего роутера) 33 | 34 | ## Публикация HTTPS сервисов 35 | 36 | Публикация HTTPS сервисов аналогична публикации HTTP сервисов, но с указанием протокола HTTPS: 37 | 38 | ```bash 39 | clo publish https 443 40 | ``` 41 | 42 | ## Заголовки HTTP и HTTPS запросов 43 | 44 | При публикации HTTP и HTTPS сервисов, вы можете переопределить или указать дополнительные заголовки, которые будут добавлены к запросам, отправляемым на ваш локальный сервер. 45 | 46 | Это может быть полезно, если ваш сервер требует определенные заголовки для работы, например, заголовок `Host` cовпадающий локальным адресом сервера (`localhost`) 47 | 48 | ```bash 49 | clo publish -H Host:localhost https 443 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/ru/docs/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: / 4 | --- 5 | 6 | import { Downloads, getUrl, getFile } from 'src/app/components/downloads'; 7 | import CodeBlock from '@theme/CodeBlock'; 8 | 9 | # Быстрый старт 10 | 11 | Как начать использовать **CloudPub за 5 минут**. 12 | 13 | ## Установите клиент 14 | 15 | 16 | 17 | ## Приложение с графическим интерфейсом 18 | 19 | - Создайте аккаунт в [личном кабинете](https://cloudpub.ru/dashboard) 20 | - Запустите приложение (исполнимый файл называется `cloudpub`) 21 | - Авторизуйтесь: 22 | 23 | ![Авторизация](/img/login-form.png) 24 | 25 | - Нажмите на кнопку `Новая публикация` 26 | - Выберите тип ресурса, который вы хотите опубликовать 27 | - Введите необходимые данные: 28 | 29 | ![Публикация](/img/publication.png) 30 | 31 | - Нажмите на кнопку `Опубликовать` 32 | - После этого вам будет предоставлен URL, по которому ресурс будет доступен в интернете 33 | 34 | ## Утилита для командной строки 35 | 36 | ### Windows {#windows} 37 | 38 | - Скачайте архив: {getFile('windows', 'x86_64')} 39 | - Распакуйте архив в любую папку. Для удобства рекомендуем распаковать архив и добавить путь к папке в переменную PATH. 40 | - Нажмите `Win + R` 41 | - Введите `cmd.exe` и нажмите `Enter` 42 | - В открывшемся окне введите `cd <путь к папке>` и нажмите `Enter`* 43 | 44 | * Этот пункт не обязателен, если вы добавили путь к папке в переменную PATH. 45 | 46 | #### Добавление пути в переменную PATH 47 | 48 | Чтобы добавить путь к папке в переменную PATH, выполните следующие шаги: 49 | 50 | - Щелкните правой кнопкой мыши на "Мой компьютер" и выберите "Свойства". 51 | - В открывшемся окне системных свойств нажмите на "Дополнительные параметры системы" слева. 52 | - В окне системных свойств нажмите на кнопку "Переменные среды". 53 | - В окне переменных среды, под "Системные переменные" или "Переменные пользователя" выберите переменную "Path" и нажмите "Изменить". 54 | - В окне изменения переменной среды нажмите "Новый" и добавьте путь к папке, в которую вы распаковали архив. Например, если путь - `C:\путь\к\вашей\папке`, добавьте `C:\путь\к\вашей\папке` как новую запись. 55 | - Нажмите "ОК" во всех окнах, чтобы сохранить изменения. 56 | - Для применения изменений возможно потребуется перезагрузить все открытые окна командной строки. 57 | 58 | ### Linux {#linux} 59 | 60 | - Откройте терминал 61 | - Скачайте архив при помощи команды 62 | 63 | wget {getUrl('linux', 'x86_64')} 64 | 65 | - Распакуйте архив при помощи команды 66 | 67 | tar -xvf {getFile('linux', 'x86_64')} 68 | 69 | ### MacOS {#macos} 70 | 71 | - Откройте терминал 72 | - Скачайте и распакуйте архив для вашей архитектуры: 73 | 74 | #### Apple Silicon: 75 | 76 | curl {getUrl('macos', 'aarch64')} -o {getFile('macos', 'aarch64')} 77 | tar -xvf {getFile('macos', 'aarch64')} 78 | 79 | #### Intel: 80 | 81 | curl {getUrl('macos', 'x86_64')} -o {getFile('macos', 'x86_64')} 82 | tar -xvf {getFile('macos', 'x86_64')} 83 | 84 | 85 | ## Привяжите ваш аккаунт 86 | 87 | Если в еще этого не сделали, создайте аккаунт на в [личном кабинете](https://cloudpub.ru/dashboard). После этого привяжите ваш аккаунт к клиенту, выполнив следующую команду: 88 | 89 | ```bash 90 | clo set token <ваш токен> 91 | ``` 92 | 93 | Свой токен вы можете найти на главной странице в личном кабинете после регистрации. 94 | 95 | Начиная с версии 1.6 клиента, вы можете авторизоватся при помощи команды: 96 | 97 | ```bash 98 | clo login 99 | ``` 100 | 101 | :::note 102 | На Linux и MacOS вам необходимо указывать путь до файла `clo`, даже если он в текущей директории: 103 | 104 | ```bash 105 | ./clo login 106 | ``` 107 | ::: 108 | 109 | ## Опубликуйте ваш первый ресурс 110 | 111 | Для публикации локального HTTP сервера работающего на порте 8080 выполните команду: 112 | 113 | ```bash 114 | clo publish http 8080 115 | ``` 116 | 117 | После этого вам будет предоставлен URL, по которому ваш ресурс будет доступен в интернете, например: 118 | 119 | ```bash 120 | Сервис опубликован: http://localhost:8080 -> https://wildly-suitable-fish.cloudpub.ru 121 | ``` 122 | 123 | В этом случае ваш ресурс будет доступен по адресу `https://wildly-suitable-fish.cloudpub.ru`. 124 | 125 | URL вашего ресурса будет отличаться от приведенного в примере. 126 | -------------------------------------------------------------------------------- /docs/ru/docs/minecraft.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | slug: /minecraft 4 | --- 5 | 6 | # Сервер Minecraft 7 | 8 | ## Публикация сервера Minecraft в интернете 9 | 10 | CloudPub позволяет публиковать сервера Minecraft в интернете, чтобы ваши друзья могли подключиться к нему из любой точки мира. 11 | 12 | Если вы не используете моды, то это делается очень просто. Вам нужно указать путь к папке с сервером Minecraft, и CloudPub самостоятельно настроит все необходимые параметры. 13 | 14 | ### Приложение с графическим интерфейсом 15 | 16 | Выберите тип публикации `minecraft` и укажите путь к папке, куда будет установлен сервер. 17 | 18 | ### Командная строка 19 | 20 | ```bash 21 | clo publish minecraft [путь к папке с сервером] 22 | ``` 23 | 24 | После этого вам будет предоставлен URL, по которому ваш сервер будет доступен в интернете, например: 25 | 26 | ```bash 27 | Сервис опубликован: minecraft://C:\Minecraft -> minecraft://minecraft.cloudpub.ru:32123 28 | ``` 29 | 30 | Указанный после стрелки (`-> minecraft://`) адрес и будет адресом, который и нужен игрокам для входа в игру. 31 | 32 | В примере выше это `minecraft.cloudpub.ru:32123` 33 | 34 | 35 | ### Сервер с модами 36 | 37 | Если вы используете сервер с модами, воспользуйтесь [инструкцией по публикации TCP сервиса](/docs/tcp). 38 | 39 | Порт который нужно открыть для подключения к серверу Minecraft по умолчанию 25565, но может быть изменен в настройках сервера. 40 | 41 | Более подробно это описано в [официальной документации Minecraft](https://minecraft.fandom.com/ru/wiki/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B8_%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0). 42 | -------------------------------------------------------------------------------- /docs/ru/docs/rtsp.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | slug: /rtsp 4 | --- 5 | 6 | # RTSP видеопотоки 7 | 8 | С помощью CloudPub вы можете публиковать RTSP видеопотоки камер наблюдения. 9 | 10 | Это позволяет вам получить доступ к вашим камерам из интернета, не открывая порты на роутере. 11 | 12 | Кроме того, вы можете просматривать видеопотоки в личном кабинете или приложении CloudPub. 13 | 14 | ## RTSP протокол 15 | 16 | Видеопотоки публикуются по протоколу RTSP. 17 | 18 | Это означает, что вы можете использовать любой RTSP-плеер для доступа к видеопотокам. 19 | 20 | Например, в Windows 10 это можно сделать через VLC Media Player, в macOS - через QuickTime Player. 21 | 22 | Просто откройте плеер, введите адрес RTSP потока, который вам предоставил CloudPub. 23 | 24 | 25 | ### Приложение с графическим интерфейсом 26 | 27 | Выберите тип публикации `Камера наблюдения (RTSP)` и введите URL вашего RTSP потока. 28 | 29 | ### Командная строка 30 | 31 | ```bash 32 | clo publish rtsp "[URL RTSP потока]" 33 | ``` 34 | 35 | После этого вам будет предоставлен URL, по которому ваш RTSP видеопоток будет доступен. 36 | 37 | ```bash 38 | Сервис опубликован: rtsp://192.168.0.100:554/stream0 -> rtsp://rtsp.cloudpub.ru:51243/stream0 39 | ``` 40 | 41 | Указанный после стрелки адрес будет доступен из интернета. 42 | 43 | Просматривать опубликованные потоки вы можете в разделе "Видеопотоки" личного кабинета или приложения. 44 | -------------------------------------------------------------------------------- /docs/ru/docs/tcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | slug: /tcp 4 | --- 5 | 6 | # TCP и UDP сервисы 7 | 8 | ## Публикация TCP сервисов 9 | 10 | Публикации сервиса работающего по протоколу TCP осуществляется аналогично публикации HTTP сервиса, но с указанием протокола TCP: 11 | 12 | ```bash 13 | clo publish tcp 22 14 | ``` 15 | 16 | В этом примере мы публикуем сервис работающий на порту 22 (SSH). 17 | 18 | В отличие от HTTP сервисов, TCP сервисы не уникального доменного имени, и доступны только по адресу `tcp.cloudpub.ru` и уникальному порту. 19 | 20 | Так же как для HTTP сервисов, можно указать адрес любого хоста в локальной сети: 21 | 22 | ```bash 23 | clo publish tcp myserver:3389 24 | ``` 25 | 26 | В этом примере мы публикуем сервис работающий на порту 3389 (RDP) на хосте `myserver`. 27 | 28 | 29 | ## Публикация UDP сервисов 30 | 31 | Публикации сервиса работающего по протоколу UDP осуществляется аналогично публикации TCP сервиса, но с указанием протокола UDP: 32 | 33 | ```bash 34 | clo publish udp 53 35 | ``` 36 | 37 | В этом примере мы публикуем сервис работающий на порту 53 (DNS). 38 | -------------------------------------------------------------------------------- /docs/ru/docs/webdav.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | slug: /webdav 4 | --- 5 | 6 | # Публикация файлов 7 | 8 | С помощью CloudPub вы можете публиковать файлы и папки, чтобы делиться ими с другими пользователями. 9 | 10 | Кроме того, это позволяет вам управлять своими файлами, не загружая их на сторонние сервисы. 11 | 12 | ## WebDAV протокол 13 | 14 | Файлы публикуются по протоколу WebDAV. 15 | 16 | Это означает, что вы можете использовать любой WebDAV-клиент для доступа к файлам. 17 | 18 | Например, в Windows 10 это можно сделать через проводник, в macOS - через Finder. 19 | 20 | Просто откройте проводник или Finder, введите адрес, который вам предоставил CloudPub, и введите логин и пароль. 21 | 22 | После этого вы сможете работать с файлами, как с обычными файлами на вашем компьютере. 23 | 24 | ### Приложение с графическим интерфейсом 25 | 26 | Выберите тип публикации `Папка c файлами (WebDAV)` и укажите путь к папке, куда будет установлен сервер. 27 | 28 | ### Командная строка 29 | 30 | ```bash 31 | clo publish webdav "[путь к папке]" 32 | ``` 33 | 34 | После этого вам будет предоставлен URL, по которому ваши файлы будут доступны. 35 | 36 | ```bash 37 | Сервис опубликован: webdav://C:\Users\Администратор -> https://indelibly-fearless-jackdaw.cloudpub.local 38 | ``` 39 | 40 | Указанный после стрелки адрес будет доступен из интернета. 41 | 42 | Для доступа к файлам вам потребуется ввести логин и пароль. В качестве логина используется ваш E-Mail, пароль совпадает с паролем от вашего аккаунта. 43 | 44 | Управлять файлами вы можете из раздела "Файловый менеджер" в личном кабинете. 45 | 46 | Если вам нужно предоставить доступ к файлу другим пользователям, там вы можете сгенерировать ссылку на скачивание файла. 47 | -------------------------------------------------------------------------------- /docs/ru/docusaurus.config.ts: -------------------------------------------------------------------------------- 1 | import { themes as prismThemes } from "prism-react-renderer"; 2 | import type { Config } from "@docusaurus/types"; 3 | import type * as Preset from "@docusaurus/preset-classic"; 4 | import path from "path"; 5 | 6 | process.env.IS_PREACT = "false"; 7 | 8 | const config: Config = { 9 | title: "CloudPub", 10 | tagline: "От локального к глобальному за один клик", 11 | favicon: "img/favicon.ico", 12 | 13 | // Set the production url of your site here 14 | url: "https://cloudpub.ru", 15 | // Set the // pathname under which your site is served 16 | // For GitHub pages deployment, it is often '//' 17 | baseUrl: "/docs/", 18 | 19 | // GitHub pages deployment config. 20 | // If you aren't using GitHub pages, you don't need these. 21 | organizationName: "cloudpub", // Usually your GitHub org/user name. 22 | projectName: "cloudpub", // Usually your repo name. 23 | 24 | onBrokenLinks: "throw", 25 | onBrokenMarkdownLinks: "warn", 26 | 27 | staticDirectories: ["public", "static"], 28 | 29 | // Even if you don't use internationalization, you can use this field to set 30 | // useful metadata like html lang. For example, if your site is Chinese, you 31 | // may want to replace "en" with "zh-Hans". 32 | i18n: { 33 | defaultLocale: "ru", 34 | locales: ["ru"], 35 | }, 36 | plugins: [ 37 | [ 38 | "docusaurus-plugin-module-alias", 39 | { 40 | alias: { 41 | src: path.resolve(__dirname, "../../frontend/src"), 42 | }, 43 | }, 44 | ], 45 | [ 46 | "docusaurus-plugin-dotenv", 47 | { 48 | path: "./.env", 49 | systemvars: true, 50 | }, 51 | ], 52 | ], 53 | presets: [ 54 | [ 55 | "classic", 56 | { 57 | docs: { 58 | sidebarPath: "./sidebars.ts", 59 | routeBasePath: "/", 60 | }, 61 | blog: { 62 | blogTitle: "Блог", 63 | blogSidebarTitle: "Последние записи", 64 | blogSidebarCount: 10, 65 | showReadingTime: true, 66 | feedOptions: { 67 | type: ["rss", "atom"], 68 | xslt: true, 69 | }, 70 | }, 71 | theme: { 72 | customCss: "./src/css/custom.css", 73 | }, 74 | } satisfies Preset.Options, 75 | ], 76 | ], 77 | 78 | themeConfig: { 79 | image: "img/welcome.png", 80 | navbar: { 81 | title: "CloudPub", 82 | logo: { 83 | alt: "CloudPub Logo", 84 | src: "img/logo.svg", 85 | href: "https://cloudpub.ru", 86 | target: "_self", 87 | }, 88 | items: [ 89 | { 90 | type: "docSidebar", 91 | sidebarId: "tutorialSidebar", 92 | position: "left", 93 | label: "Документация", 94 | }, 95 | { to: "/blog", label: "Блог", position: "left" }, 96 | ], 97 | }, 98 | footer: { 99 | style: "dark", 100 | copyright: `Copyright © ${new Date().getFullYear()} CloudPub`, 101 | }, 102 | prism: { 103 | theme: prismThemes.github, 104 | darkTheme: prismThemes.dracula, 105 | }, 106 | } satisfies Preset.ThemeConfig, 107 | }; 108 | 109 | export default config; 110 | -------------------------------------------------------------------------------- /docs/ru/marketing/anounce-post.md: -------------------------------------------------------------------------------- 1 | # CloudPub: Как мы создали российскую альтернативу ngrok с графическим интерфейсом 2 | 3 | Привет, друзья! Сегодня хочу рассказать о нашем проекте CloudPub, над которым мы работали последние месяцы. 4 | 5 | Всё началось с простой идеи — создать удобный инструмент для публикации локальных ресурсов в интернете. Как разработчик, я часто сталкивался с необходимостью показать заказчику локальный сайт или дать доступ к API, запущенному на моей машине. Существующие решения вроде tuna.am или xtunnel.ru решали эту задачу, но мне всегда не хватало удобного интерфейса и широкой поддержки различных протоколов. 6 | 7 | ## Что нас отличает от конкурентов 8 | 9 | Главное отличие CloudPub — это полноценное приложение с графическим интерфейсом. Мы решили, что не все разработчики любят возиться с командной строкой, поэтому создали интуитивно понятное приложение, где все функции доступны в пару кликов. 10 | 11 | При этом мы не забыли и про консольную версию для тех, кто предпочитает классический подход. Обе версии обладают одинаковым функционалом и работают на всех популярных платформах: Windows, macOS и Linux. 12 | 13 | ## Модульная архитектура 14 | 15 | Мы изначально проектировали CloudPub как модульную систему с поддержкой плагинов. Это позволило нам быстро добавлять поддержку новых протоколов: 16 | 17 | - HTTP/HTTPS для веб-приложений 18 | - TCP/UDP для сетевых сервисов 19 | - WebDAV для файловых систем 20 | - 1C для публикации баз данных 21 | - RTSP для видеопотоков 22 | - Minecraft для игровых серверов 23 | 24 | И это только начало! Благодаря модульной архитектуре мы можем оперативно добавлять новые протоколы по запросам пользователей. 25 | 26 | ## Инспектор трафика и другие возможности 27 | 28 | Важная часть нашего продукта — встроенный инспектор трафика. Он позволяет в реальном времени анализировать и выгружать HTTP-запросы в удобном формате (JSON, XML, HEX, Image и др), в том числе с поддержкой сжатия (Content-Encoding). 29 | 30 | Мы также реализовали гибкую систему контроля доступа, позволяющую настраивать права для разных пользователей, и возможность установки CloudPub как системный сервис для автоматического запуска. 31 | 32 | ## Планы на будущее 33 | 34 | Мы только в начале пути. В ближайших планах: 35 | - Расширение списка поддерживаемых протоколов 36 | - Улучшение производительности 37 | - Добавление новых инструментов для анализа и отладки 38 | 39 | Приглашаю всех попробовать CloudPub — скачать можно на нашем сайте https://cloudpub.ru. Буду рад услышать ваши отзывы и предложения! 40 | -------------------------------------------------------------------------------- /docs/ru/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cloudpub/docs", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "^3.7.0", 19 | "@docusaurus/preset-classic": "^3.7.0", 20 | "@mdx-js/react": "^3.0.0", 21 | "clsx": "^2.0.0", 22 | "prism-react-renderer": "^2.3.0", 23 | "react": "^18.0.0", 24 | "react-dom": "^18.0.0" 25 | }, 26 | "devDependencies": { 27 | "@cloudpub/frontend": "file:../frontend/dist", 28 | "@docusaurus/module-type-aliases": "^3.7.0", 29 | "@docusaurus/tsconfig": "^3.7.0", 30 | "@docusaurus/types": "^3.7.0", 31 | "docusaurus-plugin-dotenv": "^1.0.1", 32 | "docusaurus-plugin-module-alias": "^0.0.2", 33 | "typescript": "~5.5.2" 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.5%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 3 chrome version", 43 | "last 3 firefox version", 44 | "last 5 safari version" 45 | ] 46 | }, 47 | "engines": { 48 | "node": ">=18.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/ru/sidebars.ts: -------------------------------------------------------------------------------- 1 | import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; 2 | import { TEST } from '@cloudpub/frontend'; 3 | 4 | /** 5 | * Creating a sidebar enables you to: 6 | - create an ordered group of docs 7 | - render a sidebar for each doc of that group 8 | - provide next/previous navigation 9 | 10 | The sidebars can be generated from the filesystem, or explicitly defined here. 11 | 12 | Create as many sidebars as you want. 13 | */ 14 | const sidebars: SidebarsConfig = { 15 | // By default, Docusaurus generates a sidebar from the docs folder structure 16 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 17 | 18 | // But you can create a sidebar manually 19 | /* 20 | tutorialSidebar: [ 21 | 'intro', 22 | 'hello', 23 | { 24 | type: 'category', 25 | label: 'Tutorial', 26 | items: ['tutorial-basics/create-a-document'], 27 | }, 28 | ], 29 | */ 30 | }; 31 | 32 | export default sidebars; 33 | -------------------------------------------------------------------------------- /docs/ru/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | 32 | img[src*='#center'] { 33 | display: block; 34 | margin: auto; 35 | } 36 | -------------------------------------------------------------------------------- /docs/ru/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/.nojekyll -------------------------------------------------------------------------------- /docs/ru/static/img/1c-publish0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-publish0.png -------------------------------------------------------------------------------- /docs/ru/static/img/1c-publish1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-publish1.png -------------------------------------------------------------------------------- /docs/ru/static/img/1c-publish2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-publish2.png -------------------------------------------------------------------------------- /docs/ru/static/img/1c-publish3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-publish3.png -------------------------------------------------------------------------------- /docs/ru/static/img/1c-publish4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-publish4.png -------------------------------------------------------------------------------- /docs/ru/static/img/1c-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-server.jpg -------------------------------------------------------------------------------- /docs/ru/static/img/1c-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/1c-server.png -------------------------------------------------------------------------------- /docs/ru/static/img/card1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/card1.png -------------------------------------------------------------------------------- /docs/ru/static/img/card2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/card2.png -------------------------------------------------------------------------------- /docs/ru/static/img/card3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/card3.png -------------------------------------------------------------------------------- /docs/ru/static/img/card4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/card4.png -------------------------------------------------------------------------------- /docs/ru/static/img/card5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/card5.png -------------------------------------------------------------------------------- /docs/ru/static/img/clouds.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/clouds.jpeg -------------------------------------------------------------------------------- /docs/ru/static/img/django_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/django_logo.png -------------------------------------------------------------------------------- /docs/ru/static/img/django_publish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/django_publish.png -------------------------------------------------------------------------------- /docs/ru/static/img/favicon.ico: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/ru/static/img/inspector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/inspector.png -------------------------------------------------------------------------------- /docs/ru/static/img/login-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/login-form.png -------------------------------------------------------------------------------- /docs/ru/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/ru/static/img/minecraft-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/minecraft-server.jpg -------------------------------------------------------------------------------- /docs/ru/static/img/publication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/publication.png -------------------------------------------------------------------------------- /docs/ru/static/img/publish-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/publish-cam.png -------------------------------------------------------------------------------- /docs/ru/static/img/rich-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/rich-gui.png -------------------------------------------------------------------------------- /docs/ru/static/img/rtsp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/rtsp.jpg -------------------------------------------------------------------------------- /docs/ru/static/img/tunnel.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/tunnel.jpeg -------------------------------------------------------------------------------- /docs/ru/static/img/view-cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/view-cam.png -------------------------------------------------------------------------------- /docs/ru/static/img/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ermakus/cloudpub/763adc564e8ebd64c7831a43e47fcc2c05822cbe/docs/ru/static/img/welcome.png -------------------------------------------------------------------------------- /docs/ru/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | --------------------------------------------------------------------------------