test docker build

This commit is contained in:
Darren 2023-12-08 17:09:20 +08:00 committed by GitHub
parent f5a6573dde
commit aa2f781fae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 6 additions and 5894 deletions

View file

@ -1,3 +1,6 @@
# This action will be trigger by docker.yml action
# docker.yml action download the artifact for build
name: Build media for apphub image name: Build media for apphub image
on: on:

3
.gitignore vendored
View file

@ -6,4 +6,5 @@ logs
.pytest_cache .pytest_cache
apphub/swagger-ui apphub/swagger-ui
apphub/apphub.egg-info apphub/apphub.egg-info
cli/__pycache__ cli/__pycache__
source

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
# modify time: 202312081656, you can modify here to trigger Docker Build action # modify time: 202312081709, you can modify here to trigger Docker Build action
FROM python:3.10-slim-bullseye FROM python:3.10-slim-bullseye
LABEL maintainer="Websoft9<help@websoft9.com>" LABEL maintainer="Websoft9<help@websoft9.com>"
@ -16,18 +16,15 @@ RUN apt update && apt install -y --no-install-recommends curl git jq cron iprout
git clone --depth=1 $library_repo \ git clone --depth=1 $library_repo \
mv docker-library w9library && \ mv docker-library w9library && \
rm -rf w9library/.github && \ rm -rf w9library/.github && \
# Prepare media # Prepare media
if [ ! -f ./media.zip ]; then \ if [ ! -f ./media.zip ]; then \
wget $websoft9_artifact/plugin/media/media-latest.zip -O ./media.zip && \ wget $websoft9_artifact/plugin/media/media-latest.zip -O ./media.zip && \
unzip media.zip \ unzip media.zip \
fi \ fi \
mv media* w9media \ mv media* w9media \
git clone --depth=1 https://github.com/swagger-api/swagger-ui.git && \ git clone --depth=1 https://github.com/swagger-api/swagger-ui.git && \
wget https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js && \ wget https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js && \
cp redoc.standalone.js swagger-ui/dist && \ cp redoc.standalone.js swagger-ui/dist && \
git clone --depth=1 $websoft9_repo ./w9source && \ git clone --depth=1 $websoft9_repo ./w9source && \
cp -r ./w9media ./media && \ cp -r ./w9media ./media && \
cp -r ./w9library ./library && \ cp -r ./w9library ./library && \

View file

@ -1,126 +0,0 @@
## 0.8.30-rc1 release on 2023-11-16
1. improve all plugins githubaction
2. install plugin by shell
## 0.8.29 release on 2023-11-04
1. gitea,myapps,appstore update
2. apphub domains
3. apphub docs nginx config
## 0.8.28 release on 2023-11-01
1. improve dockerfile to reduce image size
2. fixed update_zip.sh
3. hide websoft9 containers
## 0.8.27 release on 2023-10-31
1. new websoft9 init
## 0.8.26 release on 2023-09-27
1. appmanage change to apphub
## 0.8.20 release on 2023-08-23
1. appmanage config files error:bug fix
## 0.8.19 release on 2023-08-23
1. New App Store preview push function added
2. Fix some known bugs
## 0.8.18 release on 2023-08-17
1. appmanage volumes bug edit
## 0.8.15 release on 2023-08-17
1. service menu bug
## 0.8.14 release on 2023-08-16
1. myapps plugins refresh bug
## 0.8.13 release on 2023-08-15
1. update plugins
2. fix bug data save in session
## 0.8.12 release on 2023-08-12
1. navigator plugin install way change
2. update plugin
## 0.8.11 release on 2023-08-03
1. Optimize interface calls
2. library artifacts directory: websoft9/plugin/library
3. add init apps: nocobase, affine
## 0.8.10 release on 2023-08-01
1. improve update.sh
2. add docs to artifacts
3. improve server's hostname
## 0.8.8 release on 2023-07-27
fixed update search api bug
## 0.8.5 release on 2023-07-26
add docs
## 0.8.4 release on 2023-07-26
add appstore search api
## 0.8.2 release on 2023-07-24
1. install from artifacts
2. add extre version.json into artifacts
## 0.7.2 release on 2023-06-25
1. appmanage 自动更新接口升级
## 0.7.1 release on 2023-06-21
1. appmanage version 文件意外删除时 bug 修改
2. 自动更新的时间频率调整为一天
3. 更新脚本 version 文件不存在的 bug 修改
## 0.7.0 release on 2023-06-20
1. appstore 增加 更新功能
2. myapps 功能优化
3. 新增 settings(设置) 功能
## 0.6.0 release on 2023-06-17
1. 上架 wordpress
2. 下架 moodle
3. 修改 redmine
4. 升级 discuzqzabbix
5. 新增自动更新软件商店功能
## 0.4.0 release on 2023-06-15
1. owncloud 下线测试
## 0.3.0 release on 2023-06-06
1. appmanage docker 镜像更新到 0.3.0
2. 修复 prestashop 无法访问的 bug
3. 修复 odoo 无法安装的 bug
## 0.2.0 release on 2023-06-03
1. appmanage docker 镜像更新到 0.2.0
2. Portainer 插件修复自动登录 bug
3. My Apps 插件修复首次使用获取容器 bug
## 0.1.0 release on 2023-05-26
1. stackhub 预发布,基本功能实现

View file

