├── .github └── workflows │ └── docker-publish.yml ├── Dockerfile ├── club ├── bin │ ├── dufs │ ├── uv │ ├── uvx │ └── webssh ├── configs │ ├── .bashrc │ └── supervisord.conf └── entrypoint.sh ├── readme.md └── static └── photos ├── deploy.png ├── dufs.png ├── network.png ├── restart.png └── webssh.png /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish Docker image 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | 16 | - name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v3 18 | 19 | - name: Log in to GitHub Container Registry 20 | uses: docker/login-action@v3 21 | with: 22 | registry: ghcr.io 23 | username: ${{ github.actor }} 24 | password: ${{ secrets.GITHUB_TOKEN }} 25 | 26 | - name: Set lowercase owner 27 | run: echo "REPO_OWNER_LC=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV 28 | 29 | - name: Build and push Docker image 30 | uses: docker/build-push-action@v5 31 | with: 32 | context: . 33 | push: true 34 | tags: | 35 | ghcr.io/${{ env.REPO_OWNER_LC }}/${{ github.event.repository.name }}:${{ github.ref_name }} 36 | ghcr.io/${{ env.REPO_OWNER_LC }}/${{ github.event.repository.name }}:latest -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 使用较小的基础镜像 2 | FROM ubuntu:22.04 3 | 4 | # 设置环境变量,避免交互式安装 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | # 更新系统并安装必要的软件包 8 | RUN apt-get update 9 | RUN apt-get install -y --no-install-recommends \ 10 | vim supervisor sudo openssh-server iputils-ping net-tools curl ca-certificates \ 11 | && apt-get clean \ 12 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 13 | 14 | # 创建club用户并设置密码,同时将其加入sudo组 15 | RUN useradd -m -s /bin/bash club \ 16 | && echo "club:123456" | chpasswd \ 17 | && usermod -aG sudo club 18 | 19 | # 将当前目录的所有文件复制到容器的 /club 目录下 20 | COPY ./club/bin /club/bin 21 | COPY ./club/configs /club/configs 22 | COPY ./club/entrypoint.sh /club/entrypoint.sh 23 | 24 | # 设置工作目录 25 | WORKDIR /root 26 | 27 | # 设置执行权限 28 | RUN chmod +x /club/entrypoint.sh && cp /club/bin/u* /bin 29 | 30 | # 设置入口点 31 | ENTRYPOINT ["/club/entrypoint.sh"] 32 | 33 | # 设置默认命令 34 | CMD ["/usr/bin/supervisord", "-n", "-c", "/root/supervisord/supervisord.conf"] 35 | -------------------------------------------------------------------------------- /club/bin/dufs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/club/bin/dufs -------------------------------------------------------------------------------- /club/bin/uv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/club/bin/uv -------------------------------------------------------------------------------- /club/bin/uvx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/club/bin/uvx -------------------------------------------------------------------------------- /club/bin/webssh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/club/bin/webssh -------------------------------------------------------------------------------- /club/configs/.bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | [ -z "$PS1" ] && return 7 | 8 | # don't put duplicate lines in the history. See bash(1) for more options 9 | # ... or force ignoredups and ignorespace 10 | HISTCONTROL=ignoredups:ignorespace 11 | 12 | # append to the history file, don't overwrite it 13 | shopt -s histappend 14 | 15 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 16 | HISTSIZE=1000 17 | HISTFILESIZE=2000 18 | 19 | # check the window size after each command and, if necessary, 20 | # update the values of LINES and COLUMNS. 21 | shopt -s checkwinsize 22 | 23 | # make less more friendly for non-text input files, see lesspipe(1) 24 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 25 | 26 | # set variable identifying the chroot you work in (used in the prompt below) 27 | if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then 28 | debian_chroot=$(cat /etc/debian_chroot) 29 | fi 30 | 31 | # set a fancy prompt (non-color, unless we know we "want" color) 32 | case "$TERM" in 33 | xterm-color) color_prompt=yes;; 34 | esac 35 | 36 | # uncomment for a colored prompt, if the terminal has the capability; turned 37 | # off by default to not distract the user: the focus in a terminal window 38 | # should be on the output of commands, not on the prompt 39 | #force_color_prompt=yes 40 | 41 | if [ -n "$force_color_prompt" ]; then 42 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 43 | # We have color support; assume it's compliant with Ecma-48 44 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 45 | # a case would tend to support setf rather than setaf.) 46 | color_prompt=yes 47 | else 48 | color_prompt= 49 | fi 50 | fi 51 | 52 | if [ "$color_prompt" = yes ]; then 53 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 54 | else 55 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 56 | fi 57 | unset color_prompt force_color_prompt 58 | 59 | # If this is an xterm set the title to user@host:dir 60 | case "$TERM" in 61 | xterm*|rxvt*) 62 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 63 | ;; 64 | *) 65 | ;; 66 | esac 67 | 68 | # enable color support of ls and also add handy aliases 69 | if [ -x /usr/bin/dircolors ]; then 70 | test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" 71 | alias ls='ls --color=auto' 72 | #alias dir='dir --color=auto' 73 | #alias vdir='vdir --color=auto' 74 | 75 | alias grep='grep --color=auto' 76 | alias fgrep='fgrep --color=auto' 77 | alias egrep='egrep --color=auto' 78 | fi 79 | 80 | # some more ls aliases 81 | alias ll='ls -alF' 82 | alias la='ls -A' 83 | alias l='ls -CF' 84 | 85 | # Alias definitions. 86 | # You may want to put all your additions into a separate file like 87 | # ~/.bash_aliases, instead of adding them here directly. 88 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 89 | 90 | if [ -f ~/.bash_aliases ]; then 91 | . ~/.bash_aliases 92 | fi 93 | 94 | # enable programmable completion features (you don't need to enable 95 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 96 | # sources /etc/bash.bashrc). 97 | #if [ -f /etc/bash_completion ] && ! shopt -oq posix; then 98 | # . /etc/bash_completion 99 | #fi 100 | 101 | eval "$(uv generate-shell-completion bash)" 102 | eval "$(uvx --generate-shell-completion bash)" 103 | -------------------------------------------------------------------------------- /club/configs/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=false 3 | logfile=/root/supervisord/supervisord.log 4 | logfile_maxbytes=10MB 5 | logfile_backups=5 6 | pidfile=/root/supervisord/supervisord.pid 7 | 8 | [unix_http_server] 9 | file=/var/run/supervisor.sock 10 | chmod=0700 11 | 12 | [rpcinterface:supervisor] 13 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 14 | 15 | [supervisorctl] 16 | serverurl=unix:///var/run/supervisor.sock 17 | 18 | [program:sshd] 19 | command=/usr/sbin/sshd -D 20 | autostart=true 21 | autorestart=true 22 | 23 | stdout_logfile=/root/sshd/sshd_stdout.log 24 | stderr_logfile=/root/sshd/sshd_stderr.log 25 | stdout_logfile_maxbytes=10MB 26 | stderr_logfile_maxbytes=10MB 27 | stdout_logfile_backups=5 28 | stderr_logfile_backups=5 29 | 30 | [program:webssh] 31 | command=/root/webssh/webssh --delay=10 --encoding=utf-8 --fbidhttp=False --maxconn=20 --origin='*' --policy=warning --redirect=False --timeout=10 --port=8888 --debug --xsrf=False --xheaders --wpintvl=1 32 | autostart=true 33 | autorestart=true 34 | 35 | stdout_logfile=/root/webssh/webssh_stdout.log 36 | stderr_logfile=/root/webssh/webssh_stderr.log 37 | stdout_logfile_maxbytes=10MB 38 | stderr_logfile_maxbytes=10MB 39 | stdout_logfile_backups=5 40 | stderr_logfile_backups=5 41 | 42 | [program:dufs] 43 | command=/root/dufs/dufs -p 5000 --allow-upload -a club:123456@/:rw 44 | autostart=true 45 | autorestart=true 46 | 47 | stdout_logfile=/root/dufs/dufs_stdout.log 48 | stderr_logfile=/root/dufs/dufs_stderr.log 49 | stdout_logfile_maxbytes=10MB 50 | stderr_logfile_maxbytes=10MB 51 | stdout_logfile_backups=5 52 | stderr_logfile_backups=5 53 | -------------------------------------------------------------------------------- /club/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 进入工作目录 4 | cd /root 5 | 6 | # 创建初始化标记文件所在的目录 7 | mkdir -p /root/init 8 | 9 | # 检查是否首次启动(通过检查标记文件) 10 | if [ ! -f "/root/init/.initialized" ]; then 11 | echo "首次启动,执行初始化操作..." 12 | 13 | # 创建必要的目录 14 | mkdir -p /root/webssh 15 | mkdir -p /root/dufs 16 | mkdir -p /root/supervisord 17 | mkdir -p /root/sshd 18 | 19 | # 确保日志目录存在并设置适当的权限 20 | for dir in /root/webssh /root/dufs /root/sshd; do 21 | mkdir -p $dir 22 | touch $dir/${dir##*/}_stdout.log $dir/${dir##*/}_stderr.log 23 | chmod 755 $dir 24 | chmod 644 $dir/*.log 25 | done 26 | 27 | # 复制必要的二进制文件和配置 28 | cp /club/configs/.bashrc /root/.bashrc 29 | cp -r /club/bin/dufs /root/dufs 30 | cp -r /club/bin/webssh /root/webssh 31 | cp -r /club/configs/supervisord.conf /root/supervisord/supervisord.conf 32 | 33 | # 创建标记文件,表示已初始化 34 | touch /root/init/.initialized 35 | echo "初始化完成" 36 | else 37 | echo "检测到已初始化,跳过初始化步骤..." 38 | fi 39 | 40 | # 每次启动时都要执行的操作 41 | 42 | # 配置 SSH 服务 43 | if [ ! -d "/var/run/sshd" ]; then 44 | mkdir -p /var/run/sshd 45 | chmod 0755 /var/run/sshd 46 | fi 47 | 48 | # 确保 SSH 主机密钥存在 49 | if [ ! -f "/etc/ssh/ssh_host_rsa_key" ]; then 50 | ssh-keygen -A 51 | fi 52 | 53 | # 每次启动都设置club用户密码 54 | CLUB_PWD_FILE="/root/init/.club" 55 | if [ -f "$CLUB_PWD_FILE" ]; then 56 | CLUB_PWD=$(cat "$CLUB_PWD_FILE") 57 | else 58 | CLUB_PWD="123456" 59 | fi 60 | echo "club:$CLUB_PWD" | chpasswd 61 | 62 | # 执行传入的命令,通常是启动 supervisord 63 | exec "$@" -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ClawCloud 环境说明 2 | 3 | 在使用 ClawCloud 过程中,发现其使用k8s的pod容器,所以在重启或者其他操作后,会还原系统,而且不能挂载整个“/”目录做持久化,所以搞了一个自用镜像。 4 | 本仓库为 ClawCloud 的application提供一个ubuntu 22.04环境,集成了自定义 uv Python 环境、WebSSH 远程连接和 dufs 文件上传服务,方便使用。 5 | 6 | ## 主要功能 7 | 8 | - **自定义 uv Python 环境**:内置 uv、uvx,支持现代 Python 包管理和虚拟环境。 9 | - **WebSSH 自启动**:容器启动后自动运行 WebSSH,便于通过网页安全连接终端。 10 | - **dufs 文件上传**:集成 dufs,支持通过网页上传/下载文件,提升文件管理效率。 11 | - **supervisord 管理**:集成 supervisord,可同时管理多个服务,如 WebSSH、dufs 等。 12 | - **vim,ping,ifconfig**:安装了 vim,ping,ifconfig 等常用命令 13 | 14 | ## 快速开始 15 | 16 | 1. **clawcloud镜像运行**: 17 | - 创建 app,名称随意,镜像按照图上步骤进行创建。 18 | ``` bash 19 | ghcr.io/cjsen/club:latest 20 | ``` 21 | - CPU 和内存根据自身需求调整,按照图上来的话,每天的费用大概在 $0.05/day。每月五美元完全够用。 22 | - 端口开放 5000(dufs)和 8888(webssh),并打开 "Enable Internet Access" 按钮。 23 | - 挂载 /root 目录(必须),大小自己调整。 24 | - 点击右上角 "deploy application",等待容器启动(可能会超时,镜像比较大,没关系,直接返回在点进来就好了) 25 | ![alt text](./static/photos/deploy.png) 26 | 27 | 2. **访问服务**: 28 | ![alt text](./static/photos/network.png) 29 | 访问面板,点击对应的 public address,即可访问服务。 30 | - webssh: 31 | - hostname: localhost 32 | - username:club 33 | - password:123456 34 | ![alt text](./static/photos/webssh.png) 35 | - dufs: 36 | - username:club 37 | - password:123456 38 | ![alt text](./static/photos/dufs.png) 39 | 40 | ## 安全提醒(务必阅读) 41 | 42 | **首次启动后,请务必立即完成以下操作:** 43 | 44 | 1. **修改系统用户 club 的密码** 45 | 进入容器后执行: 46 | ```bash 47 | password="your-new-password" && echo "$password" | sudo tee /root/init/.club > /dev/null && echo "club:$password" | sudo chpasswd 48 | ``` 49 | 50 | 2. **修改 dufs 的访问密码** 51 | dufs 默认密码为弱密码,请及时在 `/root/supervisord/supervisord.conf` 配置中更改为强密码,并重启服务。 52 | ```bash 53 | sudo sed -i 's/club:[^@]*@/club:your-new-password@/' /root/supervisord/supervisord.conf && sudo supervisorctl reread && sudo supervisorctl update 54 | ``` 55 | 56 | 3. **重启你的应用** 57 | ![alt text](./static/photos/restart.png) 58 | 59 | ## 目录结构 60 | 61 | - `bin/`:包含 uv、uvx、webssh、dufs 可执行文件 62 | - `configs/`:supervisord 及相关配置 63 | - `entrypoint.sh`:容器启动脚本 64 | 65 | ## 其他说明 66 | 67 | - 建议定期更新镜像,及时修复安全漏洞。 68 | - 如需自定义 Python 包或工具,请参考 uv 官方文档。 69 | 70 | --- 71 | 72 | 如有问题欢迎提 issue 或联系维护者。 73 | 74 | 你可以根据实际端口和配置进一步补充细节。 -------------------------------------------------------------------------------- /static/photos/deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/static/photos/deploy.png -------------------------------------------------------------------------------- /static/photos/dufs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/static/photos/dufs.png -------------------------------------------------------------------------------- /static/photos/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/static/photos/network.png -------------------------------------------------------------------------------- /static/photos/restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/static/photos/restart.png -------------------------------------------------------------------------------- /static/photos/webssh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CJSen/club/12e4142918b68e5db3c8746774715e57a6e0da11/static/photos/webssh.png --------------------------------------------------------------------------------