@ -1,68 +0,0 @@
# Contributing to Websoft9
From opening a bug report to creating a pull request: every contribution is appreciated and welcome.
If you're planning to implement a new feature or change the api please [create an issue](https://github.com/websoft9/websoft9/issues/new/choose) first. This way we can ensure that your precious work is not in vain.
## Not Sure Architecture?
It's important to figure out the design [architecture of Websoft9](docs/architecture.md)
## Fork
Contributor only allow to fork [main branch](https://github.com/Websoft9/websoft9/tree/main) and pull request for it. Maintainers don't accept any pr to **production branch**
## Branch
This repository have these branchs:
* **Contributor's branch**: Develpoer can fork main branch as their delelopment branch anytime
* **main branch**: The only branch that accepts PR from Contributors's branch
* **production branch**: For version release and don't permit modify directly, only merge PR from **main branch**
Flow: Contributor's branch → main branch → production branch
## Pull request
[Pull request](https://docs.github.com/pull-requests) let you tell others about changes you've pushed to a branch in a repository on GitHub.
#### When is PR produced?
* Contributor commit to main branch
* main branch commit to production branch
#### How to deal with PR?
1. [pull request reviews](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews)
2. Merge RP and CI/CD for it
## DevOps principle
DevOps thinks the same way **[5m1e](https://www.dgmfmoldclamps.com/what-is-5m1e-in-injection-molding-industry/)** for manufacturing companies
We follow the development principle of minimization, rapid release
### Version
Use *[[major].[minor].[patch]](https://semver.org/lang/zh-CN/)* for version serial number and [version.json](../version.json) for version dependencies
### Artifact
Websoft9 use below [Artifact](https://jfrog.com/devops-tools/article/what-is-a-software-artifact/) for different usage:
* **Dockerhub for image**: Access [Websoft9 docker images](https://hub.docker.com/u/websoft9dev) on Dockerhub
* **Azure Storage for files**: Access [packages list](https://artifact.azureedge.net/release?restype=container&comp=list) at [Azure Storage](https://learn.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-blobs#list-the-blobs-in-a-container)
### Tags
- Type tags: Bug, enhancement, Documetation
- Stages Tags: PRD, Dev, QA(include deployment), Documentation
### WorkFlow
Websoft9 use the [Production branch with GitLab flow](https://cm-gitlab.stanford.edu/help/workflow/gitlab_flow.md#production-branch-with-gitlab-flow) for development collaboration
> [gitlab workflow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) is improvement model for git

View file

@ -1,167 +0,0 @@
This program is released under LGPL-3.0 and with the additional Terms:
Without authorization, it is not allowed to publish free or paid image based on this program in any Cloud platform's Marketplace.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View file

@ -1,72 +0,0 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0)
[![GitHub last commit](https://img.shields.io/github/last-commit/websoft9/websoft9)](https://github.com/websoft9/websoft9)
[![GitHub Release Date](https://img.shields.io/github/release-date/websoft9/websoft9)](https://github.com/websoft9/websoft9)
[![GitHub Repo stars](https://img.shields.io/github/stars/websoft9/websoft9?style=social)](https://github.com/websoft9/websoft9)
# What is Websoft9?
Websoft9 is web-based PaaS platform for running 200+ hot [open source application](https://github.com/Websoft9/docker-library/tree/main/apps) on your own server.
Websoft9 help you running multiple applications in a single server, that means we believe Microservices on single machine is reasonable. On the contrary, it becomes more and more valuable as computing power increases
Although the Cloud Native emphasizes high availability and clustering, but most of the time, applications do not need to implement complex clusters or K8S.
Websoft9's [architecture](https://github.com/Websoft9/websoft9/blob/main/docs/architecture.md) is simple, it did not create any new technology stack, and we fully utilize popular technology components to achieve our product goals, allowing users and developers to participate in our projects without the need to learn new technologies.
## Demos
You can see the sceenshoots below:
| ![image](https://github.com/Websoft9/websoft9/assets/16741975/8321780c-4824-4e40-997d-676a31534063) | ![image](https://github.com/Websoft9/websoft9/assets/16741975/e842575b-60bc-4b0d-a57b-28c26b16196a) | ![image](https://github.com/Websoft9/websoft9/assets/16741975/c598412a-9529-4286-ba03-6234d6da99b9) |
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| ![image](https://github.com/Websoft9/websoft9/assets/16741975/7bed3744-1e9f-429e-8678-3714c8c262e2) | ![image](https://github.com/Websoft9/websoft9/assets/16741975/a0923c69-2792-4cde-bfaf-bc018b61aee9) | ![image](https://github.com/Websoft9/websoft9/assets/16741975/901efd1c-31a0-4b31-b79c-fc2d441bb679) |
## Features
- Applications listing
- Install 200+ template applications without any configuration
- Web-based file browser to manage files and folder
- Manage user accounts
- Use a terminal on a remote server in your local web browser
- Nginx gui for proxy and free SSL with Let's Encrypt
- Deploy, configure, troubleshoot and secure containers in minutes on Kubernetes, Docker, and Swarm in any data center, cloud, network edge or IIOT device.
- Manage your Linux by GUI: Inspect and change network settings, Configure a firewall, Manage storage, Browse and search system logs, Inspect a systems hardware, Inspect and interact with systemd-based services,
- Supported languages: English, Chinese中文
# Installation
You should have root privileges user to install or upgrade or uninstall Websoft9, if you use no-root user you can `sudo su` for it
## Install & Upgrade
```
# Install by default
wget -O install.sh https://websoft9.github.io/websoft9/install/install.sh && bash install.sh
# Install Websoft9 with parameters
wget -O install.sh https://websoft9.github.io/websoft9/install/install.sh && bash install.sh --port 9000 --channel release --path "/data/websoft9/source" --version "latest"
```
After installation, access it by: **http://Internet IP:9000** and using **Linux user** for login
## Uninstall
```
# Uninstall by default
curl https://websoft9.github.io/websoft9/install/uninstall.sh | bash
# Uninstall all
wget -O - https://websoft9.github.io/websoft9/install/uninstall.sh | bash /dev/stdin --cockpit --files
```
# Contributing
Follow the [contributing guidelines](CONTRIBUTING.md) if you want to propose a change in the Websoft9 core. For more information about participating in the community and contributing to the Websoft9 project, see [this page](https://support.websoft9.com/docs/community/contributing).
- Documentation for [Websoft9 core maintainers](docs/MAINTAINERS.md)
- Documentation for application templates based on Docker maintainers is in the [docker-library](https://github.com/Websoft9/docker-library).
- [Articles promoting Websoft9](https://github.com/Websoft9/websoft9/issues/327)
# License
Websoft9 is licensed under the [LGPL-3.0](/License.md), and additional Terms: It is not allowed to publish free or paid image based on this repository in any Cloud platform's Marketplace without authorization

View file

@ -1,15 +0,0 @@
# Security Policy
## Versions
As an open source product, we will only patch the latest major version for security vulnerabilities. Previous versions of Websoft9 will not be retroactively patched.
## Disclosing
You can get in touch with us regarding a vulnerability via [issue](https://github.com/Websoft9/websoft9/issues) or email at help@websoft9.com.
You can also disclose via huntr.dev. If you believe you have found a vulnerability, please disclose it on huntr and let us know.
https://huntr.dev/bounties/disclose
This will enable us to review the vulnerability and potentially reward you for your work.

View file

@ -1,2 +0,0 @@
1. improve all plugins githubaction
2. install plugin by shell

View file

@ -1,24 +0,0 @@
# Cockpit
Cockpit is used for backend service gatway, we have not modify Cockpit core, just improve the installation and modify config for Websoft9
## Install
```
# default install
wget https://websoft9.github.io/websoft9/install/install_cockpit.sh && bash install_cockpit.sh
# define Cockpit port and install
wget https://websoft9.github.io/websoft9/install/install_cockpit.sh && bash install_cockpit.sh --port 9099
```
## Development
Developer should improve these codes:
- Install and Upgrade Cockpit: */install/install_cockpit.sh*
- Override the default menus: */cockpit/menu_override*
> shell.override.json is used for Top menu of Cockpit。Override function until Cockpit 297
- Cockipt configuration file: */cockpit/cockpit.conf*

View file

@ -1,5 +0,0 @@
# docs: https://cockpit-project.org/guide/latest/cockpit.conf.5.html
[WebService]
AllowUnencrypted = true
LoginTitle= Websoft9 - Linux AppStore

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,3 +0,0 @@
{
"menu": null
}

View file

@ -1,57 +0,0 @@
{
"menu": null,
"tools": {
"index": {
"label": "Networking",
"order": 40,
"docs": [
{
"label": "Managing networking bonds",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/configuring-network-bonds-using-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing networking teams",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/configuring-network-teams-using-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing networking bridges",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/configuring-network-bridges-in-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing VLANs",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/configuring-vlans-in-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing firewall",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing_firewall_using_the_web_console"
}
],
"keywords": [
{
"matches": [
"network",
"interface",
"bridge",
"vlan",
"bond",
"team",
"port",
"mac",
"ipv4",
"ipv6"
]
},
{
"matches": [
"firewall",
"firewalld",
"zone",
"tcp",
"udp"
],
"goto": "/network/firewall"
}
]
}
}
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,3 +0,0 @@
{
"menu": null
}

View file

@ -1,29 +0,0 @@
{
"locales": {
"cs-cz": null,
"de-de": null,
"es-es": null,
"fi-fi": null,
"fr-fr": null,
"he-il": null,
"it-it": null,
"ja-jp": null,
"ka-ge": null,
"ko-kr": null,
"nb-no": null,
"nl-nl": null,
"pl-pl": null,
"pt-br": null,
"ru-ru": null,
"sk-sk": null,
"sv-se": null,
"tr-tr": null,
"uk-ua": null
},
"docs": [
{
"label": "Documentation",
"url": "https://support.websoft9.com/en/docs/"
}
]
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,69 +0,0 @@
{
"menu": null,
"tools": {
"index": {
"label": "Storage",
"order": 30,
"docs": [
{
"label": "Managing partitions",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-partitions-using-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing NFS mounts",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-nfs-mounts-in-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing RAIDs",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-redundant-arrays-of-independent-disks-in-the-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing LVMs",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/using-the-web-console-for-configuring-lvm-logical-volumes_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing physical drives",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/using-the-web-console-for-changing-physical-drives-in-volume-groups_system-management-using-the-rhel-8-web-console"
},
{
"label": "Managing VDOs",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/using-the-web-console-for-managing-virtual-data-optimizer-volumes_system-management-using-the-rhel-8-web-console"
},
{
"label": "Using LUKS encryption",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/locking-data-with-luks-password-in-the-rhel-web-console_system-management-using-the-rhel-8-web-console"
},
{
"label": "Using Tang server",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/configuring-automated-unlocking-using-a-tang-key-in-the-web-console_system-management-using-the-rhel-8-web-console"
}
],
"keywords": [
{
"matches": [
"filesystem",
"partition",
"nfs",
"raid",
"volume",
"disk",
"vdo",
"iscsi",
"drive",
"mount",
"unmount",
"udisks",
"mkfs",
"format",
"fstab",
"lvm2",
"luks",
"encryption",
"nbde",
"tang"
]
}
]
}
}
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,147 +0,0 @@
{
"tools": {
"terminal": null,
"services": {
"label": "Services",
"order": 10,
"docs": [
{
"label": "Managing services",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-services-in-the-web-console_system-management-using-the-rhel-8-web-console"
}
],
"keywords": [
{
"matches": [
"service",
"systemd",
"target",
"socket",
"timer",
"path",
"unit",
"systemctl"
]
},
{
"matches": [
"boot",
"mask",
"unmask",
"restart",
"enable",
"disable"
],
"weight": 1
}
]
},
"logs": {
"label": "Logs",
"order": 20,
"docs": [
{
"label": "Reviewing logs",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/reviewing-logs_system-management-using-the-rhel-8-web-console"
}
],
"keywords": [
{
"matches": [
"journal",
"warning",
"error",
"debug"
]
},
{
"matches": [
"abrt",
"crash",
"coredump"
],
"goto": "?tag=abrt-notification"
}
]
}
},
"menu": {
"logs": null,
"services": null,
"index": {
"label": "Overview",
"order": -2,
"docs": [
{
"label": "Configuring system settings",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/getting-started-with-the-rhel-8-web-console_system-management-using-the-rhel-8-web-console"
}
],
"keywords": [
{
"matches": [
"time",
"date",
"restart",
"shut",
"domain",
"machine",
"operating system",
"os",
"asset tag",
"ssh",
"power",
"version",
"host"
]
},
{
"matches": [
"hardware",
"mitigation",
"pci",
"memory",
"cpu",
"bios",
"ram",
"dimm",
"serial"
],
"goto": "/system/hwinfo"
},
{
"matches": [
"graphs",
"metrics",
"history",
"pcp",
"cpu",
"memory",
"disks",
"network",
"cgroups",
"performance"
],
"goto": "/metrics"
}
]
},
"terminal": {
"label": "Terminal",
"keywords": [
{
"matches": [
"console",
"command",
"bash",
"shell"
]
}
]
}
},
"preload": [
"index"
],
"content-security-policy": "img-src 'self' data:"
}

View file

@ -1,3 +0,0 @@
{
"tools": null
}

View file

@ -1,31 +0,0 @@
{
"menu": null,
"tools": {
"index": {
"label": "Accounts",
"order": 70,
"docs": [
{
"label": "Managing user accounts",
"url": "https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-user-accounts-in-the-web-console_system-management-using-the-rhel-8-web-console"
}
],
"keywords": [
{
"matches": [
"user",
"password",
"useradd",
"passwd",
"username",
"login",
"access",
"roles",
"ssh",
"keys"
]
}
]
}
}
}

View file

@ -1,4 +0,0 @@
git clone --depth=1 https://github.com/Websoft9/websoft9.git
rm -rf /etc/cockpit/*.override.json
cp -r websoft9/cockpit/menu_override/* /etc/cockpit
rm -rf websoft9

View file

@ -1,4 +0,0 @@
APPHUB_VERSION=0.0.6
DEPLOYMENT_VERSION=2.19.0
GIT_VERSION=1.20.4
PROXY_VERSION=2.10.4

View file

@ -1,28 +0,0 @@
# Docker
## Test it
All backend services of Websoft9 is packaged to Docker image, just these steps you can running them:
```
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && sudo systemctl enable docker && sudo systemctl start docker
sudo docker network create websoft9
wget https://websoft9.github.io/websoft9/docker/.env
wget https://websoft9.github.io/websoft9/docker/docker-compose.yml
sudo docker compose -p websoft9 up -d
```
> If you want only want to change to development, you should execute following commands:
```
sudo docker compose -p websoft9 down -v
wget https://websoft9.github.io/websoft9/docker/docker-compose-dev.yml
# /data/source is development sources path in host
docker compose -f docker-compose-dev.yml -p websoft9 up -d --build
```
## Develop it
The folder **apphub, deployment, git, proxy** stored development files, and used for:
- Optimize dockerfile
- Release version
- Build docker image by Githuh action

View file

@ -1,59 +0,0 @@
# modify time: 202311131740, you can modify here to trigger Docker Build action
FROM python:3.10-slim-bullseye
LABEL maintainer="Websoft9<help@websoft9.com>"
LABEL version="0.0.6"
WORKDIR /websoft9
ENV LIBRARY_VERSION=0.5.8
ENV MEDIA_VERSION=0.0.3
ENV websoft9_repo="https://github.com/Websoft9/websoft9"
ENV docker_library_repo="https://github.com/Websoft9/docker-library"
ENV media_repo="https://github.com/Websoft9/media"
ENV source_github_pages="https://websoft9.github.io/websoft9"
RUN apt update && apt install -y --no-install-recommends curl git jq cron iproute2 supervisor rsync wget unzip zip && \
# Prepare source files
wget $docker_library_repo/archive/refs/tags/$LIBRARY_VERSION.zip -O ./library.zip && \
unzip library.zip && \
mv docker-library-* w9library && \
rm -rf w9library/.github && \
wget $media_repo/archive/refs/tags/$MEDIA_VERSION.zip -O ./media.zip && \
unzip media.zip && \
mv media-* w9media && \
rm -rf w9media/.github && \
git clone --depth=1 https://github.com/swagger-api/swagger-ui.git && \
wget https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js && \
cp redoc.standalone.js swagger-ui/dist && \
git clone --depth=1 $websoft9_repo ./w9source && \
cp -r ./w9media ./media && \
cp -r ./w9library ./library && \
cp -r ./w9source/apphub ./apphub && \
cp -r ./swagger-ui/dist ./apphub/swagger-ui && \
cp -r ./w9source/apphub/src/config ./config && \
cp -r ./w9source/docker/apphub/script ./script && \
curl -o ./script/update_zip.sh $source_github_pages/scripts/update_zip.sh && \
pip install --no-cache-dir --upgrade -r apphub/requirements.txt && \
pip install -e ./apphub && \
# Clean cache and install files
rm -rf apphub/docs apphub/tests library.zip media.zip redoc.standalone.js swagger-ui w9library w9media w9source && \
apt clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/man /usr/share/doc /usr/share/doc-base
# supervisor
COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN chmod +r /etc/supervisor/conf.d/supervisord.conf
# cron
COPY config/cron /etc/cron.d/cron
RUN echo "" >> /etc/cron.d/cron && crontab /etc/cron.d/cron
# chmod for all .sh script
RUN find /websoft9/script -name "*.sh" -exec chmod +x {} \;
VOLUME /websoft9/apphub/logs
VOLUME /websoft9/apphub/src/config
EXPOSE 8080
ENTRYPOINT ["/websoft9/script/entrypoint.sh"]

View file

@ -1,4 +0,0 @@
ARG APPHUB_VERSION
FROM websoft9dev/apphub:${APPHUB_VERSION} as buildstage
RUN mkdir -p /websoft9/apphub-dev
RUN sed -i '/supervisorctl start apphub/c\supervisorctl start apphubdev' /websoft9/script/entrypoint.sh

View file

@ -1,11 +0,0 @@
# README
- Download docker-library release to image
- install git
- entrypoint: config git credential for remote gitea
- health.sh: gitea/portaner/nginx credentials, if have exception output to logs
- use virtualenv for pip install requirements.txt
- create volumes at dockerfile
- EXPOSE port
- process logs should output to docker logs by supervisord
- [uvicorn](https://www.uvicorn.org/) load Fastapi

View file

@ -1 +0,0 @@
{"username":"appuser","password":"apppassword"}

View file

@ -1 +0,0 @@
0 2 * * * /websoft9/script/update.sh

View file

@ -1,45 +0,0 @@
[supervisord]
nodaemon=false
logfile=/var/log/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
user=root
[program:apphub]
command=uvicorn src.main:app --host 0.0.0.0 --port 8080
autostart=false
user=root
directory=/websoft9/apphub
stdout_logfile=/var/log/supervisord.log
stdout_logfile_maxbytes=0
stderr_logfile=/var/log/supervisord.log
stderr_logfile_maxbytes=0
[program:apphubdev]
command=/websoft9/script/developer.sh
autostart=false
user=root
stdout_logfile=/var/log/supervisord.log
stdout_logfile_maxbytes=0
stderr_logfile=/var/log/supervisord.log
stderr_logfile_maxbytes=0
[program:cron]
command=cron -f
autostart=true
user=root
stdout_logfile=/var/log/supervisord.log
stdout_logfile_maxbytes=0
stderr_logfile=/var/log/supervisord.log
stderr_logfile_maxbytes=0
[program:media]
command=uvicorn src.media:app --host 0.0.0.0 --port 8081
autostart=true
user=root
directory=/websoft9/apphub
stdout_logfile=/var/log/supervisord.log
stdout_logfile_maxbytes=0
stderr_logfile=/var/log/supervisord.log
stderr_logfile_maxbytes=0

View file

@ -1,17 +0,0 @@
#!/bin/bash
source_path="/websoft9/apphub-dev"
echo "Start to cp source code"
if [ ! "$(ls -A $source_path)" ]; then
cp -r /websoft9/apphub/* $source_path
fi
cp -r /websoft9/apphub/swagger-ui $source_path
echo "Install apphub cli"
pip uninstall apphub -y
pip install -e $source_path
echo "Running the apphub"
cd $source_path
exec uvicorn src.main:app --reload --host 0.0.0.0 --port 8080

View file

@ -1,56 +0,0 @@
#!/bin/bash
# Define PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# Export PATH
export PATH
set -e
bash /websoft9/script/migration.sh
try_times=5
supervisord
supervisorctl start apphub
# set git user and email
for ((i=0; i<$try_times; i++)); do
set +e
username=$(apphub getconfig --section gitea --key user_name 2>/dev/null)
email=$(apphub getconfig --section gitea --key user_email 2>/dev/null)
set -e
if [ -n "$username" ] && [ -n "$email" ]; then
break
fi
echo "Wait for service running, retrying..."
sleep 3
done
if [[ -n "$username" ]]; then
echo "git config --global user.name $username"
git config --global user.name "$username"
else
echo "username is null, git config username failed"
exit 1
fi
regex="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if [[ $email =~ $regex ]]; then
echo "git config --global user.email $email"
git config --global user.email "$email"
else
echo "Not have correct email, git config email failed"
exit 1
fi
create_apikey() {
if [ ! -f /websoft9/apphub/src/config/initialized ] || [ -z "$(apphub getkey)" ]; then
echo "Create new apikey"
apphub genkey
touch /websoft9/apphub/src/config/initialized 2>/dev/null
fi
}
create_apikey
tail -n 1000 -f /var/log/supervisord.log

View file

@ -1,51 +0,0 @@
#!/bin/bash
echo "start to migrate config.ini"
migrate_ini() {
# Define file paths, use template ini and syn exsit items from target ini
export target_ini="$1"
export template_ini="$2"
python3 - <<EOF
import configparser
import os
import sys
target_ini = os.environ['target_ini']
template_ini = os.environ['template_ini']
# Create two config parsers
target_parser = configparser.ConfigParser()
template_parser = configparser.ConfigParser()
try:
target_parser.read(target_ini)
template_parser.read(template_ini)
except configparser.MissingSectionHeaderError:
print("Error: The provided files are not valid INI files.")
sys.exit(1)
# use target_parser to override template_parser
for section in target_parser.sections():
if template_parser.has_section(section):
for key, value in target_parser.items(section):
if template_parser.has_option(section, key):
template_parser.set(section, key, value)
with open(target_ini, 'w') as f:
template_parser.write(f)
EOF
}
migrate_ini "/websoft9/apphub/src/config/config.ini" "/websoft9/config/config.ini"
if [ $? -eq 0 ]; then
echo "Success to update config.ini"
else
echo "Fail to update config.ini, skip it"
fi

View file

@ -1,9 +0,0 @@
#!/bin/bash
echo "$(date) - Compare remote version and local version." | tee -a /var/log/supervisord.log
echo "$(date) - Download remote packages and replace local data." | tee -a /var/log/supervisord.log
bash /websoft9/script/update_zip.sh --package_name "media-latest.zip" --sync_to "/websoft9/media"
bash /websoft9/script/update_zip.sh --package_name "library-latest.zip" --sync_to "/websoft9/library"
echo "$(date) - Success to update library and media."

View file

@ -1,7 +0,0 @@
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}

View file

@ -1,23 +0,0 @@
# modify time: 202311031633, you can modify here to trigger Docker Build action
# step1: Build entrypoint execute program init_portainer by golang
FROM golang:latest AS builder
WORKDIR /
COPY init_portainer.go /
# CGO_ENABLED=0 can not depend on any dynamic library
RUN CGO_ENABLED=0 go build -o init_portainer /init_portainer.go
RUN chmod +x /init_portainer
COPY endpoint.go /
RUN CGO_ENABLED=0 go build -o endpoint /endpoint.go
RUN chmod +x /endpoint
# step2: Copy build go program to portainer
# Dockerfile refer to: https://github.com/portainer/portainer/blob/develop/build/linux/Dockerfile
FROM portainer/portainer-ce:2.19.0
LABEL maintainer="websoft9<help@websoft9.com>"
LABEL version="2.19.0"
COPY --from=builder /init_portainer /
COPY --from=builder /endpoint /
ENTRYPOINT ["/init_portainer"]

View file

@ -1,3 +0,0 @@
# Readme
- create local endpoint and lock

View file

@ -1,167 +0,0 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"os"
"time"
)
const (
AdminUser = "admin"
EndpointURL = "http://localhost:9000/api/endpoints"
AuthURL = "http://localhost:9000/api/auth"
CredentialLoc = "/data/credential"
)
type Endpoint struct {
Name string `json:"name"`
URL string `json:"url"`
}
type EndpointCreation struct {
Name string `json:"name"`
EndpointCreationType int `json:"EndpointCreationType"`
}
type AuthResponse struct {
Jwt string `json:"jwt"`
}
type Credentials struct {
Username string `json:"username"`
Password string `json:"password"`
}
func main() {
fmt.Println("Start to create endpoint...")
client := &http.Client{}
password, err := getPassword()
if err != nil {
fmt.Println("Failed to get password:", err)
return
}
token, err := authenticate(client, AdminUser, password)
if err != nil {
fmt.Println("Failed to authenticate:", err)
return
}
endpoints, err := queryEndpoints(client, token)
if err != nil {
fmt.Println("Failed to query endpoints:", err)
return
}
for _, endpoint := range endpoints {
if endpoint.Name == "local" && endpoint.URL == "unix:///var/run/docker.sock" {
fmt.Println("Endpoint exists, exiting...")
return
}
}
fmt.Println("Endpoint does not exist, creating...")
createEndpoint(client, token)
fmt.Println("Endpoint created successfully")
}
func getPassword() (string, error) {
for {
if _, err := os.Stat(CredentialLoc); os.IsNotExist(err) {
fmt.Printf("%s does not exist, waiting for 3 seconds...\n", CredentialLoc)
time.Sleep(3 * time.Second)
} else {
fmt.Printf("%s exists, proceeding...\n", CredentialLoc)
data, err := ioutil.ReadFile(CredentialLoc)
if err != nil {
return "", err
}
return string(data), nil
}
}
}
func authenticate(client *http.Client, username, password string) (string, error) {
credentials := Credentials{Username: username, Password: password}
credentialsJson, err := json.Marshal(credentials)
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", AuthURL, bytes.NewBuffer(credentialsJson))
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var authResponse AuthResponse
err = json.Unmarshal(body, &authResponse)
if err != nil {
return "", err
}
return authResponse.Jwt, nil
}
func queryEndpoints(client *http.Client, token string) ([]Endpoint, error) {
req, err := http.NewRequest("GET", EndpointURL, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var endpoints []Endpoint
err = json.Unmarshal(body, &endpoints)
if err != nil {
return nil, err
}
return endpoints, nil
}
func createEndpoint(client *http.Client, token string) error {
data := url.Values{
"Name": {"local"},
"EndpointCreationType": {"1"},
}
req, err := http.NewRequest("POST", EndpointURL, strings.NewReader(data.Encode()))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if resp.StatusCode != http.StatusCreated {
body, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf("Failed to create endpoint: %s, Response body: %s", resp.Status, string(body))
}
return nil
}

View file

@ -1,70 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"os/exec"
"time"
)
func main() {
filePath := "/data/credential"
initPath := "/data/init"
_, err := os.Stat(filePath)
if os.IsNotExist(err) {
_, err := os.Stat(initPath)
if os.IsNotExist(err) {
fmt.Println("credential is not exist, create it.")
password := generatePassword(16)
err := writeToFile(filePath, password)
if err != nil {
fmt.Println("write file error:", err)
return
}
} else {
fmt.Println("credential is exist, skip it.")
}
// call portainer
cmd := exec.Command("./portainer", "--admin-password-file", filePath, "--hide-label", "owner=websoft9")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
fmt.Println("error running compiled_program:", err)
return
}else{
os.Create(initPath)
}
}else{
fmt.Println("credential is exist, skip it.")
cmd := exec.Command("./portainer", "--hide-label", "owner=websoft9")
cmd.Run()
}
}
func generatePassword(length int) string {
rand.Seed(time.Now().UnixNano())
charset := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@$()_"
password := make([]byte, length)
for i := range password {
password[i] = charset[rand.Intn(len(charset))]
}
return string(password)
}
func writeToFile(filePath , content string) error {
return ioutil.WriteFile(filePath , []byte(content), 0755)
}

View file

@ -1,98 +0,0 @@
# this file for developer
# install --devto "/data/mysource"
version: "3.8"
services:
apphub:
image: websoft9dev/apphub:${APPHUB_VERSION}
container_name: websoft9-apphub
build:
context: .
dockerfile: ./apphub/Dockerfiledev
args:
- APPHUB_VERSION=${APPHUB_VERSION}
ports:
- 9001-9999:8080
restart: always
volumes:
- /data/websoft9/apphub:/websoft9/apphub-dev
- apphub_media:/websoft9/media
depends_on:
- deployment
- git
- proxy
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:8080"
deployment:
image: websoft9dev/deployment:$DEPLOYMENT_VERSION
container_name: websoft9-deployment
restart: always
ports:
- 9001-9999:9000
volumes:
- portainer:/data
- /data/compose:/data/compose
- /var/run/docker.sock:/var/run/docker.sock
#- /run/podman/podman.sock:/var/run/docker.sock
healthcheck:
test: ["CMD", "/endpoint"]
interval: 10s
timeout: 30s
retries: 4
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:9000"
git:
image: websoft9dev/git:$GIT_VERSION
container_name: websoft9-git
restart: always
volumes:
- gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- 9001-9999:3000
environment:
- INSTALL_LOCK=true
- DISABLE_SSH=true
- RUN_MODE=prod
- HTTP_PORT=3000
- DISABLE_REGISTRATION=false
- REQUIRE_SIGNIN_VIEW=false
- ROOT_URL=http://localhost/w9git/
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:3000"
proxy:
image: websoft9dev/proxy:$PROXY_VERSION
container_name: websoft9-proxy
restart: always
ports:
- "80:80"
- "443:443"
- "9001-9999:81"
volumes:
- nginx_data:/data
- nginx_letsencrypt:/etc/letsencrypt
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port: 80"
- "com.docker.compose.w9_https.port: 443"
- "com.docker.compose.w9_console.port: 81"
networks:
default:
name: websoft9
external: true
volumes:
apphub_media:
portainer:
gitea:
nginx_data:
nginx_letsencrypt:

View file

@ -1,84 +0,0 @@
version: "3.8"
services:
apphub:
image: websoft9dev/apphub:$APPHUB_VERSION
container_name: websoft9-apphub
restart: always
volumes:
- apphub_logs:/websoft9/apphub/logs
- apphub_config:/websoft9/apphub/src/config
depends_on:
- deployment
- git
- proxy
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:8080"
deployment:
image: websoft9dev/deployment:$DEPLOYMENT_VERSION
container_name: websoft9-deployment
restart: always
volumes:
- portainer:/data
- /data/compose:/data/compose
- /var/run/docker.sock:/var/run/docker.sock
#- /run/podman/podman.sock:/var/run/docker.sock
healthcheck:
test: ["CMD", "/endpoint"]
interval: 10s
timeout: 30s
retries: 4
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:9000"
git:
image: websoft9dev/git:$GIT_VERSION
container_name: websoft9-git
restart: always
volumes:
- gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- INSTALL_LOCK=true
- DISABLE_SSH=true
- RUN_MODE=prod
- HTTP_PORT=3000
- DISABLE_REGISTRATION=false
- REQUIRE_SIGNIN_VIEW=false
- ROOT_URL=http://localhost/w9git/
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port:3000"
proxy:
image: websoft9dev/proxy:$PROXY_VERSION
container_name: websoft9-proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- nginx_data:/data
- nginx_letsencrypt:/etc/letsencrypt
labels:
- "owner=websoft9"
- "com.docker.compose.w9_http.port: 80"
- "com.docker.compose.w9_https.port: 443"
- "com.docker.compose.w9_console.port: 81"
networks:
default:
name: websoft9
external: true
volumes:
apphub_logs:
apphub_config:
portainer:
gitea:
nginx_data:
nginx_letsencrypt:

View file

@ -1,8 +0,0 @@
# modify time: 202310250925, you can modify here to trigger Docker Build action
# Dockerfile refer to: https://github.com/go-gitea/gitea/blob/main/Dockerfile
FROM gitea/gitea:1.20.4
LABEL maintainer="Websoft9<help@websoft9.com>"
LABEL version="1.20.4"
COPY ./src/s6/user /etc/s6/user
RUN chmod -R 755 /etc/s6/user

View file

@ -1,19 +0,0 @@
# Readme
## Development
From official Gitea image, and:
- Complete install wizard automaticlly by enviroment INSTALL_LOCK
- Use default URL localhost for Host/Root_URL settings
## User
### Repository
How to clone a Repository ?
- Git clone a repository by external network address(gitea repository page's HTTP URL)
- Git clone a repository by internal network address(e.g. http://websoft9-git:3000/organization/repository.git

View file

@ -1,98 +0,0 @@
APP_NAME = gitea
RUN_MODE = prod
RUN_USER = git
WORK_PATH = /data/gitea
[repository]
ROOT = /data/git/repositories
[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
[repository.upload]
TEMP_PATH = /data/gitea/uploads
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = 119.8.96.66
SSH_DOMAIN = 119.8.96.66
HTTP_PORT = 3000
ROOT_URL = http://119.8.96.66:3000/
DISABLE_SSH = true
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = prcv5KuvKilAB_369Vr4saJf4QBdlMwD-vOXD2l7IHo
OFFLINE_MODE = false
[database]
PATH = /data/gitea/gitea.db
DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD =
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
[indexer]
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file
[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
[attachment]
PATH = /data/gitea/attachments
[log]
MODE = console
LEVEL = info
ROOT_PATH = /data/gitea/log
[security]
INSTALL_LOCK = true
SECRET_KEY =
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = *
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2OTQ1NzI0NDN9.kzFr-t0io9M_XQWojbvG20KPiXIZPS2GMadRBgR9xMM
PASSWORD_HASH_ALGO = pbkdf2
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.119.8.96.66
[lfs]
PATH = /data/git/lfs
[mailer]
ENABLED = false
[openid]
ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = true
[cron.update_checker]
ENABLED = false
[repository.pull-request]
DEFAULT_MERGE_STYLE = merge
[repository.signing]
DEFAULT_TRUST_MODEL = committer
[oauth2]
JWT_SECRET = vIGxNkS5o0NYgDZwxMIcS_zXbbN3GBLCTO5MseHgO8Q

View file

@ -1,5 +0,0 @@
## Readme
- Create admin credential by admin cli
- to do: Disable user register
- to do: Disable Gravatar

View file

@ -1,6 +0,0 @@
#!/bin/bash
[[ -f ./setup ]] && source ./setup
pushd /root >/dev/null
exec s6-svc -D /etc/s6/user
popd

View file

@ -1,53 +0,0 @@
#!/bin/bash
set -e
echo "start create user shell" >> /tmp/user
# Confirm gitea is running
count=1
response=""
cred_path="/data/gitea/credential"
admin_username="websoft9"
admin_email="help@websoft9.com"
while [ "$response" != "200" ]; do
response=$(curl -s -o /dev/null -w "%{http_code}" localhost:3000)
if [ "$response" = "200" ]; then
echo "gitea is runing"
break
fi
count=$((count+1))
if [ $count -gt 10 ]; then
echo "gitea is not runing"
break
fi
done
if [ -e "$cred_path" ]; then
echo "File $cred_path exists. Exiting script."
exit 0
fi
echo "Create admin credential by admin cli"
su -c "
if gitea admin user list | grep -q '$admin_username'; then
echo 'User already exists.'
exit 0
else
gitea admin user create --admin --username '$admin_username' --random-password --email '$admin_email' > /tmp/credential
touch /data/gitea/create_user 2>/dev/null
fi
" git
if [ -f /data/gitea/create_user ]; then
echo "Read credential from tmp"
username=$(grep -o "New user '[^']*" /tmp/credential | sed "s/New user '//")
if [ -z "$username" ] || [ "$username" != "websoft9" ]; then
echo "username is not websoft9, exit"
fi
password=$(grep -o "generated random password is '[^']*" /tmp/credential | sed "s/generated random password is '//")
rm -rf /tmp/credential
echo "Save to credential"
json="{\"username\":\"$admin_username\",\"password\":\"$password\",\"email\":\"$admin_email\"}"
echo "$json" > "$cred_path"
fi

View file

@ -1,23 +0,0 @@
# modify time: 202311071641, you can modify here to trigger Docker Build action
# from Dockerfile: https://github.com/NginxProxyManager/nginx-proxy-manager/blob/develop/docker/Dockerfile
# from image: https://hub.docker.com/r/jc21/nginx-proxy-manager
FROM jc21/nginx-proxy-manager:2.10.4
LABEL maintainer="Websoft9<help@websoft9.com>"
LABEL version="2.10.4"
RUN apt-get update && apt-get install --no-install-recommends -y curl jq && rm -rf /var/lib/apt/lists/*
COPY ./config/initproxy.conf /etc/
COPY ./s6/w9init/setuser.sh /app/setuser.sh
COPY ./s6/w9init/migration.sh /app/migration.sh
RUN chmod +x /app/setuser.sh /app/migration.sh
RUN export add_ip_data="const ipDataFile={[CLOUDFRONT_URL]:'ip-ranges.json',[CLOUDFARE_V4_URL]:'ips-v4',[CLOUDFARE_V6_URL]:'ips-v6'}[url];logger.info(ipDataFile);if(ipDataFile){return fs.readFile(__dirname+'/../lib/ipData/'+ipDataFile,'utf8',(error,data)=>{if(error){logger.error('fetch '+ipDataFile+' error');reject(error);return}logger.info('fetch '+ipDataFile+' success');resolve(data)})}" && \
sed -i "s#url);#&${add_ip_data}#g" /app/internal/ip_ranges.js && \
mkdir -p /app/lib/ipData && cd /app/lib/ipData && \
curl -O https://ip-ranges.amazonaws.com/ip-ranges.json && \
curl -O https://www.cloudflare.com/ips-v4 && \
curl -O https://www.cloudflare.com/ips-v6
CMD ["/bin/sh", "-c", "/app/migration.sh && /app/setuser.sh && tail -f /dev/null"]

View file

@ -1,7 +0,0 @@
# Readme
From official Nginx Proxy Manager image, and:
- add init_proxy.conf to image
- init install wizard and modify user and password
- lock the line of BoltDB at Portainer where envrionment=1

View file

@ -1,125 +0,0 @@
# ------------------------------------------------------------
# domain.com
# ------------------------------------------------------------
server {
listen 80;
listen [::]:80;
server_name ~\.?[0-9a-zA-Z]$;
access_log /data/logs/proxy-host-1_access.log proxy;
error_log /data/logs/proxy-host-1_error.log warn;
if ($http_referer ~* /w9deployment/) {
rewrite ^/locales/(.*) /w9deployment/locales/$1 break;
}
location / {
# Proxy!
include conf.d/include/proxy.conf;
}
# proxy for portainer
location /w9deployment/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Accept-Encoding \"\";
proxy_pass http://websoft9-deployment:9000/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
# proxy_http_version 1.1;
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = OPTIONS) {
return 204;
}
set $quot_tmp "\"";
set $portainer_jwt "${quot_tmp}${cookie_portainerJWT}${quot_tmp}";
sub_filter '</head>' "<script>($portainer_jwt)?window.localStorage.setItem('portainer.JWT', '$portainer_jwt'):null;</script></head>";
sub_filter_once on;
sub_filter_types *;
}
# proxy for Nginx proxy Manager
location /w9proxy/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://websoft9-proxy:81;
rewrite ^/w9proxy/?(.*)$ /$1 break;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_cache_bypass $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_cache_bypass $http_secret_header;
proxy_set_header Accept-Encoding \"\";
add_header Pragma "no-cache";
add_header Cache-Control "no-cache";
if ($request_method = OPTIONS) {
return 204;
}
sub_filter '</head>' "<script>var tokens='$cookie_nginx_tokens';(tokens)?window.localStorage.setItem('nginx-proxy-manager-tokens', '[{\"t\":\"$cookie_nginx_tokens\",\"n\":\"$cookie_nginx_nikeName\"}]'):null;</script></head>";
# source changes
sub_filter 'href="/' 'href="/w9proxy/';
sub_filter 'src="/' 'src="/w9proxy/';
sub_filter '/api' '/w9proxy/api';
sub_filter '/assets' '/w9proxy/assets';
sub_filter '/js/' '/w9proxy/js/';
# script changes
sub_filter 'r.p="/' 'r.p="/w9proxy/';
sub_filter '"/login' '"/w9proxy/login';
sub_filter 'case"/logout"' 'case"/w9proxy/logout"';
sub_filter 'window.location="/"' 'window.location="/w9proxy/"';
sub_filter 'history.start({pushState:!0})' 'history.start({pushState:!0,root: "/w9proxy/"})';
sub_filter 'i.history.navigate(e.' 'i.history.navigate(e.replace("/w9proxy","").';
sub_filter_types *;
sub_filter_once off;
}
# proxy for Gitea
location /w9git/ {
proxy_pass http://websoft9-git:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header 'Access-Control-Allow-Credentials' 'true';
if ($request_method = OPTIONS) {
return 204;
}
}
location /api/ {
proxy_pass http://websoft9-apphub:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header 'Access-Control-Allow-Origin' $http_origin always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,x-api-key' always;
if ($request_method = OPTIONS) {
return 204;
}
}
location /media/ {
proxy_pass http://websoft9-apphub:8081/images/;
}
# Custom
include /data/nginx/custom/server_proxy[.]conf;
}

View file

@ -1,5 +0,0 @@
# S6
S6 is a mulitply process management tools at Nginx Proxy Manager.
- nginx_proxy() at migration.sh: Migration initproxy.conf to Nginx, condition is compare Container created time and Named Volumes created time

View file

@ -1,23 +0,0 @@
#!/bin/bash
set +e
nginx_proxy(){
current_time=$(date +%s)
shadow_modified_time=$(stat -c %Y /etc/shadow)
time_difference=$((current_time - shadow_modified_time))
if [ ! -f /data/nginx/proxy_host/initproxy.conf ] || [ $time_difference -le 60 ]
then
cp /etc/initproxy.conf /data/nginx/proxy_host/
echo "Update initproxy.conf to Nginx"
else
echo "Don't need to update initproxy.conf to Nginx"
fi
}
nginx_proxy
set -e

View file

@ -1,61 +0,0 @@
#!/bin/bash
set +e
username="help@websoft9.com"
password=$(openssl rand -base64 16 | tr -d '/+' | cut -c1-16)
token=""
cred_path="/data/credential"
max_attempts=10
echo "Start to change nginxproxymanage users"
if [ -e "$cred_path" ]; then
echo "File $cred_path exists. Exiting script."
exit 0
fi
echo "create diretory"
mkdir -p "$(dirname "$cred_path")"
sleep 10
while [ -z "$token" ]; do
sleep 5
login_data=$(curl -X POST -H "Content-Type: application/json" -d '{"identity":"admin@example.com","scope":"user", "secret":"changeme"}' http://localhost:81/api/tokens)
token=$(echo $login_data | jq -r '.token')
done
echo "Change username(email)"
for attempt in $(seq 1 $max_attempts); do
response=$(curl -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"email": "'$username'", "nickname": "admin", "is_disabled": false, "roles": ["admin"]}' http://localhost:81/api/users/1)
if [ $? -eq 0 ]; then
echo "Set username successful"
break
else
echo "Set username failed, retrying..."
sleep 5
if [ $attempt -eq $max_attempts ]; then
echo "Failed to set username after $max_attempts attempts. Exiting."
exit 1
fi
fi
done
echo "Update password"
for attempt in $(seq 1 $max_attempts); do
response=$(curl -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"type":"password","current":"changeme","secret":"'$password'"}' http://localhost:81/api/users/1/auth)
if [ $? -eq 0 ]; then
echo "Set password successful"
echo "Save to credential"
json="{\"username\":\"$username\",\"password\":\"$password\"}"
echo "$json" > "$cred_path"
break
else
echo "Set password failed, retrying..."
sleep 5
if [ $attempt -eq $max_attempts ]; then
echo "Failed to set password after $max_attempts attempts. Exiting."
exit 1
fi
fi
done
set -e

View file

@ -1,42 +0,0 @@
# Documentation for core maintainers
This documentaion is from [jenkins MAINTAINERS](https://github.com/jenkinsci/jenkins/blob/master/docs/MAINTAINERS.adoc) which have a paradigm of rigorous open source project maintenance
## Scope
This document applies to the following components:
- Websoft9 core
- Websoft9 core plugins
- docker-library
## Roles
| Role/job | submit pr | review pr | assign pr | merge pr | close pr | create issue | manage issue | release |
| ------------ | --------- | --------- | --------- | -------- | -------- | ------------ | ------------ | ------- |
| Contributor | √ | | | | | √ | | |
| Issue Team | √ | | | | | √ | √ | |
| PR Reviewer | √ | √ | | | | √ | | |
| Release Team | √ | | | | | √ | | √ |
| Maintainer | √ | √ | √ | √ | √ | √ | | |
| PR Assignee | | | | √ | | √ | | |
* **Contributor**: submit pull requests to the Jenkins core and review changes submitted by others. There are no special preconditions to do so. Anyone is welcome to contribute.
* **Issue Triage Team Member**: review the incoming issues: bug reports, requests for enhancement, etc. Special permissions are not required to take this role or to contribute.
* **Core Pull Request Reviewer**: A team for contributors who are willing to regularly review pull requests and eventually become core maintainers.
* **Core Maintainer**: Get permissions in the repository, and hence they are able to merge pull requests.Their responsibility is to perform pull request reviews on a regular basis and to bring pull requests to closure, either by merging ready pull requests towards weekly releases ( branch) or by closing pull requests that are not ready for merge because of submitter inaction after an extended period of time.
* **Pull Request Assignee**: Core maintainers make a commitment to bringing a pull request to closure by becoming an Assignee. They are also responsible to monitor the weekly release status and to perform triage of critical issues.
* **Release Team Member**: Responsible for Websoft9 weekly and LTS releases
## Pull request review process
## Pull request Merge process
## Issue triage
## Release process
## Tools
## Communication

View file

@ -1,24 +0,0 @@
## Architecture
Websoft9 is very simple [architecture](https://www.canva.cn/design/DAFpI9loqzQ/hI_2vrtfoK7zJwauhJzipQ/view?utm_content=DAFpI9loqzQ&utm_campaign=designshare&utm_medium=link&utm_source=publishsharelink) which used [Redhat Cockpit ](https://cockpit-project.org/) for web framework and [Docker](https://www.docker.com/) for running [application](https://github.com/Websoft9/docker-library).
The benefits of this architecture means you don't have to learn new technology stacks or worry about the lack of maintenance this project.
![Alt text](image/archi.png)
What we do is integrating below stacks's API or interfaces to Cockpit console by [Cockpit packages (Also known as plugin)](https://cockpit-project.org/guide/latest/packages.html) :
- [Nginx Proxy Manager](https://nginxproxymanager.com/): A web-based Nginx management
- [Portainer](https://www.portainer.io/): Powerful container management for DevSecOps
- [Duplicati](https://www.duplicati.com/): Backup software to store encrypted backups online
- [Redis](https://redis.io/): The open source, in-memory data store
- [Appmanage](https://github.com/Websoft9/websoft9/tree/main/appmanage): API for create and manage docker compose based application powered by Websoft9
- [websoft9-plugins](https://github.com/websoft9?q=plugin&type=all&language=&sort=): Cockpit packages powered by Websoft9
As Websoft9 is a complete product, we also offer:
* API
* CLI
And Websoft9 is more attractive to users is [200+ application templates](https://github.com/Websoft9/docker-library).

View file

@ -1,24 +0,0 @@
# Developer Guide
## Release
#### 制品库自动化
- 插件制品管理:开发人员开发测试完成后,修改插件版本,触发 Action 构建 Github packages 制品
- docker-libaray 库制品管理:开发人员测试完成后,修改 library 版本,触发 Action 构建 Github packages 制品
- websoft9 制品管理:开发人员修改 appmanage 源码或微服务 docker-compose 测试完成后,修改 微服务 版本,触发 Action 构建 Dockerhub 镜像制品以及后台微服务 Github packages 制品
> Portainer,redis,nginxproxymanager 使用外部 dockerhub 镜像
### 自动化测试
当各个制品更新后,项目管理者修改 version_test.json 对应的组件的版本,构建 Action 触发自动化系统测试。
自动化测试失败,通知各开发人员,删除制品,修改后重新生成制品。
自动化测试成功,同步 version_test.json 到 version.json 新制品正式发布。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -1,151 +0,0 @@
# 需求
从两个主线理解 stackhub 的需求:
- 应用生命周期管理:寻找、安装、发布、停止、卸载、升级等软件全生命周期。
- 基础设施运维管理:安全、存储、文件、容器、监控等系统管理
## 应用生命周期
### 业务需求
#### 寻找
用户可以通过两个入口寻找应用:
- 应用商店:采用一级分类的方式展现应用,并支持**筛选+搜索**的方式以便于用户检索
- Docker 镜像仓库:检索 Docker 镜像仓库,找到对应的应用
#### 安装
- 用户自主安装应用,后端按顺序依次启动目标应用
- 启动应用之前先进行资源约束判断,不符合条件的目标应用不予安装
- 与安装有关的状态:安装中、运行中、安装失败、反复重启、已停止
#### 发布
- 以域名或端口的方式,将运行中的应用发布出去,供外部用户访问。
- 自助设置 HTTPS上传或更新证书
#### 停止
将应用服务停止
#### 卸载
卸载应用并删除数据
#### 升级
升级应用,如果升级失败会自动回滚到升级之前的状态
#### 恢复
在已有的完整备份的基础,恢复应用。
可能存在两种情况:
- 覆盖现有应用
- 恢复成一个新的应用
#### 克隆
克隆一个已经存在的应用,命名为新应用
### 技术需求
#### 模板编排
应用的底层编排 100% 以 Docker Compose 语法作为编排语言
#### 多语言
- 前端支持 i18n
- 后端接口支持英文
#### 用户管理
- 支持多个用户,用户角色分为普通用户和管理员用户
- 普通用户可以创建和管理自己的应用,不可以删除他人的应用
#### UI 自适应
UI 自适应各种屏幕尺寸
#### 2FA
引入一种双重登录策略
#### 商店基础设置
- 商店 Logo 可自定义
- 语言、时区可选
- 绑定域名
- SMTP 信息填写
#### 通知
- SMTP 邮件通知
#### 商店更新
商店支持在线更新提示和在线更新
#### API
支持生成 API Tokens
#### CLI
基于 API 的 CLI
#### 仓库管理
默认以 DockerHub 作为镜像仓库,支持自建仓库并同步 DockerHub 镜像
#### 安装程序
一键自动化安装程序,类似:
```
curl https://websoft9.github.io/stackhub/install/install.sh | bash
```
主要步骤包括:
1. Check 硬件、操作系统、cpu 架构
2. 安装依赖包
3. 安装 docker
4. 下载各源码包
5. 启动个源码对应服务
## 基础设施运维
### SSH 终端
Web-Based SSH 终端
### 文件管理器
Web-Based 文件管理器
### 存储管理
- 支持接入第三方对象存储
### 备份
备份完整的应用数据:
- 自定义备份时间区间
- 自动备份可取消
- 备份可以管理:删除、下载等
### 容器管理
可视化的容器管理,包括:拉镜像、创建/删除/停止容器、SSH 进入容器、向容器上传文件等
### 系统监控
- 监控容器的 CPU内存和存储消耗情况
- 监控系统的 CPU内存和存储消耗情况

View file

@ -1,339 +0,0 @@
# Process
要理解整个架构设计,先打开[组件图](https://www.canva.cn/design/DAFt2DhfqYM/3uwKe09X5xaD4QPc47rNMQ/view?utm_content=DAFt2DhfqYM&utm_campaign=designshare&utm_medium=link&utm_source=publishsharelink),然后结合一下内容进行阅读:
所有的微操作一定归属于如下三个类别:
- CI持续集成即源码准确性
- CD持续部署即让软件 running目前采用拉式方式与CI协作
- CP持续发布即通过域名让用户可以访问
另外还有与系统维护相关的:
- Settings
- CLI
## API
API 接口功能设计:
### app/install
功能:安装应用并自动绑定域名
输入参数:
```
body:
{
- app_name # 产品名
- app_id # 自定义应用名称
- domains[] #域名-可选
- default_domain #默认域名-可选:设置.env中APP_URL
- edition{dist:community, version:5.0} #应用版本来自variable.json但目前variable.json中只有 version 的数据
- endpointId: 安装目的地portainer中有定义默认为 local
}
```
过程:
1. 参数验证:
app_id 验证:
业务要求gitea 中是否存在同名的 repositoryPortainer中是否存在同名stack
技术要求-【非空容器要求2位-20位字母数字以及-组成 giteatodo portainertodo】
app_name 验证: 在gitea容器的library目录下验证
domains[]验证是否绑定过数量不能超过2泛域名+其他域名
default_domain验证来自domains[]中,自定义域名优先
edition: community这个不做验证保留扩展只做version处理
endpointId通过Portainer容器取名称【local】的endpointId不存在报错
2. CIGitea 创建 repository通过Gitea创建仓库并修改.env文件
3. CD: Portainer
创建websoft9网络判断 websoft9 network (先判断是否存在)
Portainer 基于 Gitea Repository 在对应的 endpointId 中创建项目staus: [active,inactive]
4. CPNginx 为应用创建 Proxy 访问如果Proxy创建失败应用安装成功但提示Proxy创建失败不做应用安装回滚
2-3 步骤是有状态操作(产生对后续操作有影响的记录),故需考虑事务完整性。
### apps
查询所有apps的信息返回完整数据。等同于 CD: deploy/apps
另外app 的状态以及各个状态对应的操作:
- 状态:
- Active等同于 Portainer Active。此状态下显示容器的状态 running(1),stopped(2)
- Unactive,等同于 Portainer Unactive
- 操作:
- for running: stop | start | restart | redeploy | delete && delete(down -v)
- for Unactive: redeploy | delete(down -v)
### apps/{id}/*
对单个 apps 的增删改查:
- 查询deploy/apps/{id} with **get** method
- 启动deploy/apps/{id}/start
- 停止deploy/apps/{id}/stop
- 重启deploy/apps/{id}/restart
- 迁移deploy/apps/{id}/migrate
- 重建deploy/apps/{id}/git/redeploy + deploy/apps/{id}/restart
- 卸载:
- APP_Manage 调用 integration/,删除 Repository
- APP_Manage 调用 publish/nginx/proxy删除 Proxy
- APP_Manage 调用 deploy/apps/{id} with **delete** method删除应用
> 卸载必须是一个事务操作,确保完成所有步骤,以上先后顺序非常关键
### app/domains
App 域名的:增、删、改、查。
输入参数:
pulisherId: 默认为本地 nginx将来可扩展支持云平台的应用访问网关。
```
body:
{
- app_id
- domains[] 可选
- default_domain 可选
}
```
流程:
- CP: publish/nginx/proxy
- CI: Gitea 修改 repository 的 .env 文件中的 APP_URL 为默认域名
- CDdeploy/apps/{id}/git/redeploy + deploy/apps/{id}/restart
## Settings
配置文件可以通过接口和CLI进行更改
### 系统配置
系统配置,需重启服务后生效。
system.ini
### 应用配置
app.ini
应用配置一般会提供API供前端调用。应用配置更改后不需要重启。
功能:
- settings 增删改查
```
[system]
# websoft9 install path, it can not modify now
install_path=/data/websoft9
# apps install path, it can not modify now
apps_path=/data/compose
# enable appstore preview, it use for CLI upgrade COMMAND
appstore_preview=false
[address]
# Wildcard Domain Name for application
wildcard_domain=test.websoft9.com
[smtp]
smtp_port=743
smtp_server=smtp.websoft9.com
smtp_tls/ssl=true
smtp_user=admin
smtp_password=password
[receive]
# receive the notify of system
email=help@websoft9.com
wechat=
```
## CLI
CLI 是安装到服务器的服务端命令行工具。它的功能有几种来源:
1. 继承:由 API 直接转换
2. 相关:多个 API 以及 组合
3. 无关:与 API 无关,
具体指令以及参数设计如下:
```
Usage: w9 [OPTIONS] COMMAND sub-COMMAND
Common Commands
version 查询 websoft9 版本
repair 修复 websoft9
clean 清空 websoft9 使用过程中不需要的残留资源
upgrade 检查并更新 [core|plugin], --check 只检查
uninstall 删除 Websoft9 所有服务以及组件,除了 Docker 以及 Docker 应用之外
environments list all Environments
apikey 生产以及管理 AppManage keys
ip --replace newIP直接更改 gitea 和 Nginx IP相关的配置
App Commands:
install 安装应用
ls List 应用列表 [app_id, app_name, status, time, endpointId]
inspect 显示 APP 详细信息
start 启动一个停止的应用
stop 停止一个运行中的应用
restart 重启应用
redeploy 重建应用(包含更新镜像后重建)
delete 删除应用
Global Options:
-c, --context string
-D, --debug Enable debug mode
-e, --environment which environment you used
Run 'w9 COMMAND --help' for more information on a command.
```
## Core
### CI
CI 遵循几个法则:
* 为 CD 准备一个完全可用的编排物料
* Git 驱动,保证编排物料与应用运行环境分离,编排物料可修改可复原
* 编排物料中的资源(包/镜像)具备良好的网络可达性
CI 过程中除了直接使用 [Gitea API](https://docs.gitea.cn/api/1.19/) 之外,还需增加如下业务:
#### integation/repository/create
功能:
基于本地目录 library/apps/app_name创建一个符合 Websoft9 规范格式的 repository名称为app_id
> app_name 是软件名称例如wordpress。app_id 是用户安装的应用名称例如mywordpress
步骤:
1. 在 Gitea 中创建一个名称为 app_id 的 repository
2. 修改 Gitea repository 仓库的设置属性,只保留【代码】栏
#### integation/repository/modify
更改临时目录 .env 文件中的重要参数:
- APP_URL 用域名/公网IP替换
- POWER_PASSWORD 使用 16位 【大小写数字特殊字符】 替代
- APP_VERSION 根据安装输入参数替换
- APP_NAME 更换为 app_id
然后 git push
#### integation/repository/delete
### CD
CD 遵循几个法则:
* 可以管理应用的完全生命周期
* 应用可以指定部署到local之外的服务器或集群环境portainer 中对应的术语为 endpoint 或 environment
* 部署编排物料(CI 的产出物)可以是 docker-compose也可以是 helm
* 也可以支持源码编译成镜像后自动部署参考waypoint
#### deploy/apps/create/standalone/repository
基于 repository 创建应用100% 使用 Portainer API /stacks/create/standalone/repository
#### deploy/apps/{id}/git
设置 portainer 与 repository 之间的连接关系100% 使用 Portainer API /stacks/{id}/git
#### deploy/apps
List all apps继承 Portainer API /stacks
额外需要增加如下几类数据:
1. 将 app 主容器的 "Env" 合并到 Portainer API 返回的 env[] 中。
> portaier 中的 repository 安装方式中,.env 并不会被 portainer 保存到接口中
2. portainer 中的应用目录的 variables.json 或 repository variables.json
3. Gitea API 列出当前 APP 的 repository 之 URL提供访问链接?
4. 所用应用的数据目录:/var/lib/docker/volumes/...
5. Portainer 通过主容器的 Label 标签和 Ports获取 app_*_port等
#### deploy/apps/{id}
与 Portainer API /stacks{id} 雷同,支持 get(查询), delete删除
#### deploy/apps/{id}/git/redeploy
100% 使用 Portainer API /stacks/{id}/git/redeploy
#### deploy/apps/{id}/start
100% 使用 Portainer API /stacks/{id}/start
#### deploy/apps/{id}/stop
100% 使用 Portainer API /stacks/{id}/stop
#### deploy/apps/{id}/restart
Portainer 未提供对应的 API可以创建此操作也可以直接在前端通过 stop & start 组合实现。
#### deploy/apps/{id}/migrate
将 Docker 应用迁移到另外一台服务器上。此需求暂不实现
100% 使用 Portainer API /stacks/{id}/migrate
### CP
#### publish/nginx/proxy
function proxy(hostdomains[], Optional:port, Optional:exra_proxy.conf)
**init()**
也可以使用 getPort(), getExra_proxy()
1. 获取 Port: 从 portainer.containers 接口中 Label 属性集中获取 http 或 https
> com.docker.compose.http.port": "9001" | com.docker.compose.https.port": "9002"
2. 获取 exra_proxy.conf: 从 Gitea 接口中获取 repository 的 src/nginx_proxy.conf
**update()**
修改 proxy 中的 domain
**add()**
查询 Nginx 中是否有此应用的 Proxy
- Y将新的域名插入到 Proxy 中(忽略 nginx_proxy.conf
- N新增 Proxy
**delete()**
删除所有相关的 proxys
**list()**
查询所有相关的 proxys
**enable()**
enable所有相关的 proxys
**disable()**
disable 所有相关的 proxys

View file

@ -1,57 +0,0 @@
# 概述
## 需求草稿
| | Cloudron | [casaos](https://www.casaos.io/) | umbrel | runtipi |
| -------------- | -------- | -------------------------------------------------------- | ------------ | ------- |
| 应用编排 | | 单一镜像 | | 多镜像compose 编排 |
| 市场应用来源 | | 官方+社区 | 官方+社区 | |
| 一键安装程度 | | 不需任何配置 | 不需任何配置 | |
| 应用访问方式 | | 端口 | 端口 | |
| 自定义安装应用 | | Y | N | N |
| Web 管理容器 | | Y | N | |
| 默认镜像仓库 | | DockerHub | | |
| 自适应 | | Y | Y | |
| 多语言 | | Y | N | |
| 用户管理 | | 单一用户 | 单一用户 | |
| 自带应用 | | 文件,服务器终端,容器终端,监控,日志 | 监控,日志 | |
| 应用管理 | | 完整容器参数设置,克隆,绑定域名?备份?证书? | 无 | |
| 应用更新 | | N | | |
| 后端语言 | | Go | | |
| API | | HTTP API | | |
| 前端 | | vue.js | | |
| CLI | | Y | | |
| HTTP 服务器 | | 无,端口访问应用 | | traefik |
| 公共数据库 | | 无 | | |
| 开发文档 | | [wiki](https://wiki.casaos.io/en/contribute/development) | | |
| 2FA | | N | Y | |
| 安装方式 | | 服务器安装 | 容器安装 | |
| 商店更新 | | N | Y | Y |
| 商店绑定域名 | Y | N | N | |
| DNS服务 | Y | N | | |
* 应用自动分配4级域名后如何再 CNAME 二级域名?
### casaos 架构分析
#### 安装脚本
1. Check硬件、操作系统、cpu架构
2. 安装依赖包
3. 安装docker
4. 下载各源码包
5. 启动个源码对应服务
#### 源码解析
| 运行时项目 | 对应项目源码 | 说明 |
| -------------- | -------- | -------------------------------------------------------- |
| casaos | CasaOS | 每隔5秒通过websocekt推送内存/CPU/网络等系统信息;提供ssh登录操作的http接口;提供"sys", "port", "file", "folder", "batch", "image", "samba", "notify"这些http接口的访问|
| casaos-message-bus | CasaOS-MessageBus | 类似一个MQ提供消息的发布/订阅 |
| casaos-local-storage | CasaOS-LocalStorage | 每隔5S统计磁盘/USB信息,提供监控信息;提供http接口访问disk/usb/storage信息 |
| casaos-user-service | CasaOS-UserService | 通过http server提供用户管理的接口 |
| casaos-app-management | CasaOS-AppManagement | 使用CasaOS-AppStore中App的元数据;提供所有appList的分类/列表/详细信息;通过docker来管理app,提供安装/启动/关闭/重启/日志查看等相关接口;docker-compose管理V2;|
| casaos-gateway | CasaOS-Gateway | 提供Gateway自身管理接口,比如切换Gateway的port的接口,查看所有路由的接口;提供CasaOS-UI的静态资源访问服务;根据请求的PATH将请求代理转发至其它模块 |
| casaos-cli | CasaOS-CLI | 通过命令行的方式来调用CasaOS-Gateway的接口,该模块未完全实现,实现了部分命令 |
| linux-all-casaos | CasaOS-UI | VUE2,CasaOS的Web源码,编译后的html/js/image/css等由CasaOS-Gateway提供访问入口,所有API接口指向CasaOS-Gateway |
| - | CasaOS-Common | Common structs and functions for CasaOS |

View file

@ -1,37 +0,0 @@
# 软件工厂
由 Websoft9 自主研发的面向高校的【软件工厂】解决方案,学生和老师可以自由使用镜像库用于教学。
## 商业需求
高校老师和学生在教学中需要使用大量的开源软件作为教学的载体,以及通过使用开源软件学习实战的经验,打开商业化软件领域的大门。
目前,老师和学生受制于眼界以及技术原因,无法很方便的搭建和使用各种开源软件,大大的制约了教学的发展。
我们目前的方案只需要加以【盒子化】即可满足用户的需要。
## 业务模式
对我们既有的方案进行盒子化之后,通过如下方式盈利:
- 售卖软件解决方案以及技术支持
- 云资源分成
- 镜像按小时付费
- 知识库付费
- 课程合作付费
## 功能需求
盒子化的解决方案包括:
### 业务功能
- 可以一键使用的软件库(提供 300+场景方案)
- 可以在线使用的工具库(基于 Web 的工具库,学生在上课中无需安装大量的客户端工具即可完成任务)
- 可以管理教学过程的慕课系统
### 系统功能
- 账号管理
- 日志管理
- 安全管理
- 资源消耗管理

View file

@ -1,8 +0,0 @@
# Developer Guide
## Mulitiple language
Below points you should know if you want to tranlate:
- Every plugin's po.zh_CN.js can be used for other Cockpit plugin
- po.zh_CN.js.gz at base1 is the system language file

View file

@ -1,29 +0,0 @@
# recruit
In order to optimize the app management architecture and code specifications, and perform daily maintenance on new features and bugs, Websoft9 recruits a senior Python development expert.
## Requirements
1. Proficient in Python and have architectural experience in Python web projects
2. Have experience in developing distributed (caching, message middleware)
3. Familiar with Docker and other container technologies
4. Love coding and willing to continuously optimize code at work
5. Strong document reading and understanding skills as well as document writing experience
## Job Description
1. Complete additional features and modify bugs for existing projects
2. Provide reasons and solutions for optimizing the project architecture and API methods
## Work form
Remote, must complete 40 hours of work per month
## Remuneration and payment
Pay 4000 yuan before the 10th of each month

View file

@ -1,33 +0,0 @@
# Team and Division
## Active Team{#active-team}
The Websoft9 active team works on the core functionality, as well as the documentation website.
* Xu Wei: One of the founders of Websoft9, responsible for code review
* Darren Chen: One of the founders of Websoft9, responsible for user experience design and architecture
* Morning Tan: Testing
* Lao Zhou: Document writing and issue collection feedback
## Architect Consultant
Create more, better and more realistic software solutions for the world
* Liu Guanghui: Engaged in enterprise architecture for 20 years, experienced complete typical enterprise applications such as ERP, MES, WMS, e-commerce, OA, etc.
## Candidate
- [mayo7e](https://github.com/mayo7e): [#296](https://github.com/Websoft9/websoft9/issues/296) mayowa.wh@gmail.com
## Honorary Alumni
Websoft9 would never be what it is today without the huge contributions from these folks who have moved on to bigger and greater things.
* Zengxc: RHCE
* [Brendan](https://github.com/dudeisbrendan03): Infra Engineer in Greater Manchester. Studying MSc @ Lancaster
* [Biao Yang](https://github.com/hotHeart48156): Hot heart and smart developer
* [Junhao](https://github.com/hnczhjh): RedHat Engineer CA, Studding at ChangSha colleague
* [QiuJiaHon](https://github.com/orgs/Websoft9/people/QiuJiaHon): Studing at Hunan Normal University
* [Ryan Gates](https://github.com/gatesry)
* [Kai Jiao](https://github.com/jiaosir-cn)
* [Geraintl yu](https://github.com/geraintlyu)

View file

@ -1,28 +0,0 @@
# User Guide
## FAQ
#### user can not sudo?
```
# add user to sudo/admin group (select one command)
usermod -aG wheel username
usermod -aG sudo username
# sudo not need to input password
```
#### Can not login with correct credential?
Many reason may make you login failed with the correct credential:
- Cookie at you browser if IP change, need to clear cookie
- *.override.json is not correct
- TLS certificate
- User not allowed login, need to modify ssh_config file
More details, you can get it from `sudo grep cockpit /var/log/messages`
#### How to modify Websoft9 port?
Access web console > settings or use cli to modify port

View file

@ -1,58 +0,0 @@
# Install
- The [install.sh](./install.sh) is the entry file for install or upgrade
- You can separate running the [install_cockpit.sh](./install_cockpit.sh), [install_docker.sh](./install_docker.sh), [install_plugins.sh](./install_plugins.sh) also
- The [uninstall.sh](./install.sh) is the entry file for uninstall
## User it
```
# install or upgrade Websoft9
wget -O install.sh https://websoft9.github.io/websoft9/install/install.sh && bash install.sh
# install or upgrade Websoft9 with parameters
wget -O install.sh https://websoft9.github.io/websoft9/install/install.sh && bash install.sh --port 9000 --channel release --path "/data/websoft9/source" --version "latest"
# install or upgrade Cockpit with parameters
wget -O - https://websoft9.github.io/websoft9/install/install_cockpit.sh | bash --port 9000
# install or upgrade Docker
wget -O - https://websoft9.github.io/websoft9/install/install_docker.sh | bash
# uninstall by default
curl https://websoft9.github.io/websoft9/install/uninstall.sh | bash
# uninstall all
wget -O - https://websoft9.github.io/websoft9/install/uninstall.sh | bash /dev/stdin --cockpit --files
```
## Develop it
This install script have below related resources:
- Tools: Install or upgrade some useful software packages at Linux
- Source Code: Download source code from artifactory
- Docker: Install and upgrade Docker, compose up **backend service** with docker-compose.yml
- Cockpit: Install and upgrade Cockpit and its Packages, manage it port, fix it menu
- Plugins: Install and upgrade Websoft9 plugins which is the **frontend**
- Systemd: Install and upgrade websoft9.serivce
- Set Firewalld: let 80,443 and Cockpit port allowed, Cockpit and Docker service with firewalld
The install script should adhere to the following principles:
1. Not allowed to modify the source code of the application.
2. Every task must have an exception exit mechanism.
3. Both installation and updates should be considered simultaneously.
4. Upgrade script should not overwrite existing configurations.
5. Duplication of codes in any form is not allowed, it must used function.
6. Paths, ports, etc. must be defined using variables.
Some default parameters you should know:
- Websoft9 root path*/data/websoft9/source*
- Websoft9 Systemd script path: */opt/websoft9/systemd*
- Plugins path: */usr/share/cockpit*
- Cockpit config path: */ect/cockpit*
- Cockpit default port: 9000

View file

@ -1,448 +0,0 @@
#!/bin/bash
# Define PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# Export PATH
export PATH
# Command-line options
# ==============================================================================
#
# --version
# Use the --version option to install a special version for installation. default is latest, for example:
#
# $ sudo bash install.sh --version "0.8.25"
#
# --port <9000>
# Use the --port option to set Websoft9 cosole port. default is 9000, for example:
#
# $ sudo bash install.sh --port 9001
#
# --channel <release|dev>
# Use the --channel option to install a release(production) or dev distribution. default is release, for example:
#
# $ sudo bash install.sh --channel release
#
# --path
# Use the --path option to for installation path for example:
#
# $ sudo bash install.sh --path "/data/websoft9/source"
#
# --devto
# Use the --devto option to developer mode, devto is the developer code path, for example:
#
# $ sudo bash install.sh --devto "/data/dev/mycode"
#
# ==============================================================================
# 设置参数的默认值
version="latest"
channel="release"
path="/data/websoft9/source"
# 获取参数值
while [[ $# -gt 0 ]]; do
case $1 in
--version)
version="$2"
shift 2
;;
--port)
port="$2"
shift 2
;;
--channel)
channel="$2"
shift 2
;;
--path)
path="$2"
shift 2
;;
--devto)
devto="$2"
shift 2
;;
*)
shift
;;
esac
done
if [ -n "$port" ]; then
export port
else
export port=9000
fi
starttime=$(date +%s)
# 输出参数值
echo -e "\n------ Welcome to install Websoft9, it will take 3-5 minutes ------"
echo -e "\nYour installation parameters are as follows: "
echo "--version: $version"
echo "--port: $port"
echo "--channel: $channel"
echo "--path: $path"
echo "--devto: $devto"
echo -e "\nYour OS: "
cat /etc/os-release | head -n 3 2>/dev/null
# Define global vars
# export var can send it to subprocess
export http_port=80
export https_port=443
export install_path=$path
export channel
export version
export systemd_path="/opt/websoft9/systemd"
export source_zip="websoft9-$version.zip"
export source_unzip="websoft9"
export source_github_pages="https://websoft9.github.io/websoft9"
# inotify-tools is at epel-release
export repo_tools_yum="epel-release"
export tools_yum="git curl wget yum-utils jq bc unzip inotify-tools"
export tools_apt="git curl wget jq bc unzip inotify-tools"
export docker_network="websoft9"
export artifact_url="https://w9artifact.blob.core.windows.net/$channel/websoft9"
# export OS release environments
if [ -f /etc/os-release ]; then
. /etc/os-release
else
echo "Can't judge your Linux distribution"
exit 1
fi
echo Install from url: $artifact_url
# Define common functions
Wait_apt() {
# Function to check if apt is locked
local lock_files=("/var/lib/dpkg/lock" "/var/lib/apt/lists/lock")
for lock_file in "${lock_files[@]}"; do
while fuser "${lock_file}" >/dev/null 2>&1 ; do
echo "${lock_file} is locked by another process. Waiting..."
sleep 5
done
done
echo "APT locks are not held by any processes. You can proceed."
}
export -f Wait_apt
install_tools(){
echo_prefix_tools=$'\n[Tools] - '
echo "$echo_prefix_tools Starting install necessary tool..."
if [ "$ID" = "rhel" ] || [ "$ID" = "ol" ]; then
RHEL_VERSION=${VERSION_ID%%.*}
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-${RHEL_VERSION}.noarch.rpm >/dev/null
if [ $? -ne 0 ]; then
exit 1
fi
elif [ "$ID" = "centos" ] || [ "$ID" = "rocky" ]; then
sudo yum install -y "$repo_tools_yum" >/dev/null
if [ $? -ne 0 ]; then
exit 1
fi
elif [ "$ID" = "amzn" ]; then
sudo amazon-linux-extras install epel -y >/dev/null
if [ $? -ne 0 ]; then
exit 1
fi
fi
dnf --version >/dev/null 2>&1
dnf_status=$?
yum --version >/dev/null 2>&1
yum_status=$?
apt --version >/dev/null 2>&1
apt_status=$?
if [ $dnf_status -eq 0 ]; then
for package in $tools_yum; do
echo "Start to install $package"
sudo dnf install -y $package > /dev/null
if [ $? -ne 0 ]; then
exit 1
fi
done
elif [ $yum_status -eq 0 ]; then
for package in $tools_yum; do
echo "Start to install $package"
sudo yum install -y $package > /dev/null
if [ $? -ne 0 ]; then
exit 1
fi
done
elif [ $apt_status -eq 0 ]; then
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
echo "Waiting for other software managers to finish..."
sleep 5
done
sudo apt-get update -y 1>/dev/null 2>&1
for package in $tools_apt; do
echo "Start to install $package"
sudo apt-get install $package -y > /dev/null
if [ $? -ne 0 ]; then
exit 1
fi
done
else
echo "You system can not install Websoft9 because not have available Linux Package Manager"
exit 1
fi
}
download_source() {
echo_prefix_source=$'\n[Download Source] - '
echo "$echo_prefix_source Download Websoft9 source code from $artifact_url/$source_zip"
find . -type f -name "websoft9*.zip*" -exec rm -f {} \;
if [ -d "$install_path" ]; then
echo "Directory $install_path already exists and installation will cover it."
else
sudo mkdir -p "$install_path"
fi
wget "$artifact_url/$source_zip"
if [ $? -ne 0 ]; then
echo "Failed to download source package."
exit 1
fi
sudo unzip -o "$source_zip" -d "$install_path" > /dev/null
if [ $? -ne 0 ]; then
echo "Failed to unzip source package."
exit 1
fi
cp -r $install_path/$source_unzip/* "$install_path"
if [ $? -ne 0 ]; then
echo "Move directory failed"
exit 1
fi
rm -rf "$source_zip" "$install_path/$source_unzip"
}
check_ports() {
local ports=("$@")
echo "Stop Websoft9 Proxy and Cockpit service for reserve ports..."
sudo docker stop websoft9-proxy 2>/dev/null || echo "docker stop websoft9-proxy not need "
for port in "${ports[@]}"; do
if ss -tuln | grep ":$port " >/dev/null && ! systemctl status cockpit.socket | grep "$port" >/dev/null; then
echo "Port $port is in use or not in cockpit.socket, install failed"
exit
fi
done
echo "All ports are available"
}
merge_json_files() {
local target_path="/etc/docker/daemon.json"
python3 - <<EOF 2>/dev/null
import json
import urllib.request
import os
def merge_json_files(file1, file2):
print("Merge from local file... ")
with open(file1, 'r') as f1, open(file2, 'r') as f2:
data1 = json.load(f1)
data2 = json.load(f2)
merged_data = {**data1, **data2}
with open(file1, 'w') as f:
json.dump(merged_data, f, indent=4)
def download_and_merge(url, file_path):
print("Download daemon.json from url and merge... ")
with urllib.request.urlopen(url) as response:
data = json.loads(response.read().decode())
with open(file_path, 'r') as f:
local_data = json.load(f)
merged_data = {**local_data, **data}
with open(file_path, 'w') as f:
json.dump(merged_data, f, indent=4)
# Create target file if it does not exist
if not os.path.exists("${target_path}"):
os.makedirs(os.path.dirname("${target_path}"), exist_ok=True)
with open("${target_path}", 'w') as f:
json.dump({}, f)
if os.path.exists("${install_path}/docker/daemon.json"):
merge_json_files("${target_path}", "${install_path}/docker/daemon.json")
elif urllib.request.urlopen("${source_github_pages}/docker/daemon.json").getcode() == 200:
download_and_merge("${source_github_pages}/docker/daemon.json", "${target_path}")
else:
print("No target daemon.json file need to merged")
EOF
if [ $? -ne 0 ]; then
echo "merge daemon.json failed, but install continue running"
fi
}
set_docker(){
echo "Set Docker for Websoft9 backend service..."
merge_json_files
if ! systemctl is-active --quiet firewalld; then
echo "firewalld is not running"
else
echo "Set firewall for Docker..."
sudo sudo firewall-cmd --permanent --new-zone=docker 2> /dev/null
sudo firewall-cmd --permanent --zone=docker --add-interface=docker0 2> /dev/null
sudo firewall-cmd --permanent --zone=docker --set-target=ACCEPT
sudo firewall-cmd --reload
sudo systemctl stop firewalld
sudo systemctl disable firewalld
fi
sudo systemctl restart docker
}
install_backends() {
echo_prefix_backends=$'\n[Backend] - '
echo "$echo_prefix_backends Install backend docker services"
set_docker
cd "$install_path/docker"
if [ $? -ne 0 ]; then
echo "Failed to change directory."
exit 1
fi
sudo docker network inspect $docker_network >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Docker network '$docker_network' already exists."
else
sudo docker network create $docker_network
if [ $? -ne 0 ]; then
echo "Failed to create docker network."
exit 1
fi
fi
# set to devloper mode
if [ -n "$devto" ]; then
sed -i "s|\(- \).*:/websoft9/apphub-dev|\1$devto:/websoft9/apphub-dev|g" docker-compose-dev.yml
composefile=docker-compose-dev.yml
else
composefile=docker-compose.yml
fi
container_names=$(docker ps -a --format "{{.Names}}" --filter "name=websoft9")
sudo docker compose -p websoft9 -f $composefile down
# delete some dead containers that docker compose cannot deleted
if [ ! -z "$container_names" ]; then
echo "Deleting containers:"
echo $container_names
docker rm -f $container_names 2>/dev/null
else
echo "No containers to delete."
fi
sudo docker compose -f $composefile pull
sudo docker compose -p websoft9 -f $composefile up -d --build
if [ $? -ne 0 ]; then
echo "Failed to start docker services."
exit 1
fi
}
install_systemd() {
echo -e "\n\n-------- Systemd --------"
echo_prefix_systemd=$'\n[Systemd] - '
echo "$echo_prefix_systemd Install Systemd service"
if [ ! -d "$systemd_path" ]; then
sudo mkdir -p "$systemd_path"
fi
sudo cp -r $install_path/systemd/script/* "$systemd_path"
sudo cp -f "$install_path/systemd/websoft9.service" /lib/systemd/system/
if [ $? -ne 0 ]; then
echo "Failed to copy Systemd service file."
exit 1
fi
sudo systemctl daemon-reload
if [ $? -ne 0 ]; then
echo "Failed to reload Systemd daemon."
exit 1
fi
sudo systemctl enable websoft9.service
if [ $? -ne 0 ]; then
echo "Failed to enable Systemd service."
exit 1
fi
sudo systemctl start websoft9
if [ $? -ne 0 ]; then
echo "Failed to start Systemd service."
exit 1
fi
}
#--------------- main-----------------------------------------
check_ports $http_port $https_port $port
install_tools
download_source
bash $install_path/install/install_docker.sh
if [ $? -ne 0 ]; then
echo "install_docker failed with error $?. Exiting."
exit 1
fi
install_backends
install_systemd
bash $install_path/install/install_cockpit.sh
if [ $? -ne 0 ]; then
echo "install_cockpit failed with error $?. Exiting."
exit 1
fi
bash $install_path/install/install_plugins.sh
if [ $? -ne 0 ]; then
echo "install_plugins failed with error $?. Exiting."
exit 1
fi
echo "Restart Docker for Firewalld..."
sudo systemctl restart docker
endtime=$(date +%s)
runtime=$((endtime-starttime))
echo "Script execution time: $runtime seconds"
echo -e "\n-- Install success! ------"
echo "Access Websoft9 console by: http://Internet IP:$(grep ListenStream /lib/systemd/system/cockpit.socket | cut -d= -f2) and using Linux user for login"

View file

@ -1,391 +0,0 @@
#!/bin/bash
# Define PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# Export PATH
export PATH
## This script is used for install or upgrade Cockpit on Linux
## Cockpit build at redhat family: https://copr.fedorainfracloud.org/coprs/g/cockpit/cockpit-preview/monitor/
## Cockpit reposoitory list: https://pkgs.org/download/cockpit
## PackageKit: https://www.freedesktop.org/software/PackageKit/
## Not use pkcon install/update cockpit, the reason is: https://cockpit-project.org/faq.html#error-message-about-being-offline
## pkcon can read repositories at you system directly, it don't provide exra repository
## [apt show cockpit] or [apt install cockpit] show all additional packages
## Ubuntu have backports at file /etc/apt/sources.list by default
## Cockpit application: https://cockpit-project.org/applications
# Command-line options
# ==========================================================
#
# --port <9000>
# Use the --port option to set Websoft9 cosole port. default is 9000, for example:
#
# $ sudo sh install_cockpit.sh --port 9001
############################################################
# Below vars export from install.sh
# $port
# $install_path
############################################################
echo -e "\n\n-------- Cockpit --------"
while [[ $# -gt 0 ]]; do
case $1 in
--port)
port="$2"
shift 2
;;
*)
shift
;;
esac
done
# Port priority: --port > ListenStream= > 9000
cockpit_exist() {
systemctl list-unit-files | grep -q "cockpit.service"
return $?
}
if cockpit_exist; then
cockpit_now_port=$(grep -oP "(?<=^ListenStream=).*" "/lib/systemd/system/cockpit.socket")
if [ -z "${cockpit_now_port// }" ]; then
echo "cockpit port is null,set it to 9000"
cockpit_now_port=9000
else
echo "$cockpit_now_port at cockpit.socket"
fi
else
cockpit_now_port=9000
fi
if [ -n "$port" ]; then
cockpit_port=$port
else
cockpit_port=$cockpit_now_port
fi
if [ -n "$install_path" ]; then
echo "Have found install files"
else
install_path="/data/websoft9/source"
fi
echo -e "\nYour installation parameters are as follows: "
echo "cockpit_port:$cockpit_port"
echo "install_path:$install_path"
related_containers=("websoft9-apphub")
echo_prefix_cockpit=$'\n[Cockpit] - '
# package cockpit depends_on [cockpit-bridge,cockpit-ws,cockpit-system], but update cockpit the depends don't update
cockpit_packages="cockpit cockpit-ws cockpit-bridge cockpit-system cockpit-pcp cockpit-networkmanager cockpit-session-recording cockpit-sosreport"
menu_overrides_github_page_url="https://websoft9.github.io/websoft9/cockpit/menu_override"
cockpit_config_github_page_url="https://websoft9.github.io/websoft9/cockpit/cockpit.conf"
cockpit_menu_overrides=()
# export OS release environments
if [ -f /etc/os-release ]; then
. /etc/os-release
else
echo "Can't judge your Linux distribution"
exit 1
fi
# This solution from: https://help.ubuntu.com/community/PinningHowto
pin_config="
Package: cockpit*
Pin: release a=$VERSION_CODENAME-backports
Pin-Priority: 1000
"
check_ports() {
local ports=("$@")
for port in "${ports[@]}"; do
if netstat -tuln | grep ":$port " >/dev/null; then
echo "Port $port is in use, install failed"
exit
fi
done
echo "All ports are available"
}
Print_Version(){
sudo /usr/libexec/cockpit-ws --version 2>/dev/null || sudo /usr/lib/cockpit-ws --version 2>/dev/null || /usr/lib/cockpit/cockpit-ws --version 2>/dev/null
}
Install_PackageKit(){
echo "$echo_prefix_cockpit Install PackageKit(pkcon) and Cockpit repository"
if command -v pkcon &> /dev/null; then
echo "pkcon is at your system ..."
elif command -v yum &> /dev/null; then
if [ "$(cat /etc/redhat-release)" = "Redhat7" ]; then
sudo subscription-manager repos --enable rhel-7-server-extras-rpms
fi
sudo yum install PackageKit -y
elif command -v dnf &> /dev/null; then
sudo dnf install PackageKit -y
elif command -v apt &> /dev/null; then
sudo apt update
sudo apt install packagekit -y
else
echo "PackageKit not found, Cockpit cannot be installed"
exit 1
fi
}
Set_Repository() {
echo "$echo_prefix_cockpit Set Cockpit deb repository"
if command -v apt &> /dev/null; then
if [ "$NAME" = "Debian" ]; then
echo "deb http://deb.debian.org/debian $VERSION_CODENAME-backports main" > /etc/apt/sources.list.d/backports.list
fi
echo "Set the cockpit repository priority on Ubuntu/Debian..."
sudo bash -c "echo '$pin_config' > /etc/apt/preferences.d/cockpit_backports"
fi
echo "Complete set Cockpit repository"
}
Restart_Cockpit(){
echo "$echo_prefix_cockpit Restart Cockpit"
sudo systemctl daemon-reload
sudo systemctl restart cockpit.socket 2> /dev/null
sudo systemctl restart cockpit || exit 1
}
Add_Firewalld(){
echo "Add cockpit service to Firewalld..."
# cockpit.xml is not always the same path at Linux distributions
sudo sed -i "s/port=\"[0-9]*\"/port=\"$cockpit_port\"/g" /etc/firewalld/services/cockpit.xml
sudo sed -i "s/port=\"[0-9]*\"/port=\"$cockpit_port\"/g" /usr/lib/firewalld/services/cockpit.xml
sudo firewall-cmd --zone=public --add-service=cockpit --permanent
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --reload
}
Set_Firewalld(){
echo "$echo_prefix_cockpit Set firewalld for cockpit access"
if command -v firewall-cmd &> /dev/null; then
echo "Set firewall for Cockpit..."
if ! systemctl is-active --quiet firewalld; then
sudo systemctl start firewalld
Add_Firewalld
sudo systemctl stop firewalld
else
Add_Firewalld
fi
fi
}
Set_Selinux(){
echo "$echo_prefix_cockpit Set Selinux for cockpit access"
if [ -f /etc/selinux/config ]; then
echo "Set Selinux for Cockpit..."
sudo setenforce 0 1>/dev/null 2>&1
sudo sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config 1>/dev/null 2>&1
fi
}
Set_Cockpit(){
echo "$echo_prefix_cockpit Set Cockpit for Websoft9"
echo "Cockpit allowed root user ..."
echo "" > /etc/cockpit/disallowed-users
# fix bug: https://github.com/Websoft9/websoft9/issues/332
sed 's/selector(:is():where())/selector(:is(*):where(*))/' -i /usr/share/cockpit/static/login.js
echo "Set Cockpit config file..."
if [ -f "$install_path/cockpit/cockpit.conf" ]; then
cp -f "$install_path/cockpit/cockpit.conf" /etc/cockpit/cockpit.conf
else
echo "Download config from URL $cockpit_config_github_page_url"
curl -sSL $cockpit_config_github_page_url | sudo tee /etc/cockpit/cockpit.conf > /dev/null
fi
echo "Change cockpit default port to $cockpit_port ..."
sudo sed -i "s/ListenStream=[0-9]*/ListenStream=${cockpit_port}/" /lib/systemd/system/cockpit.socket
if docker ps --format '{{.Names}}' | grep -wq "${related_containers[0]}"; then
echo "Try to change cockpit port at ${related_containers[0]} container..."
sudo docker exec -i ${related_containers[0]} apphub setconfig --section cockpit --key port --value $cockpit_port || true
else
echo "Not found ${related_containers[0]} container"
fi
# fwupd-refresh.service may push error for Cockpit menu, so disable it
if sudo systemctl is-active --quiet fwupd-refresh.service; then
echo "fwupd-refresh.service is already running. Stopping and disabling it..."
sudo systemctl stop fwupd-refresh.service
sudo systemctl disable fwupd-refresh.service
echo "fwupd-refresh.service stopped and disabled."
else
echo "fwupd-refresh.service is not running."
fi
}
get_github_files() {
python3 - <<EOF
import requests
import json
url = "https://api.github.com/repos/Websoft9/websoft9/contents/cockpit/menu_override?ref=main"
headers = {
"Accept": "application/vnd.github.v3+json"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
files = json.loads(response.text)
for file in files:
print(file['name'])
else:
print(f"Error: {response.status_code}")
EOF
}
Download_Menu_Override(){
cockpit_menu_overrides=($(get_github_files))
for file in "${cockpit_menu_overrides[@]}"
do
echo "$menu_overrides_github_page_url/$file"
curl -sSL "$menu_overrides_github_page_url/$file" | sudo tee /etc/cockpit/"$file" > /dev/null
if [ $? -ne 0 ]; then
echo "Failed to download files"
exit 1
fi
done
}
Edit_Menu(){
echo "$echo_prefix_cockpit Start to edit Cockpit origin Menu"
if [ -f "$install_path/cockpit/cockpit.conf" ]; then
cp -f "$install_path/cockpit/cockpit.conf" /etc/cockpit/cockpit.conf
else
echo "Download config file from URL..."
curl -sSL $cockpit_config_github_page_url | sudo tee /etc/cockpit/cockpit.conf > /dev/null
if [ $? -ne 0 ]; then
echo "Failed to download cockpit.conf"
exit 1
fi
fi
if test -d "$install_path/cockpit/menu_override"; then
cp -r $install_path/cockpit/menu_override/* /etc/cockpit
else
echo "Download override files from URL..."
Download_Menu_Override
fi
}
Install_Cockpit(){
if cockpit_exist; then
echo "$echo_prefix_cockpit Prepare to upgrade Cockpit"
echo "You installed version: "
Print_Version
else
echo "$echo_prefix_cockpit Prepare to install Cockpit"
check_ports $port
fi
dnf --version >/dev/null 2>&1
dnf_status=$?
yum --version >/dev/null 2>&1
yum_status=$?
apt --version >/dev/null 2>&1
apt_status=$?
if [ $dnf_status -eq 0 ]; then
for pkg in $cockpit_packages
do
echo "Install or upgrade $pkg"
sudo dnf upgrade -y "$pkg" > /dev/null || echo "$pkg failed to upgrade"
sudo dnf install -y "$pkg" > /dev/null || echo "$pkg failed to install"
done
elif [ $yum_status -eq 0 ]; then
for pkg in $cockpit_packages
do
echo "Install or update $pkg"
sudo yum update -y "$pkg" > /dev/null || echo "$pkg failed to update"
sudo yum install -y "$pkg" > /dev/null || echo "$pkg failed to install"
done
elif [ $apt_status -eq 0 ]; then
export DEBIAN_FRONTEND=noninteractive
sudo dpkg --configure -a
apt-get update -y >/dev/null
apt-get --fix-broken install
for pkg in $cockpit_packages
do
echo "Installing $pkg"
sudo apt-get install -u -y "$pkg" > /dev/null || echo "$pkg failed to install"
done
else
echo "Neither apt,dnf nor yum found. Please install one of them and try again."
fi
Set_Firewalld
Set_Selinux
Set_Cockpit
Edit_Menu
Restart_Cockpit
}
Test_Cockpit(){
echo "$echo_prefix_cockpit Test Cockpit console accessibility"
test_cmd="curl localhost:$cockpit_port"
start_time=$(date +%s)
timeout=30
while true; do
if $test_cmd >/dev/null 2>&1; then
echo "Cockpit running OK..."
break
else
current_time=$(date +%s)
elapsed_time=$(($current_time - $start_time))
if [ $elapsed_time -ge $timeout ]; then
echo "Cockpit is not running... Timeout after waiting $timeout seconds."
exit 1
fi
sleep 1
fi
done
Print_Version
}
#### -------------- main() start here ------------------- ####
Set_Repository
Install_Cockpit
Test_Cockpit
# release package memory
if systemctl cat packagekit > /dev/null 2>&1; then
sudo systemctl restart packagekit
else
echo "no packagekit"
fi

View file

@ -1,165 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# Install and Upgade Docker for mosts of Linux
# This script is intended from https://get.docker.com and add below:
#
# - install or update Docker
# - support Redhat, CentOS-Stream, OracleLinux, AmazonLinux
#
# 1. download the script
#
# $ curl -fsSL https://websoft9.github.io/websoft9/install/install_docker.sh -o install_docker.sh
#
# 2. verify the script's content
#
# $ cat install_docker.sh
#
# 3. run the script with --dry-run to verify the steps it executes
#
# $ sh install_docker.sh --dry-run
#
# 4. run the script either as root, or using sudo to perform the installation.
#
# $ sudo sh install_docker.sh
# it must export, otherwise Rocky Linux cannot used at yum command
export docker_packages="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
echo_prefix_docker=$'\n[Docker] - '
docker_exist() {
# 检查 `docker` 命令是否存在
if ! command -v docker &> /dev/null; then
echo "docker command not exist"
return 1
fi
# 检查 Docker 服务是否正在运行
systemctl is-active docker.service &> /dev/null
if [ $? -ne 0 ]; then
echo "Docker service is not running, trying to start it..."
systemctl start docker.service
if [ $? -ne 0 ]; then
echo "Failed to start Docker service."
return 1
fi
fi
return 0
}
Install_Docker(){
local mirror=$1
local timeout=$2
local repo_url=$3
echo "$echo_prefix_docker Installing Docker from ${mirror} with timeout ${timeout} seconds for your system"
if [ "$mirror" = "Official" ]; then
mirror=""
fi
# For redhat family
if [[ -f /etc/redhat-release ]] || command -v amazon-linux-extras >/dev/null 2>&1; then
# For CentOS, Fedora, or RHEL(only s390x)
if [[ $(cat /etc/redhat-release) =~ "Red Hat" ]] && [[ $(uname -m) == "s390x" ]] || [[ $(cat /etc/redhat-release) =~ "CentOS" ]] || [[ $(cat /etc/redhat-release) =~ "Fedora" ]]; then
curl -fsSL https://get.docker.com -o get-docker.sh
timeout $timeout sh get-docker.sh --channel stable --mirror $mirror
else
# For other distributions(Redhat and Rocky linux ...)
dnf --version >/dev/null 2>&1
dnf_status=$?
yum --version >/dev/null 2>&1
yum_status=$?
if [ $dnf_status -eq 0 ]; then
sudo dnf install dnf-utils -y > /dev/null
sudo dnf config-manager --add-repo $repo_url
timeout $timeout sudo dnf install $docker_packages -y
elif [ $yum_status -eq 0 ]; then
sudo yum install yum-utils -y > /dev/null
sudo yum-config-manager --add-repo $repo_url
if command -v amazon-linux-extras >/dev/null 2>&1; then
wget -O /etc/yum.repos.d/CentOS7-Base.repo https://websoft9.github.io/stackhub/apps/roles/role_common/files/CentOS7-Base.repo
sudo sed -i "s/\$releasever/7/g" /etc/yum.repos.d/docker-ce.repo
timeout $timeout sudo yum install $docker_packages --disablerepo='amzn2-extras,amzn2-core' -y
else
timeout $timeout sudo yum install $docker_packages -y
fi
else
echo "None of the required package managers are installed."
fi
fi
fi
# For Ubuntu, Debian, or Raspbian
if type apt >/dev/null 2>&1; then
# Wait for apt to be unlocked
curl -fsSL https://get.docker.com -o get-docker.sh
timeout $timeout sh get-docker.sh --channel stable --mirror $mirror
fi
}
Upgrade_Docker(){
if docker_exist; then
echo "$echo_prefix_docker Upgrading Docker for your system..."
dnf --version >/dev/null 2>&1
dnf_status=$?
yum --version >/dev/null 2>&1
yum_status=$?
apt --version >/dev/null 2>&1
apt_status=$?
if [ $dnf_status -eq 0 ]; then
sudo dnf update -y $docker_packages
elif [ $yum_status -eq 0 ]; then
sudo yum update -y $docker_packages
elif [ $apt_status -eq 0 ]; then
sudo apt update -y
sudo apt -y install --only-upgrade $docker_packages
else
echo "Docker installed, but cannot upgrade"
fi
else
local mirrors=("Official" "Official" "AzureChinaCloud" "Aliyun")
local urls=("https://download.docker.com/linux/centos/docker-ce.repo" "https://download.docker.com/linux/centos/docker-ce.repo" "https://mirror.azure.cn/docker-ce/linux/centos/docker-ce.repo" "https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo")
local timeout=180
local max_retries=4
local retry_count=0
while ((retry_count < max_retries)); do
Install_Docker ${mirrors[$retry_count]} $timeout ${urls[$retry_count]}
if ! docker_exist; then
echo "Installation timeout or failed, retrying with ${mirrors[$retry_count]} mirror..."
((retry_count++))
sleep 3
else
echo "Docker installed successfully."
exit 0
fi
done
echo "Docker Installation failed after $max_retries retries."
exit 1
fi
}
Start_Docker(){
# should have Docker server and Docker cli
if docker_exist; then
echo "$echo_prefix_docker Starting Docker"
sudo systemctl enable docker
sudo systemctl restart docker
else
echo "Docker not installed or start failed, exit..."
exit 1
fi
}
echo -e "\n\n-------- Docker --------"
Upgrade_Docker
Start_Docker

View file

@ -1,82 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# Command-line options
# ==========================================================
#
# --channel <release|dev>
# Use the --channel option to install a release(production) or dev distribution. default is release, for example:
#
# $ sudo sh install.sh --channel release
#
# ==============================================================================
# get input and define vars
while [[ $# -gt 0 ]]; do
case $1 in
--channel)
channel="$2"
shift 2
;;
*)
shift
;;
esac
done
# channel,source_github_pages,install_path from install.sh priority
if [ -z "$channel" ]; then
channel="release"
fi
if [ -z "$source_github_pages" ]; then
source_github_pages="https://websoft9.github.io/websoft9"
fi
if [ -z "$install_path" ]; then
install_path="/data/websoft9/source"
fi
echo -e "\n\n-------- Plugins --------"
echo "Your installation parameters are as follows: "
echo "--channel: $channel"
echo "--install_path: $install_path"
artifact_url="https://w9artifact.blob.core.windows.net/$channel/websoft9/plugin"
echo_prefix_plugins=$'\n[Plugins] - '
versions_local_file="$install_path/version.json"
versions_url="$source_github_pages/version.json"
file_suffix=".zip"
plugin_path="/usr/share/cockpit"
echo "$echo_prefix_plugins Starting download plugin and update it"
if [ -f "$versions_local_file" ]; then
echo "File $versions_local_file exists."
else
echo "File $versions_local_file does not exist. Downloading from $versions_url"
wget -q $versions_url -O $versions_local_file
fi
plugins=$(jq -c '.plugins' $versions_local_file)
if [ -z "$plugins" ]; then
echo "No plugins found in $versions_local_file"
exit 1
fi
for key in $(jq -r '.plugins | keys[]' $versions_local_file); do
version=$(jq -r ".plugins.${key}" $versions_local_file)
file_url=$artifact_url/$key/$key-$version$file_suffix
file_name=$key-$version$file_suffix
echo "Download from $file_url"
wget -q $file_url -O $file_name
unzip -oq $file_name -d $plugin_path
rm -rf $file_name
done
find /usr/share/cockpit -type f -name "*.py3" -exec chmod +x {} \;
echo "Plugins install successfully..."

View file

@ -1,27 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# This script is on development, can not use now
# to do
Remove_Podman(){
echo "$echo_prefix_docker Try to remove Podman"
podman pod stop --all
# Remove Podman and its dependencies
if [ -x "$(command -v dnf)" ]; then
sudo dnf remove podman -y
elif [ -x "$(command -v apt)" ]; then
sudo apt remove podman -y
elif [ -x "$(command -v zypper)" ]; then
sudo zypper remove podman -y
elif [ -x "$(command -v pacman)" ]; then
sudo pacman -Rs podman --noconfirm
else
echo "Unable to find a suitable package manager to remove Podman."
exit 1
fi
echo "Podman has been stopped and removed."
}

View file

@ -1,72 +0,0 @@
#!/bin/bash
# Define PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# Export PATH
export PATH
# Command-line options
# ==============================================================================
#
# --cockpit
# Use the --cockpit option to remove cockpit:
#
# $ sudo sh install.sh --cockpit
#
# --files
# Use the --files option remove files have installed:
#
# $ sudo sh install.sh --files
#
#
# ==============================================================================
install_path="/data/websoft9/source"
systemd_path="/opt/websoft9/systemd"
cockpit_plugin_path="/usr/share/cockpit"
cockpit_packages="cockpit cockpit-ws cockpit-bridge cockpit-system cockpit-pcp cockpit-storaged cockpit-networkmanager cockpit-session-recording cockpit-doc cockpit-packagekit cockpit-sosreport"
echo -e "\n---Remove Websoft9 backend service containers---"
sudo docker compose -p websoft9 down -v
echo -e "\n---Remove Websoft9 systemd service---"
sudo systemctl disable websoft9
sudo systemctl stop websoft9
rm -rf /lib/systemd/system/websoft9.service
remove_cockpit() {
echo -e "\n---Remove Cockpit---"
sudo systemctl stop cockpit.socket cockpit
for package in $cockpit_packages; do
sudo pkcon remove $package -y || true
done
sudo rm -rf /etc/cockpit/*
}
remove_files() {
echo -e "\n---Remove files---"
sudo rm -rf $install_path/* $systemd_path/* $cockpit_plugin_path/*
}
for arg in "$@"
do
case $arg in
--cockpit)
remove_cockpit
shift
;;
--files)
remove_files
shift
;;
*)
echo "Unknown argument: $arg"
exit 1
;;
esac
done
echo -e "\nCongratulations, Websoft9 uninstall is complete!"

View file

@ -1,3 +0,0 @@
# Scripts
Some useful script for Websoft9 maintenance

View file

@ -1,16 +0,0 @@
#!/bin/bash
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
app_port=$(cat /data/apps/$1/.env |grep APP_HTTP_PORT |cut -d= -f2 |sed -n 1p)
while true
do
app_port_lines=$(cat /tmp/port.txt |grep "$app_port" |wc -l)
if [ "$app_port_lines" -gt 0 ];then
app_port=`expr $app_port + 1`
else
echo $app_port >> /tmp/port.txt
sed -i "s/APP_HTTP_PORT=.*/APP_HTTP_PORT=$app_port/g" /data/apps/$1/.env
break
fi
done

View file

@ -1,511 +0,0 @@
#!/bin/bash
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
set -e
# Please modify this version and time after update
version(){
sudo echo "version: 1.6"
sudo echo "updated date: 2021-05-26"
}
# Tool list, apt or yum installation is only supported
tool_list=(
git
pwgen
jq
wget
curl
figlet
boxes
)
help_str="
Usage:
-h, --help Show this help message
-r, --repo_name The name of the warehouse
-p, --package Making local packs,Only when you need to pack
-v, --version Show version info
example: bash install.sh -r template -p
"
make_package=false
# Get option parameters
getopt_cmd=$(getopt -o r:phv --long repo_name:,package,help,version -n "Parameter error" -- "$@")
eval set -- "$getopt_cmd"
while [ -n "$1" ]
do
case "$1" in
-r|--repo_name)
repo_name=$2
shift ;;
-h|--help)
sudo echo -e "$help_str"
exit ;;
-p|--package)
make_package=true
shift ;;
-v|--version)
version
shift ;;
--)
break
shift ;;
esac
shift
done
[ ! -n "$repo_name" ] && exit 1
install_tools(){
if command -v apt > /dev/null;then
sudo apt update 1>/dev/null 2>&1
sudo apt install ${tool_list[*]} -y 1>/dev/null 2>&1
elif command -v yum > /dev/null;then
sudo yum clean all 1>/dev/null 2>&1
sudo yum makecache 1>/dev/null 2>&1
sudo yum install ${tool_list[*]} -y 1>/dev/null 2>&1
fi
}
download_docker_source(){
docker_download_url="https://download.docker.com/linux/static/stable/x86_64/docker-20.10.6.tgz"
cd /tmp/
sudo rm -rf docker.tgz
sudo wget $docker_download_url -O docker.tgz 1>/dev/null 2>&1
sudo echo -e "docker downloaded successfully"
sudo cat > /tmp/docker.service <<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP \$MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
}
install_docker_script(){
if command -v docker > /dev/null;then
sudo echo -e `docker -v`
sudo echo -e "Docker installed successfully"
else
sudo curl -fsSL https://get.docker.com -o get-docker.sh &>/dev/null && sh get-docker.sh &>/dev/null
sudo rm -rf get-docker.sh
sudo systemctl start docker
sudo systemctl enable docker &>/dev/null
sudo echo -e `docker -v`
sudo echo -e "Docker installed successfully"
fi
}
uninstall_docker(){
sudo rm -f /etc/systemd/system/docker.service
sudo rm -rf /usr/bin/docker*
sudo systemctl daemon-reload
sudo echo -e "Docker uninstalled successfully"
}
download_docker_compose(){
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.0/docker-compose-$(uname -s)-$(uname -m)" -o /tmp/docker-compose 1>/dev/null 2>&1
sudo chmod +x /tmp/docker-compose
sudo echo -e "docker-compose downloaded successfully"
}
install_docker_compose(){
curl -L "https://github.com/docker/compose/releases/download/1.29.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 1>/dev/null 2>&1
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose &>/dev/mull || true
sudo echo `docker-compose -v`
sudo echo -e "docker-compose installed successfully"
}
save_images(){
sudo rm -rf /tmp/docker-$repo_name
sudo git clone https://github.com/Websoft9/docker-$repo_name.git /tmp/docker-$repo_name || sudo git clone https://github.com.cnpmjs.org/Websoft9/docker-$repo_name.git /tmp/docker-$repo_name
sudo docker rmi `docker images -aq` -f &>/dev/null || true
cd /tmp/docker-$repo_name
# Pull images and save images
sudo systemctl start docker
docker-compose pull
sudo echo -e "In image packaging, there is a long wait..."
sudo docker save $(docker images | grep -v REPOSITORY | awk 'BEGIN{OFS=":";ORS=" "}{print $1,$2}') -o /tmp/$repo_name.tar
sudo echo -e "The image was successfully saved as a tar package"
}
installation(){
sudo rm -rf $install_dir
sudo mkdir -p $install_dir /credentials 1>/dev/null 2>&1 && cd $install_dir
sudo git clone https://github.com/Websoft9/docker-$repo_name.git $install_dir || sudo git clone https://github.com.cnpmjs.org/Websoft9/docker-$repo_name.git $install_dir
# Rename compose and env file name
cd $install_dir
# Stop the container and remove the Volumes for sec_installation
cd $install_dir
rm -rf volumes
sudo docker-compose down -v 1>/dev/null 2>&1
# Avoiding db port conflicts
sudo echo -e "The database port is changing"
db_port_lines=$(cat $install_dir/.env |grep DB_.*PORT |wc -l)
db_port=$(cat $install_dir/.env |grep DB_.*PORT |cut -d= -f2 |sed -n 1p)
while true
do
if [ "$db_port_lines" -gt 0 ];then
os_db_port_lines=$(ss -ntulp |grep -w "$db_port" |wc -l)
if [ "$os_db_port_lines" -gt 0 ];then
db_port=`expr $db_port + 1`
sed -ri "s/(DB.*_PORT=).*/\1$db_port/" $install_dir/.env
else
break
fi
else
break
fi
done
# DB Random password
sudo echo -e "---$repo_name Installation Wizard----" |boxes |tee -a /credentials/password.txt
new_password=$(pwgen -ncCs 15 1)
db_password_lines=`cat $install_dir/.env |grep DB.*PASSWORD |wc -l`
db_user_lines=`cat $install_dir/.env |grep DB_.*_USER |wc -l`
if [ $db_password_lines -gt 0 ];then
if [ $db_user_lines -gt 0 ];then
db_username=$(cat $install_dir/.env |grep DB_.*_USER |cut -d= -f2 |sed -n 1p )
sudo echo "db username: $db_username" |tee -a /credentials/password.txt
else
sudo echo "db username: root" |tee -a /credentials/password.txt
fi
sudo sed -ri "s/(DB_.*_PASSWORD=).*/\1$new_password/" $install_dir/.env &>/dev/null || true
sudo echo "db password: $new_password" |tee -a /credentials/password.txt
else
sudo echo "No database password" |tee -a /credentials/password.txt
fi
if [ "$db_port_lines" -gt 0 ];then
sudo echo "db port: $db_port" |tee -a /credentials/password.txt
fi
sudo echo -e "************************************\n"|tee -a /credentials/password.txt
# APP Random password
app_password_lines=$(cat $install_dir/.env |grep -w "APP_PASSWORD_INIT" |wc -l)
app_user_lines=$(cat $install_dir/.env |grep -w "APP_USER" |wc -l)
app_port_lines=$(cat $install_dir/.env |grep -w "APP_PORT" |wc -l)
if [ "$app_user_lines" -gt 0 ];then
app_username=$(cat $install_dir/.env |grep -w "APP_USER" |cut -d= -f2 |sed -n 1p)
sudo echo "$repo_name login username: $app_username" |tee -a /credentials/password.txt
else
sudo echo "$repo_name login username: default username, please see the $install_dir/.env" |tee -a /credentials/password.txt
fi
if [ "$app_password_lines" -gt 0 ];then
sudo sed -ri "s/(APP_PASSWORD=).*/\1$new_password/" $install_dir/.env &>/dev/null || true
sudo echo "$repo_name login password: $new_password" |tee -a /credentials/password.txt
else
sudo echo "$repo_name login password: default password, please see the $install_dir/.env" |tee -a /credentials/password.txt
fi
if [ "$app_port_lines" -gt 0 ];then
app_port=$(cat $install_dir/.env |grep -w "APP_PORT" |cut -d= -f2 |sed -n 1p)
sudo echo "$repo_name login port: $app_port" |tee -a /credentials/password.txt
fi
sudo echo -e "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |tee -a /credentials/password.txt
# Modify public network IP
public_ip=`wget -O - https://download.websoft9.com/ansible/get_ip.sh 2>/dev/null |bash`
case $repo_name in
"erpnext")
sudo sed -i "s/APP_SITE_NAME.*/APP_SITE_NAME=$public_ip/g" $install_dir/.env
sudo sed -i "s/APP_SITES=.*/APP_SITES=\`$public_ip\`/g" $install_dir/.env
;;
"graylog")
sudo sed -i "s#APP_HTTP_EXTERNAL_URI=.*#APP_HTTP_EXTERNAL_URI=http://$public_ip:9001/#g" $install_dir/.env
;;
"rocketchat")
sudo sed -i "s#APP_ROOT_URL=.*#APP_ROOT_URL=http://$public_ip:9001/#g" $install_dir/.env
;;
*)
;;
esac
# Change compose cli environment
export DOCKER_CLIENT_TIMEOUT=500
export COMPOSE_HTTP_TIMEOUT=500
sudo systemctl start docker
sudo docker-compose up -d
sleep 5
sudo clear
sudo echo -e "\n $repo_name installation complete\n" |boxes -d whirly
sudo echo -e "\n Please go to $repo_name to view the README file"
sudo docker ps -a
}
add_install_script(){
sudo rm -rf /tmp/install.sh /tmp/README /tmp/setup.sh
# Mirror package installation script
cat > /tmp/install.sh <<-EOF
# Install docker
sudo tar -xf docker.tgz
sudo systemctl stop docker &>/dev/mull || true
sudo mv docker.service /etc/systemd/system/docker.service
sudo mv docker/* /usr/bin/ 1>/dev/null 2>&1
sudo systemctl daemon-reload
sudo systemctl start docker
sudo systemctl enable docker &>/dev/null
sudo echo \$(docker -v)
sudo echo -e "Docker was installed successfully"
# Install docker-compose
sudo mv docker-compose /usr/local/bin/docker-compose 1>/dev/null 2>&1
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose &>/dev/mull || true
sudo echo \$(docker-compose -v)
sudo echo -e "docker-compose installed successfully"
# Pre_installation
sudo rm -rf $install_dir
sudo mkdir -p $install_dir /credentials 1>/dev/null 2>&1
sudo docker load -i $repo_name.tar
cur_dir=\$(pwd)
upper_dir=\$(dirname $install_dir)
sudo rm -rf \$upper_dir/$repo_name
cp=\$(which cp)
\$cp -rf \$cur_dir/docker-$repo_name \$upper_dir/$repo_name 1>/dev/null 2>&1
sudo mv README \$upper_dir/$repo_name/README 1>/dev/null 2>&1
# Stop the container and remove the Volumes for sec_installation
cd $install_dir
rm -rf volumes
sudo docker-compose down -v 1>/dev/null 2>&1
# Avoiding db port conflicts
db_port_lines=\$(cat $install_dir/.env |grep DB_.*PORT |wc -l)
db_port=\$(cat $install_dir/.env |grep DB_.*PORT |cut -d= -f2 |sed -n 1p)
while true
do
if [ "\$db_port_lines" -gt 0 ];then
os_db_port_lines=\$(ss -ntulp |grep \$db_port |wc -l)
if [ "\$os_db_port_lines" -gt 0 ];then
db_port=`expr \$db_port + 1`
sed -ri "s/(DB.*_PORT=).*/\1\$db_port/" $install_dir/.env
else
break
fi
else
break
fi
done
# DB Random password
sudo echo -e "---$repo_name Installation Wizard---\n" |tee -a /credentials/password.txt
new_password=\$(date | md5sum | awk '{print $1}' |cut -c 3-18)
db_password_lines=\$(cat $install_dir/.env |grep DB.*PASSWORD |wc -l)
db_user_lines=\$(cat $install_dir/.env |grep DB_.*_USER |wc -l)
if [ \$db_password_lines -gt 0 ];then
if [ \$db_user_lines -gt 0 ];then
db_username=\$(cat $install_dir/.env |grep DB_.*_USER |cut -d= -f2 |sed -n 1p)
sudo echo "db username: \$db_username" |tee -a /credentials/password.txt
else
sudo echo "db username: root" |tee -a /credentials/password.txt
fi
sudo sed -ri "s/(DB_.*_PASSWORD=).*/\1\$new_password/" $install_dir/.env &>/dev/null || true
sudo echo "db password: \$new_password" |tee -a /credentials/password.txt
else
sudo echo "No database password" |tee -a /credentials/password.txt
fi
if [ "\$db_port_lines" -gt 0 ];then
sudo echo "db port: \$db_port" |tee -a /credentials/password.txt
fi
sudo echo -e "************************************\n" |tee -a /credentials/password.txt
# APP Random password
app_user_lines=\$(cat $install_dir/.env |grep -w "APP_USER" |wc -l)
app_password_lines=\$(cat $install_dir/.env |grep -w "APP_PASSWORD_INIT" |wc -l)
app_port_lines=\$(cat $install_dir/.env |grep -w "APP_PORT" |wc -l)
if [ "\$app_user_lines" -gt 0 ];then
app_username=\$(cat $install_dir/.env |cut -d= -f2 |sed -n 1p)
sudo echo "$repo_name login username: \$app_username" |tee -a /credentials/password.txt
else
sudo echo "$repo_name login username: default username, please see the $install_dir/.env" |tee -a /credentials/password.txt
fi
if [ "\$app_password_lines" -gt 0 ];then
sudo sed -ri "s/(APP_PASSWORD=).*/\1\$new_password/" $install_dir/.env &>/dev/null || true
sudo echo "$repo_name login password: \$new_password" |tee -a /credentials/password.txt
else
sudo echo "$repo_name login password: default password, please see the $install_dir/.env" |tee -a /credentials/password.txt
fi
if [ "\$app_port_lines" -gt 0 ];then
app_port=\$(cat $install_dir/.env |grep -w "APP_PORT" |cut -d= -f2 |sed -n 1p)
sudo echo "$repo_name login port: \$app_port" |tee -a /credentials/password.txt
fi
sudo rm -rf \$cur_dir/{$repo_name.tar,get-docker.sh,docker.service,docker-compose,docker.tgz,docker,install.sh,docker-$repo_name}
sudo echo -e "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |tee -a /credentials/password.txt
# Modify public network IP
public_ip=\$(wget -O - https://download.websoft9.com/ansible/get_ip.sh 2>/dev/null | timeout 10 bash)
case $repo_name in
"erpnext")
sudo sed -i "s/APP_SITE_NAME.*/APP_SITE_NAME=\$public_ip/g" $install_dir/.env
sudo sed -i "s/APP_SITES=.*/APP_SITES=\`\$public_ip\`/g" $install_dir/.env
;;
"graylog")
sudo sed -i "s#APP_HTTP_EXTERNAL_URI=.*#APP_HTTP_EXTERNAL_URI=http://\$public_ip:9001/#g" $install_dir/.env
;;
"rocketchat")
sudo sed -i "s#APP_ROOT_URL=.*#APP_ROOT_URL=http://\$public_ip:9001/#g" $install_dir/.env
;;
*)
;;
esac
# Change compose cli environment
export DOCKER_CLIENT_TIMEOUT=500
export COMPOSE_HTTP_TIMEOUT=500
sudo systemctl start docker
sudo docker-compose up -d
sudo clear && sudo docker ps -a
sudo echo -e "\n $repo_name installation complete\n"
sudo echo -e "\n Please go to \$upper_dir/$repo_name to view the README file"
EOF
# README file
cat > /tmp/README <<-EOF
Document address:
http://support.websoft9.com/docs/$repo_name/zh/
Project address:
https://github.com/websoft9/docker-$repo_name
Password file location:
/credentials/password.txt
EOF
# Unpack the pre-installed script
cat > /tmp/setup.sh <<-EOF
#!/bin/bash
line=\`wc -l \$0|awk '{print \$1}'\`
line=\`expr \$line - 7\`
tail -n \$line \$0 |tar zx -C ~
cd ~
./install.sh
ret=\$?
exit \$ret
EOF
sudo chmod +x /tmp/install.sh
sudo chmod +x /tmp/setup.sh
}
get_install_information(){
install_dir=`curl -s https://raw.githubusercontent.com/Websoft9/docker-$repo_name/main/variables.json |jq -r .installpath` 1>/dev/null
compose_file_name=`curl -s https://raw.githubusercontent.com/Websoft9/docker-$repo_name/main/variables.json |jq -r .compose_file` 1>/dev/null
compose_env_url="https://raw.githubusercontent.com/Websoft9/docker-$repo_name/main/.env"
url_status=`curl -s -m 5 -IL $compose_env_url |grep 200 || true`
if [[ $url_status == "" ]];then
sudo echo "The env file does not exist"
exit 1
fi
if [[ $install_dir == "null" || $compose_file_name = "null" ]];then
sudo echo "variables.json has an undefined parameter"
exit 1
fi
sudo echo install path $install_dir
sudo echo compose filename $compose_file_name
}
make_package(){
sudo rm -rf /tmp/$repo_name.tgz install-$repo_name
cd /tmp && tar -zcf /tmp/$repo_name.tgz ./{install.sh,README,$repo_name.tar,docker-$repo_name,docker.tgz,docker.service,docker-compose}
sudo cat setup.sh $repo_name.tgz > ~/install-$repo_name
sudo chmod +x ~/install-$repo_name
cd ~ && sudo echo -e "Image packaging successfully" |boxes -d whirly
}
print_information(){
sudo figlet websoft9
# Check if the repo exists
repo_name_exists=$(curl -s --head https://github.com/Websoft9/docker-$repo_name | head -n 1 |grep -c '200')
[ "$repo_name_exists" -ne 1 ] && sudo echo -e "The repo does not exist !" && exit 1
# Print installation information
if [ -n "$repo_name" ] && [ "$make_package" == false ];then
sudo echo "docker-$repo_name to be installed..."
fi
if [ -n "$repo_name" ] && [ "$make_package" == true ];then
sudo echo "$repo_name will be packaged as an image..."
fi
}
install_tools
print_information
get_install_information
if [ $make_package = false ]; then
install_docker_script
install_docker_compose
installation
fi
if [ $make_package = true ]; then
install_docker_script
install_docker_compose
download_docker_source
download_docker_compose
save_images
add_install_script
make_package
fi

View file

@ -1,5 +0,0 @@
#!/bin/bash
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
sudo systemctl restart sshd
sudo passwd root

View file

@ -1,41 +0,0 @@
#!/bin/bash
url_list=(
api.ipify.org
bot.whatismyipaddress.com
icanhazip.com
ifconfig.co
ident.me
ifconfig.me
icanhazip.com
ipecho.net/plain
ipinfo.io/ip
ip.sb
whatismyip.akamai.com
inet-ip.info
)
curl_ip(){
curl --connect-timeout 1 -m 2 $1 2>/dev/null
return $?
}
debug(){
for x in ${url_list[*]}
do
curl_ip $x
done
}
print_ip(){
for n in ${url_list[*]}
do
public_ip=`curl_ip $n`
check_ip=`echo $public_ip | awk -F"." '{print NF}'`
if [ ! -z "$public_ip" -a $check_ip -eq "4" ]; then
echo $public_ip
exit 0
fi
done
}
#debug
print_ip

View file

@ -1,23 +0,0 @@
#!/bin/bash
#repo=$1
#path=$2
url_path=(
https://ghproxy.com/https://github.com
https://github.com)
git_clone(){
for r in ${1[*]}
do
filename=$(echo $r | cut -d '/' -f 2)
for x in ${url_path[*]}
do
if [ -e $filename ]; then
echo "$filename was cloned successfully"
break
else
timeout -k 1 3 git clone $x/$r.git
fi
done
done
}
git_clone

View file

@ -1,34 +0,0 @@
#!/bin/bash
# This script is created by Bing Chat
# 你可以使用以下修改后的 shell 脚本来自动尝试从 github.com 克隆仓库,如果失败了,再尝试使用不同的加速地址来克隆仓库。这个脚本会先尝试从 github.com 克隆仓库,如果失败了,再尝试使用我之前提到的加速地址来克隆仓库,直到成功为止。每个地址都会尝试克隆 3 次。如果克隆失败,脚本会输出友好的错误提示。这个脚本接受两个外部参数:$1 是用户名,$2 是仓库名。
# 获取外部参数
USERNAME="$1"
REPO="$2"
# 生成仓库 URL
REPO_URL="https://github.com/$USERNAME/$REPO.git"
# 加速地址列表
MIRRORS=(
"https://github.com"
"https://ghproxy.com/https://github.com"
)
for mirror in "${MIRRORS[@]}"; do
# 生成加速后的 URL
mirror_url="${REPO_URL/https:\/\/github.com/$mirror}"
# 尝试克隆仓库
for i in {1..3}; do
echo "Trying to clone from $mirror_url (attempt $i)"
if git clone --depth=1 "$mirror_url"; then
echo "Successfully cloned from $mirror_url"
exit 0
else
echo "Failed to clone from $mirror_url (attempt $i)"
fi
done
done
echo "Failed to clone the repository after multiple attempts. Please check your network connection and try again later."

View file

@ -1,472 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function error_exit {
echo "$1" 1>&2
exit 1
}
trap 'error_exit "Please push issue to: https://github.com/Websoft9/stackhub/issues"' ERR
urls="https://w9artifact.blob.core.windows.net/release/websoft9"
if [[ "$1" == "dev" ]]; then
echo "update by dev artifacts"
urls="https://w9artifact.blob.core.windows.net/dev/websoft9"
fi
function get_os_type() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
else
OS=$(uname -s)
fi
if [[ "$OS" == "CentOS Linux" ]]; then
echo "CentOS"
elif [[ "$OS" == "CentOS Stream" ]]; then
echo "CentOS Stream"
elif [[ "$OS" == "Rocky Linux" ]]; then
echo "Rocky Linux"
elif [[ "$OS" == "Oracle Linux Server" ]]; then
echo "OracleLinux"
elif [[ "$OS" == "Debian GNU/Linux" ]]; then
echo "Debian"
elif [[ "$OS" == "Ubuntu" ]]; then
echo "Ubuntu"
elif [[ "$OS" == "Fedora Linux" ]]; then
echo "Fedora"
elif [[ "$OS" =~ "Red Hat Enterprise Linux" ]]; then
echo "Redhat"
else
echo $OS
fi
}
function get_os_version() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VERSION=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
OS=$(lsb_release -si)
VERSION=$(lsb_release -sr)
else
OS=$(uname -s)
VERSION=$(uname -r)
fi
echo $VERSION
}
os_type=$(get_os_type)
os_version=$(get_os_version)
CheckEnvironment(){
echo "---------------------------------- Welcome to install websoft9's appstore, it will take 3-5 minutes -------------------------------------------------------"
echo "Check environment ..."
echo os_type: $os_type
echo os_version: $os_version
if [ $(id -u) != "0" ]; then
echo "Please change to root or 'sudo su' to up system privileges, and reinstall the script again ."
exit 1
fi
if [ $(getconf WORD_BIT) = '32' ] && [ $(getconf LONG_BIT) = '64' ] ; then
echo "64-bit operating system detected."
else
echo "This script only works on 64-bit operating systems."
exit 1
fi
if [ "$os_type" == 'CentOS' ] ;then
if [ "$os_version" != "7" ]; then
echo "This app only supported on CentOS 7"
exit 1
fi
fi
if [ "$os_type" == 'CentOS Stream' ] ;then
if [ "$os_version" != "8" ] || [ "$os_version" != "9" ]; then
echo "This app only supported on CentOS Stream 8,9"
exit 1
fi
fi
if [ "$os_type" == 'Rocky Linux' ] ;then
if [ "${os_version:0:1}" == "8" ] || [ "${os_version:0:1}" == "9" ]; then
echo ""
else
echo "This app only supported on Rocky Linux 8"
exit 1
fi
fi
if [ "$os_type" == 'Fedora' ];then
if [ "$os_version" != "37" ]; then
echo "This app only supported on Fedora 37"
exit 1
fi
fi
if [ "$os_type" == 'Redhat' ];then
if [ "${os_version:0:1}" != "7" ] && [ "${os_version:0:1}" != "8" ] && [ "${os_version:0:1}" != "9" ]; then
echo "This app only supported on Redhat 7,8"
exit 1
fi
fi
if [ "$os_type" == 'Ubuntu' ];then
if [ "$os_version" != "22.04" ] && [ "$os_version" != "20.04" ] && [ "$os_version" != "18.04" ]; then
echo "This app only supported on Ubuntu 22.04,20.04,18.04"
exit 1
fi
fi
if [ "$os_type" == 'Debian' ];then
if [ "$os_version" != "11" ];then
echo "This app only supported on Debian 11"
exit 1
fi
fi
# Check port used
if netstat -tuln | grep -qE ':(80|443|9000)\s'; then
echo "Port 80,443,9000 is already in use."
exit 1
else
echo "Port 80,443, 9000 are free."
fi
}
InstallTools(){
echo "Prepare to install Tools ..."
if [ "$os_type" == 'CentOS' ] || [ "$os_type" == 'Rocky Linux' ] || [ "$os_type" == 'CentOS Stream' ] || [ "$os_type" == 'Fedora' ] || [ "$os_type" == 'OracleLinux' ] || [ "$os_type" == 'Redhat' ];then
sudo yum update -y
sudo yum install git curl wget yum-utils jq bc unzip -y
fi
if [ "$os_type" == 'Ubuntu' ] || [ "$os_type" == 'Debian' ] ;then
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
echo "Waiting for other software managers to finish..."
sleep 5
done
sudo apt update -y 1>/dev/null 2>&1
if command -v git > /dev/null;then
echo "git installed ..."
else
sudo apt install git -y
fi
if command -v curl > /dev/null;then
echo "jcurlq installed ..."
else
sudo apt install curl -y
fi
if command -v wget > /dev/null;then
echo "wget installed ..."
else
sudo apt install wget -y
fi
if command -v jq > /dev/null;then
echo "jq installed ..."
else
sudo apt install jq -y
fi
if command -v bc > /dev/null;then
echo "bc installed ..."
else
sudo apt install bc -y
fi
if command -v unzip > /dev/null;then
echo "unzip installed ..."
else
sudo apt install unzip -y
fi
fi
}
InstallDocker(){
if command -v docker &> /dev/null
then
echo "Docker is installed, update..."
if command -v apt > /dev/null;then
sudo apt -y install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif command -v dnf > /dev/null;then
sudo dnf update -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif command -v yum > /dev/null;then
sudo yum update -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
fi
sudo systemctl start docker
sudo systemctl enable docker
if ! docker network inspect websoft9 > /dev/null 2>&1; then
sudo docker network create websoft9
fi
return
else
echo "Docker is not installed, start to install..."
fi
if [ "$os_type" == 'CentOS' ];then
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
fi
if [ "$os_type" == 'Ubuntu' ] || [ "$os_type" == 'Debian' ] ;then
apt-get update
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
echo "Waiting for other software managers to finish..."
sleep 5
done
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh
sleep 30
fi
if [ "$os_type" == 'OracleLinux' ] ;then
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
fi
if [ "$os_type" == 'Fedora' ] ;then
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo yum install device-mapper-persistent-data lvm2 docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-scan-plugin docker-ce-rootless-extras -y
fi
if [ "$os_type" == 'Redhat' ] ;then
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runc -y 1>/dev/null 2>&1
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
fi
if [ "$os_type" == 'CentOS Stream' ] || [ "$os_type" == 'Rocky Linux' ];then
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runc -y 1>/dev/null 2>&1
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
fi
sudo systemctl start docker
sudo systemctl enable docker
if ! docker network inspect websoft9 > /dev/null 2>&1; then
sudo docker network create websoft9
fi
}
InstallCockpit(){
echo "Prepare to install Cockpit ..."
if [ "${os_type}" == 'Debian' ]; then
VERSION_CODENAME=$(cat /etc/os-release |grep VERSION_CODENAME|cut -f2 -d"=")
sudo echo "deb http://deb.debian.org/debian ${VERSION_CODENAME}-backports main" >/etc/apt/sources.list.d/backports.list
sudo apt update
sudo apt install -t ${VERSION_CODENAME}-backports cockpit -y
sudo apt install cockpit-pcp cockpit-packagekit -y 1>/dev/null 2>&1
fi
if [ "${os_type}" == 'Ubuntu' ]; then
if grep -q "^#.*deb http://mirrors.tencentyun.com/ubuntu.*backports" /etc/apt/sources.list; then
echo "Add backports deb ..."
sudo sed -i 's/^#\(.*deb http:\/\/mirrors.tencentyun.com\/ubuntu.*backports.*\)/\1/' /etc/apt/sources.list
apt update
fi
VERSION_CODENAME=$(cat /etc/os-release |grep VERSION_CODENAME|cut -f2 -d"=")
sudo apt install -t ${VERSION_CODENAME}-backports cockpit -y
sudo apt install cockpit-pcp -y 1>/dev/null 2>&1
echo "Cockpit allow root user"
echo "" >/etc/cockpit/disallowed-users 1>/dev/null 2>&1
fi
if [ "${os_type}" == 'CentOS' ] || [ "$os_type" == 'OracleLinux' ]; then
sudo yum install cockpit -y
sudo yum install cockpit-pcp cockpit-packagekit -y 1>/dev/null 2>&1
sudo systemctl enable --now cockpit.socket
sudo firewall-cmd --permanent --zone=public --add-service=cockpit
sudo firewall-cmd --reload
fi
if [ "$os_type" == 'Fedora' ]; then
sudo dnf install cockpit -y
sudo dnf install cockpit-pcp cockpit-packagekit -y 1>/dev/null 2>&1
sudo systemctl enable --now cockpit.socket
sudo firewall-cmd --add-service=cockpit
sudo firewall-cmd --add-service=cockpit --permanent
fi
if [ "$os_type" == 'Redhat' ] ; then
sudo subscription-manager repos --enable rhel-7-server-extras-rpms 1>/dev/null 2>&1
sudo yum install cockpit -y
sudo yum install cockpit-pcp cockpit-packagekit -y 1>/dev/null 2>&1
sudo setenforce 0 1>/dev/null 2>&1
sudo sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config 1>/dev/null 2>&1
sudo systemctl enable --now cockpit.socket
sudo firewall-cmd --add-service=cockpit
sudo firewall-cmd --add-service=cockpit --permanent
fi
if [ "$os_type" == 'CentOS Stream' ]; then
sudo subscription-manager repos --enable rhel-7-server-extras-rpms 1>/dev/null 2>&1
sudo yum install cockpit -y
sudo yum install cockpit-pcp -y 1>/dev/null 2>&1
sudo systemctl enable --now cockpit.socket
sudo firewall-cmd --add-service=cockpit
sudo firewall-cmd --add-service=cockpit --permanent
sudo setenforce 0 1>/dev/null 2>&1
sudo sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config 1>/dev/null 2>&1
fi
file="/etc/cockpit/disallowed-users"
if [ -f "$file" ]; then
echo "" > "$file"
else
echo "$file is not exist"
fi
echo "Set cockpit port to 9000 ..."
sudo sed -i 's/ListenStream=9090/ListenStream=9000/' /lib/systemd/system/cockpit.socket
}
InstallPlugins(){
# download apps
mkdir -p /data/apps && cd /data/apps
wget $urls/websoft9-latest.zip
unzip websoft9-latest.zip
cp -r /data/apps/websoft9/docker /data/apps/w9services
rm -f websoft9-latest.zip
# install plugins
cd /usr/share/cockpit
appstore_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .APPSTORE | tr -d '"')
wget $urls/plugin/appstore/appstore-$appstore_version.zip
unzip appstore-$appstore_version.zip
myapps_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .MYAPPS| tr -d '"')
wget $urls/plugin/myapps/myapps-$myapps_version.zip
unzip myapps-$myapps_version.zip
portainer_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .PORTAINER | tr -d '"')
wget $urls/plugin/portainer/portainer-$portainer_version.zip
unzip portainer-$portainer_version.zip
nginx_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .NGINX | tr -d '"')
wget $urls/plugin/nginx/nginx-$nginx_version.zip
unzip nginx-$nginx_version.zip
settings_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .SETTINGS | tr -d '"')
wget $urls/plugin/settings/settings-$settings_version.zip
unzip settings-$settings_version.zip
# install navigator
navigator_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .NAVIGATOR | tr -d '"')
wget $urls/plugin/navigator/navigator-$navigator_version.zip
unzip navigator-$navigator_version.zip
rm -f *.zip
# install library
cd /data
library_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .LIBRARY | tr -d '"')
wget $urls/plugin/library/library-$library_version.zip
unzip library-$library_version.zip
rm -f library-$library_version.zip
# configure cockpit
cp /data/apps/websoft9/cockpit/cockpit.conf /etc/cockpit/cockpit.conf
#####ci-section#####
sudo systemctl daemon-reload
sudo systemctl enable --now cockpit.socket
sudo systemctl restart cockpit.socket
}
StartAppMng(){
echo "Start appmanage API ..."
cd /data/apps/w9services/w9redis && sudo docker compose up -d
cd /data/apps/w9services/w9appmanage && sudo docker compose up -d
public_ip=`bash /data/apps/websoft9/scripts/get_ip.sh`
echo $public_ip > /data/apps/w9services/w9appmanage/public_ip
appmanage_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' websoft9-appmanage)
}
StartPortainer(){
echo "Start Portainer ..."
cd /data/apps/w9services/w9portainer && sudo docker compose up -d
docker pull backplane/pwgen
new_password=$(docker run --name pwgen backplane/pwgen 15)!
docker rm -f pwgen
portainer_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' websoft9-portainer)
echo "Portainer init password:" $new_password >> /usr/password.txt
curl -X POST -H "Content-Type: application/json" -d '{"username":"admin", "Password":"'$new_password'"}' http://$portainer_ip:9000/api/users/admin/init
curl "http://$appmanage_ip:5000/AppUpdateUser?user_name=admin&password=$new_password"
}
InstallNginx(){
echo "Install nginxproxymanager ..."
cd /data/apps/w9services/w9nginxproxymanager && sudo docker compose up -d
sleep 30
echo "edit nginxproxymanager password..."
nginx_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' websoft9-nginxproxymanager)
login_data=$(curl -X POST -H "Content-Type: application/json" -d '{"identity":"admin@example.com","scope":"user", "secret":"changeme"}' http://$nginx_ip:81/api/tokens)
#token=$(echo $login_data | grep -Po '(?<="token":")[^"]*')
token=$(echo $login_data | jq -r '.token')
while [ -z "$token" ]; do
sleep 5
login_data=$(curl -X POST -H "Content-Type: application/json" -d '{"identity":"admin@example.com","scope":"user", "secret":"changeme"}' http://$nginx_ip:81/api/tokens)
token=$(echo $login_data | jq -r '.token')
done
echo "Nginx token:"$token
new_password=$(docker run --name pwgen backplane/pwgen 15)!
docker rm -f pwgen
echo "Nginx init password:" $new_password >> /usr/password.txt
curl -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"email": "help@websoft9.com", "nickname": "admin", "is_disabled": false, "roles": ["admin"]}' http://$nginx_ip:81/api/users/1
curl -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d '{"type":"password","current":"changeme","secret":"'$new_password'"}' http://$nginx_ip:81/api/users/1/auth
sleep 3
curl "http://$appmanage_ip:5000/AppUpdateUser?user_name=help@websoft9.com&password=$new_password"
echo "edit password success ..."
while [ ! -d "/var/lib/docker/volumes/w9nginxproxymanager_nginx_data/_data/nginx/proxy_host" ]; do
sleep 1
done
cp /data/apps/w9services/w9nginxproxymanager/initproxy.conf /var/lib/docker/volumes/w9nginxproxymanager_nginx_data/_data/nginx/proxy_host
echo $public_ip
sudo sed -i "s/domain.com/$public_ip/g" /var/lib/docker/volumes/w9nginxproxymanager_nginx_data/_data/nginx/proxy_host/initproxy.conf
sudo docker restart websoft9-nginxproxymanager
sudo docker cp websoft9-appmanage:/usr/src/app/db/database.sqlite /usr
}
EditMenu(){
echo "Start to Edit Cockpit Menu ..."
# uninstall plugins
rm -rf /usr/share/cockpit/apps /usr/share/cockpit/selinux /usr/share/cockpit/kdump /usr/share/cockpit/sosreport /usr/share/cockpit/packagekit
cp -r /data/apps/websoft9/cockpit/menu_override/* /etc/cockpit
echo "---------------------------------- Install success! When installation completed, you can access it by: http://Internet IP:9000 and using Linux user for login to install a app by websoft9's appstore. -------------------------------------------------------"
}
CheckEnvironment
InstallTools
InstallDocker
InstallCockpit
InstallPlugins
StartAppMng
StartPortainer
InstallNginx
EditMenu

View file

@ -1,46 +0,0 @@
function pipInstall() {
requirementsFile=$1
declare -a mirrors=(
https://pypi.org
https://pypi.tuna.tsinghua.edu.cn/simple/
https://pypi.mirrors.ustc.edu.cn/simple/
https://mirrors.aliyun.com/pypi/simple/
https://pypi.hustunique.com/
https://pypi.sdutlinux.org/
https://pypi.douban.com/simple/
https://repo.huaweicloud.com/repository/pypi/simple/
)
time=-1
fastMirror=""
for url in "${mirrors[@]}"; do
SPEED_DOWNLOAD=$(curl --location --range 0-102400 --max-time 8 --silent --write-out %{speed_download} --output /dev/null "${url}")
tempReult=$(echo "${SPEED_DOWNLOAD} ${time}" | awk '{if ($1 > $2) print 1; else print 0}')
if [ "${tempReult}" -ne 0 ]; then
time=${SPEED_DOWNLOAD}
fastMirror=${url}
fi
done
echo "choose the url: ${fastMirror}"
pip install -r ${requirementsFile} -i ${fastMirror}
}
function retry() {
local retries=$1
shift
local count=0
until "$@"; do
exit=$?
wait=$((2 ** $count))
count=$(($count + 1))
if [ $count -lt $retries ]; then
echo "Retry $count/$retries exited $exit, retrying in $wait seconds..."
sleep $wait
else
echo "Retry $count/$retries exited $exit, no more retries left."
return $exit
fi
done
return 0
}
retry 3 pipInstall requirement.txt

View file

@ -1,33 +0,0 @@
#!/bin/bash
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
clear
# Check if user is root
[ $(id -u) != "0" ] && { echo "Error: You must be root to run this script, please use 'sudo su -' command to change root"; exit 1; }
version(){
echo "version: 0.1"
echo "updated date: 2019-12-30"
}
Show_Help(){
version
echo "Usage: $0 command ...[parameters]...
--help, -h Show this help message
--version, -v Show version info
"
}
echo "Pre-installation is starting, please wait for 1-3 minutes..."
if command -v yum > /dev/null; then
sudo yum install -y epel-release 1>/dev/null 2>&1
sudo yum install yum-utils git python python3 -y 1>/dev/null 2>&1
fi
if command -v apt > /dev/null; then
sudo apt-get install git python python3 git -y 1>/dev/null 2>&1
sudo apt install software-properties-common -y 1>/dev/null 2>&1
fi
sudo echo "Pre-installation has beend completed"

View file

@ -1,323 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function error_exit {
echo "$1" 1>&2
exit 1
}
trap 'error_exit "Please push issue to: https://github.com/Websoft9/websoft9/issues"' ERR
urls="https://w9artifact.blob.core.windows.net/release/websoft9"
CheckEnv(){
echo "------------------ Welcome to update websoft9's appstore, it will take 1-3 minutes -----------------"
if [ $(id -u) != "0" ]; then
echo "Please change to root or 'sudo su' to up system privileges, and reinstall the script again ."
exit 1
fi
}
compare_versions() {
local old_version="$1"
local new_version="$2"
IFS='.' read -ra old_parts <<< "$old_version"
IFS='.' read -ra new_parts <<< "$new_version"
for i in "${!old_parts[@]}"; do
if [[ ${old_parts[i]} -lt ${new_parts[i]} ]]; then
return 0
elif [[ ${old_parts[i]} -gt ${new_parts[i]} ]]; then
return 1
fi
done
return 1
}
UpdateDocker(){
echo "Parpare to update Docker to latest ..."
if command -v apt > /dev/null;then
sudo apt -y install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif command -v dnf > /dev/null;then
sudo dnf update -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif command -v yum > /dev/null;then
sudo yum update -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
fi
}
UpdateWebsoft9(){
echo "Update websoft9 ..."
if [ ! -f /data/apps/websoft9/version.json ]; then
old_version="0.0.0"
else
old_version=$(cat /data/apps/websoft9/version.json | jq .VERSION | tr -d '"')
fi
release_version=$(curl $urls/version.json | jq .VERSION | tr -d '"')
compare_versions $old_version $release_version
if [[ $? -eq 0 ]]; then
echo "start to update websoft9..."
cd /data/apps && rm -rf websoft9
wget $urls/websoft9-latest.zip
unzip websoft9-latest.zip
rm -rf websoft9-latest.zip
else
echo "websoft9 is not need to update"
fi
}
UpdatePlugins(){
echo "Check plugins if have update ..."
# update appstore
if [ -f "/usr/share/cockpit/appstore/appstore.json" ]; then
old_appstore_version=$(cat /usr/share/cockpit/appstore/appstore.json | jq .Version | tr -d '"')
else
old_appstore_version="0.0.0"
fi
new_appstore_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .APPSTORE | tr -d '"')
# update settings
if [ -f "/usr/share/cockpit/settings/settings.json" ]; then
old_settings_version=$(cat /usr/share/cockpit/settings/settings.json | jq .Version | tr -d '"')
else
old_settings_version="0.0.0"
fi
new_settings_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .SETTINGS | tr -d '"')
# update myapps
if [ -f "/usr/share/cockpit/myapps/myapps.json" ]; then
old_myapps_version=$(cat /usr/share/cockpit/myapps/myapps.json | jq .Version | tr -d '"')
else
old_myapps_version="0.0.0"
fi
new_myapps_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .MYAPPS | tr -d '"')
## update container
if [ -f "/usr/share/cockpit/container/portainer.json" ]; then
old_container_version=$(cat /usr/share/cockpit/container/portainer.json | jq .Version | tr -d '"')
else
old_container_version="0.0.0"
fi
new_container_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .PORTAINER | tr -d '"')
## update nginx
if [ -f "/usr/share/cockpit/nginx/nginx.json" ]; then
old_nginx_version=$(cat /usr/share/cockpit/nginx/nginx.json | jq .Version | tr -d '"')
else
old_nginx_version="0.0.0"
fi
new_nginx_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .NGINX | tr -d '"')
## update navigator
if [ -f "/usr/share/cockpit/navigator/navigator.json" ]; then
old_navigator_version=$(cat /usr/share/cockpit/navigator/navigator.json | jq .Version | tr -d '"')
else
old_navigator_version="0.0.0"
fi
new_navigator_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .NAVIGATOR | tr -d '"')
## update library
if [ -f "/data/library/library.json" ]; then
old_library_version=$(cat /data/library/library.json | jq .Version | tr -d '"')
else
old_library_version="0.0.0"
fi
new_library_version=$(cat /data/apps/websoft9/version.json | jq .PLUGINS |jq .LIBRARY | tr -d '"')
if [ "$old_appstore_version" = "$new_appstore_version" ] && [ "$old_settings_version" = "$new_settings_version" ] && [ "$old_myapps_version" = "$new_myapp_version" ] && [ "$old_container_version" = "$new_container_version" ] && [ "$old_nginx_version" \< "$new_nginx_version" ]; then
echo "appstore all plugins is latest"
else
compare_versions $old_appstore_version $new_appstore_version
if [[ $? -eq 0 ]]; then
echo "appstore plugin need to update"
cd /usr/share/cockpit
wget $urls/plugin/appstore/appstore-$new_appstore_version.zip
rm -rf appstore
unzip appstore-$new_appstore_version.zip
rm -f appstore-$new_appstore_version.zip
else
echo "appstore is not need to update"
fi
compare_versions $old_navigator_version $new_navigator_version
if [[ $? -eq 0 ]]; then
echo "navigator plugin need to update"
cd /usr/share/cockpit
wget $urls/plugin/navigator/navigator-$new_navigator_version.zip
rm -rf navigator
unzip navigator-$navigator_version.zip
rm -f navigator-$navigator_version.zip
else
echo "navigator is not need to update"
fi
compare_versions $old_settings_version $new_settings_version
if [[ $? -eq 0 ]]; then
echo "settings plugin need to update"
cd /usr/share/cockpit
wget $urls/plugin/settings/settings-$new_settings_version.zip
rm -rf settings
unzip settings-$new_settings_version.zip
rm -f settings-$new_settings_version.zip
else
echo "settings is not need to update"
fi
compare_versions $old_myapps_version $new_myapps_version
if [[ $? -eq 0 ]]; then
echo "start to update myapps..."
cd /usr/share/cockpit
wget $urls/plugin/myapps/myapps-$new_myapps_version.zip
rm -rf myapps
unzip myapps-$new_myapps_version.zip
rm -f myapps-$new_myapps_version.zip
else
echo "myapps is not need to update"
fi
compare_versions $old_container_version $new_container_version
if [[ $? -eq 0 ]]; then
echo "start to update portainer..."
cd /usr/share/cockpit
wget $urls/plugin/portainer/portainer-$new_container_version.zip
rm -rf container
unzip portainer-$new_container_version.zip
rm -f portainer-$new_container_version.zip
else
echo "portainer is not need to update"
fi
compare_versions $old_nginx_version $new_nginx_version
if [[ $? -eq 0 ]]; then
echo "start to update nginx..."
cd /usr/share/cockpit
wget $urls/plugin/nginx/nginx-$new_nginx_version.zip
rm -rf nginx
unzip nginx-$new_nginx_version.zip
rm -f nginx-$new_nginx_version.zip
else
echo "nginx is not need to update"
fi
compare_versions $old_library_version $new_library_version
if [[ $? -eq 0 ]]; then
echo "start to update library..."
cd /data
wget $urls/plugin/library/library-$new_library_version.zip
rm -rf library
unzip library-$new_library_version.zip
rm -f library-$new_library_version.zip
else
echo "library is not need to update"
fi
fi
}
UpdateServices(){
echo "Check services if have update ..."
old_appmanage=$(cat /data/apps/w9services/w9appmanage/.env |grep APP_VERSION |cut -d= -f2)
new_appmanage=$(cat /data/apps/websoft9/docker/w9appmanage/.env |grep APP_VERSION |cut -d= -f2)
compare_versions $old_appmanage $new_appmanage
if [[ $? -eq 0 ]]; then
echo "start to update w9appmanage..."
rm -f /data/apps/w9services/w9appmanage/.env && cp /data/apps/websoft9/docker/w9appmanage/.env /data/apps/w9services/w9appmanage/.env
rm -f /data/apps/w9services/w9appmanage/docker-compose.yml && cp /data/apps/websoft9/docker/w9appmanage/docker-compose.yml /data/apps/w9services/w9appmanage/docker-compose.yml
cd /data/apps/w9services/w9appmanage && sudo docker compose down && sudo docker compose pull && sudo docker compose up -d
else
echo "appmanage is not need to update"
fi
old_redis=$(cat /data/apps/w9services/w9redis/.env |grep APP_VERSION |cut -d= -f2)
new_redis=$(cat /data/apps/websoft9/docker/w9redis/.env |grep APP_VERSION |cut -d= -f2)
compare_versions $old_redis $new_redis
if [[ $? -eq 0 ]]; then
echo "start to update w9redis..."
rm -f /data/apps/w9services/w9redis/.env && cp /data/apps/websoft9/docker/w9redis/.env /data/apps/w9services/w9redis/.env
rm -f /data/apps/w9services/w9redis/docker-compose.yml && cp /data/apps/websoft9/docker/w9redis/docker-compose.yml /data/apps/w9services/w9redis/docker-compose.yml
cd /data/apps/w9services/w9redis && sudo docker compose down && sudo docker compose pull && sudo docker compose up -d
else
echo "redis is not need to update"
fi
old_portainer=$(cat /data/apps/w9services/w9portainer/.env |grep APP_VERSION |cut -d= -f2)
new_portainer=$(cat /data/apps/websoft9/docker/w9portainer/.env |grep APP_VERSION |cut -d= -f2)
compare_versions $old_portainer $new_portainer
if [[ $? -eq 0 ]]; then
echo "start to update w9portainer..."
rm -f /data/apps/w9services/w9portainer/.env && cp /data/apps/websoft9/docker/w9portainer/.env /data/apps/w9services/w9portainer/.env
rm -f /data/apps/w9services/w9portainer/docker-compose.yml && cp /data/apps/websoft9/docker/w9portainer/docker-compose.yml /data/apps/w9services/w9portainer/docker-compose.yml
cd /data/apps/w9services/w9portainer && sudo docker compose down && sudo docker compose pull && sudo docker compose up -d
else
echo "w9portainer is not need to update"
fi
old_nginx=$(cat /data/apps/w9services/w9nginxproxymanager/.env |grep APP_VERSION |cut -d= -f2)
new_nginx=$(cat /data/apps/websoft9/docker/w9nginxproxymanager/.env |grep APP_VERSION |cut -d= -f2)
compare_versions $old_nginx $new_nginx
if [[ $? -eq 0 ]]; then
echo "start to update w9nginx..."
rm -f /data/apps/w9services/w9nginxproxymanager/.env && cp /data/apps/websoft9/docker/w9nginxproxymanager/.env /data/apps/w9services/w9nginxproxymanager/.env
rm -f /data/apps/w9services/w9nginxproxymanager/docker-compose.yml && cp /data/apps/websoft9/docker/w9nginxproxymanager/docker-compose.yml /data/apps/w9services/w9nginxproxymanager/docker-compose.yml
cd /data/apps/w9services/w9nginxproxymanager && sudo docker compose down && sudo docker compose pull && sudo docker compose up -d
else
echo "w9nginx is not need to update"
fi
}
EditMenu(){
echo "Start to Edit Cockpit Menu ..."
# uninstall plugins
rm -rf /usr/share/cockpit/apps /usr/share/cockpit/selinux /usr/share/cockpit/kdump /usr/share/cockpit/sosreport /usr/share/cockpit/packagekit
cp -r /data/apps/websoft9/cockpit/menu_override/* /etc/cockpit
}
UpdateCockpit(){
echo "Parpare to update Cockpit to latest ..."
if command -v apt > /dev/null;then
current_version=$(dpkg-query --showformat='${Version}' --show cockpit | cut -c 1-3)
available_version=$(apt-cache policy cockpit | grep Candidate | awk '{print $2}' | cut -c 1-3)
elif command -v yum > /dev/null;then
current_version=$(rpm -q --queryformat '%{VERSION}' cockpit | cut -c 1-3)
available_version=$(yum list available cockpit --showduplicates | awk '/cockpit/ {print $2}' | sort -V | tail -n 1 | cut -c 1-3)
fi
if [ "$current_version" \< "$available_version" ]; then
echo "There is newer version on cockpit."
pkcon refresh
pkcon get-updates
pkcon update -y 'cockpit' 'cockpit-bridge' 'cockpit-packagekit' 'cockpit-storaged' 'cockpit-system' 'cockpit-ws'
EditMenu
sudo sed -i 's/ListenStream=9090/ListenStream=9000/' /lib/systemd/system/cockpit.socket
sudo systemctl daemon-reload
sudo systemctl restart cockpit.socket
echo "cockpit update finished."
else
echo "cockpit is latest, not need to upadate."
fi
}
CheckEnv
UpdateDocker
UpdateWebsoft9
UpdatePlugins
UpdateServices
UpdateCockpit

View file

@ -1,119 +0,0 @@
#!/bin/bash
## This script is used for download zip files to a target directory
## apphub dockerfile is depends on this script
# Command-line options
# ==========================================================
#
# --channel <release|dev>
# Use the --channel option to install a release(production) or dev distribution. default is release, for example:
#
# $ sudo bash install.sh --channel release
#
# --package_name
# Use the --package_name option to define a zip file, for example:
#
# $ sudo bash install.sh --package_name media.zip
#
# --sync_to
# Use the sync_to option to define the target directory which zip file will unzip, for example:
#
# $ sudo bash install.sh --sync_to "/websoft9/media"
channel="release"
while [[ $# -gt 0 ]]; do
case $1 in
--channel)
channel="$2"
shift 2
;;
--package_name)
package_name="$2"
shift 2
;;
--sync_to)
sync_to="$2"
shift 2
;;
*)
shift
;;
esac
done
if [ -z "$package_name" ] || [ -z "$sync_to" ]; then
echo "Parameter package_name and sync_to is necessary"
exit 1
fi
# Define the artifact URL as a global variable
artifact_url="https://w9artifact.blob.core.windows.net/$channel/websoft9/plugin"
upgrade_zip() {
# Create the full URL by appending the package name to the artifact URL
local plugin_name=${package_name%%-*}
local url="$artifact_url/$plugin_name/$package_name"
# Initialize download attempts
local attempts=0
local max_attempts=2
# Download the package using wget
while [ $attempts -lt $max_attempts ]; do
rm -f "/tmp/$package_name"
wget --timeout=120 --no-clobber "$url" -O "/tmp/$package_name"
# Check if the download was successful
if [ $? -eq 0 ]; then
break
fi
attempts=$((attempts+1))
echo "Download attempt $attempts failed. Retrying in 5 seconds..."
sleep 5
done
# If the download still failed after max attempts, report an error and exit
if [ $attempts -eq $max_attempts ]; then
echo "Download failed for package: $package_name after $max_attempts attempts."
return 1
fi
# Unzip the downloaded package
unzip "/tmp/$package_name" -d "/tmp"
# Check if the unzip was successful
if [ $? -ne 0 ]; then
echo "Unzip failed for package: $package_name"
return 1
fi
# Get the name of the package without the .zip extension for syncing
local package_directory="${package_name%.zip}"
package_directory="${package_directory%%-*}"
if [ "$unzipped_folder" != "/tmp/$package_directory/" ]; then
mv "$unzipped_folder" "/tmp/$package_directory"
else
echo "The unzipped folder has the same name as the target folder."
fi
# Sync the unzipped package to the desired location
rsync -av "/tmp/$package_directory/" "$sync_to"
# Check if the sync was successful
if [ $? -ne 0 ]; then
echo "Sync failed for package: $package_name"
return 1
fi
echo "Successfully downloaded, unzipped, and synced package: $package_name"
# Remove the downloaded .zip file and the unzipped directory
rm -f "/tmp/$package_name"
rm -rf "/tmp/$package_directory"
return 0
}
upgrade_zip

View file

@ -1,22 +0,0 @@
# Systemd
This is the Websoft9 system service that run some proxy services on the host machine for Websoft9 to solve the problem that the API cannot handle.
- Copy credentials from one other containers to apphub container
## Test it
```
export install_path="/data/websoft9/source"
sudo cp -r $install_path/systemd/script/* "$systemd_path"
sudo cp -f "$install_path/systemd/websoft9.service" /lib/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable websoft9.service
sudo systemctl start websoft9
```
## Develop it
* [systemd.exec — Execution environment configuration](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
* [systemd.unit — Unit configuration](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)
* [systemd.service — Service unit configuration](https://www.freedesktop.org/software/systemd/man/systemd.service.html)

View file

@ -1,67 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
cockpit_port="9000"
container_name="websoft9-apphub"
volume_name="websoft9_apphub_config"
check_ports() {
local ports=("$@")
for port in "${ports[@]}"; do
echo "Check port: $port"
if ss -tuln | grep ":$port " >/dev/null && ! systemctl status cockpit.socket | grep "$port" >/dev/null; then
echo "Port $port is in use, can not set this port to config.ini"
return 0
fi
done
echo "All ports are available"
return 1
}
# get volume from container
function get_volume_path() {
local container_name="$1"
local volume_name="$2"
local mounts=$(docker inspect -f '{{ json .Mounts }}' "$container_name" | jq -r '.[] | select(.Name == "'$volume_name'") | .Source')
echo "$mounts"
}
volume_path=$(get_volume_path "$container_name" "$volume_name")
config_path="$volume_path/config.ini"
cockpit_service_path="/lib/systemd/system/cockpit.socket"
FILES="$cockpit_service_path $config_path"
# 监控文件发生变动时需要做的事情
on_change() {
set +e
cockpit_port=$(docker exec -i websoft9-apphub apphub getconfig --section cockpit --key port)
listen_stream=$(grep -Po 'ListenStream=\K[0-9]*' /lib/systemd/system/cockpit.socket)
if [ "$cockpit_port" != "$listen_stream" ]; then
check_ports "$cockpit_port"
if [ $? -eq 0 ]; then
sudo docker exec -i websoft9-apphub apphub setconfig --section cockpit --key port --value "$listen_stream"
else
ex -s -c "g/ListenStream=${listen_stream}/s//ListenStream=${cockpit_port}/" -c wq "$cockpit_service_path"
systemctl daemon-reload
systemctl restart cockpit.socket 2> /dev/null
systemctl restart cockpit || exit 1
set_Firewalld
fi
fi
set -e
}
set_Firewalld(){
echo "Set cockpit service to Firewalld..."
sed -i "s/port=\"[0-9]*\"/port=\"$cockpit_port\"/g" /etc/firewalld/services/cockpit.xml 2>/dev/nul
sed -i "s/port=\"[0-9]*\"/port=\"$cockpit_port\"/g" /usr/lib/firewalld/services/cockpit.xml 2>/dev/nul
firewall-cmd --reload 2>/dev/nul
}
# monitor /lib/systemd/system/cockpit.socket and config.ini, make sure config.ini port is the same with cockpit.socket
inotifywait -e modify -m $FILES | while read PATH EVENT FILE; do
echo "Set cockpit port by config.ini..."
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
on_change
done

View file

@ -1,72 +0,0 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
deployment_username="admin"
credentials=("/data/gitea/credential" "/data/credential" "/data/credential")
containers=("websoft9-git" "websoft9-deployment" "websoft9-proxy")
sections=("gitea" "portainer" "nginx_proxy_manager")
max_retries=20
declare -A usernames passwords
set +e # Ignore errors
for i in ${!containers[@]}; do
container=${containers[$i]}
credential_path=${credentials[$i]}
echo "Processing $container"
success=false
counter=0
while [[ $success == false && $counter -lt $max_retries ]]; do
temp_file=$(mktemp)
if docker cp $container:$credential_path $temp_file; then
# Check if temp_file is JSON format
if jq -e . >/dev/null 2>&1 <<< "$(cat "$temp_file")"; then
# If it is JSON format, use it directly
username=$(jq -r '.username' $temp_file)
password=$(jq -r '.password' $temp_file)
if [[ -n $username && -n $password ]]; then
usernames[$container]=$username
passwords[$container]=$password
success=true
fi
else
# If it is not JSON format, get the content and convert it to JSON
content=$(cat "$temp_file")
username="$deployment_username"
password="$content"
if [[ -n $username && -n $password ]]; then
usernames[$container]=$username
passwords[$container]=$password
success=true
fi
fi
fi
rm -f "$temp_file"
if [[ $success == false ]]; then
echo "Waiting for 3 seconds before next attempt..."
sleep 3
fi
((counter++))
done
if [[ $success == true ]]; then
echo "Successfully retrieved credentials for $container"
else
echo "Failed to retrieve credentials for $container after $max_retries attempts"
fi
done
set -e # Stop ignoring errors
length=${#containers[@]}
for ((i=0; i<$length; i++)); do
container=${containers[$i]}
section=${sections[$i]}
if [[ -n ${passwords[$container]} ]]; then
echo "$container start to set password"
docker exec -i websoft9-apphub apphub setconfig --section $section --key user_pwd --value ${passwords[$container]}
else
echo "Password for $container is not set or empty. Skipping..."
fi
done

View file

@ -1,4 +0,0 @@
#!/bin/bash
/bin/bash send_credentials.sh
/bin/bash crontab.sh

View file

@ -1,18 +0,0 @@
[Unit]
Description=Websoft9 Linux AppStore
Requires=network.target docker.service
After=network.target docker.service
[Service]
WorkingDirectory=/opt/websoft9/systemd
ExecStart=/bin/bash /opt/websoft9/systemd/start_up.sh
Restart=on-failure
Type=simple
NotifyAccess=all
StandardOutput=journal
StandardError=journal
User=root
Group=root
[Install]
WantedBy=multi-user.target

View file

@ -1,51 +0,0 @@
{
"version": "0.8.30-rc1",
"plugins": {
"portainer": "0.0.8",
"nginx": "0.0.6",
"gitea": "0.0.3",
"myapps": "0.1.0",
"appstore": "0.0.9",
"settings": "0.0.6",
"navigator": "0.5.10"
},
"OS": {
"Fedora": [
"38",
"37",
"35"
],
"RedHat": [
"9",
"8",
"7"
],
"CentOS": [
"8",
"7"
],
"Oracle Linux": [
"9",
"8",
"7"
],
"Rocky": [
"9",
"8"
],
"CentOS Stream": [
"9",
"8"
],
"Debian": [
"12",
"11",
"10"
],
"Ubuntu": [
"23.04",
"22.04",
"20.04"
]
}
}