mirror of
https://github.com/kunkundi/crossdesk-server.git
synced 2026-03-24 15:29:55 +08:00
[refactor] use fixed paths for data storage and add automatic certificate generation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,4 +8,5 @@ cert/
|
||||
|
||||
# VSCode cache
|
||||
.vscode
|
||||
.vs
|
||||
continuous-desk-server.code-workspace
|
||||
42
README.md
42
README.md
@@ -43,4 +43,44 @@ xmake b -vy crossdesk_server
|
||||
cd docker
|
||||
|
||||
sudo docker build -t image-name .
|
||||
```
|
||||
```
|
||||
|
||||
## 运行容器
|
||||
|
||||
### 基础启动(数据存储在容器内)
|
||||
|
||||
启动命令示例:
|
||||
```bash
|
||||
docker run -d \
|
||||
--name crossdesk_server \
|
||||
--network host \
|
||||
-e EXTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||
-e INTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||
-e CROSSDESK_SERVER_PORT=xxxx \
|
||||
-e COTURN_PORT=xxxx \
|
||||
-e MIN_PORT=xxxxx \
|
||||
-e MAX_PORT=xxxxx \
|
||||
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||
crossdesk/crossdesk-server:v1.1.2
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 证书文件会在首次启动时自动生成在容器内的 `/var/lib/crossdesk/certs`
|
||||
- 数据库文件会自动创建在容器内的 `/var/lib/crossdesk/db/crossdesk-server.db`
|
||||
- 日志文件会自动创建在容器内的 `/var/log/crossdesk/`
|
||||
- **注意**:如果不挂载 volume,容器删除后数据会丢失
|
||||
- `-v /var/lib/crossdesk:/var/lib/crossdesk`:持久化数据库和证书文件到宿主机
|
||||
- `-v /var/log/crossdesk:/var/log/crossdesk`:持久化日志文件到宿主机
|
||||
- 容器删除后,数据仍保留在宿主机上
|
||||
- **目录自动创建**:如果宿主机没有这些目录,Docker 会自动创建,容器内的代码也会自动创建子目录
|
||||
- **权限注意(重要)**:如果 Docker 自动创建的目录权限不足(属于 root),容器内用户无法写入,会导致:
|
||||
- 证书生成失败,容器启动脚本会报错退出
|
||||
- 数据库目录创建失败,程序会抛出异常并崩溃
|
||||
- 日志目录创建失败,日志文件无法写入(但程序可能继续运行)
|
||||
|
||||
解决方案:在启动容器前手动设置权限:
|
||||
```bash
|
||||
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||
```
|
||||
42
README_EN.md
42
README_EN.md
@@ -41,4 +41,44 @@ For more information, please refer to the [official Xmake documentation](https:/
|
||||
cd docker
|
||||
|
||||
sudo docker build -t image-name .
|
||||
```
|
||||
```
|
||||
|
||||
## Run Container
|
||||
|
||||
### Basic Startup (Data stored in container)
|
||||
|
||||
Example startup command:
|
||||
```bash
|
||||
docker run -d \
|
||||
--name crossdesk_server \
|
||||
--network host \
|
||||
-e EXTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||
-e INTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||
-e CROSSDESK_SERVER_PORT=xxxx \
|
||||
-e COTURN_PORT=xxxx \
|
||||
-e MIN_PORT=xxxxx \
|
||||
-e MAX_PORT=xxxxx \
|
||||
-v /var/lib/crossdesk:/var/lib/crossdesk \
|
||||
-v /var/log/crossdesk:/var/log/crossdesk \
|
||||
crossdesk/crossdesk-server:v1.1.2
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
- Certificate files will be automatically generated on first startup in `/var/lib/crossdesk/certs` (inside container)
|
||||
- Database file will be automatically created at `/var/lib/crossdesk/db/crossdesk-server.db` (inside container)
|
||||
- Log files will be automatically created in `/var/log/crossdesk/` (inside container)
|
||||
- **Note**: Data will be lost if container is removed without volume mounts
|
||||
- `-v /var/lib/crossdesk:/var/lib/crossdesk`: Persist database and certificate files to host
|
||||
- `-v /var/log/crossdesk:/var/log/crossdesk`: Persist log files to host
|
||||
- Data will remain on host even if container is removed
|
||||
- **Auto directory creation**: If these directories don't exist on host, Docker will create them automatically, and the container code will also create subdirectories
|
||||
- **Permission note (Important)**: If Docker auto-created directories have insufficient permissions (owned by root), the container user cannot write, which will cause:
|
||||
- Certificate generation failure, container startup script will exit with error
|
||||
- Database directory creation failure, program will throw exception and crash
|
||||
- Log directory creation failure, log files cannot be written (but program may continue running)
|
||||
|
||||
Solution: Set permissions manually before starting container:
|
||||
```bash
|
||||
sudo mkdir -p /var/lib/crossdesk /var/log/crossdesk
|
||||
sudo chown -R $(id -u):$(id -g) /var/lib/crossdesk /var/log/crossdesk
|
||||
```
|
||||
@@ -29,8 +29,9 @@ RUN mkdir -p /opt/turnserver && \
|
||||
|
||||
|
||||
COPY docker/start.sh /start.sh
|
||||
COPY docker/generate_certs.sh /docker/generate_certs.sh
|
||||
COPY --from=builder /output/crossdesk_server /crossdesk-server/crossdesk_server
|
||||
|
||||
RUN chmod +x /start.sh /crossdesk-server/crossdesk_server
|
||||
RUN chmod +x /start.sh /docker/generate_certs.sh /crossdesk-server/crossdesk_server
|
||||
|
||||
ENTRYPOINT ["/start.sh"]
|
||||
|
||||
82
docker/generate_certs.sh
Normal file
82
docker/generate_certs.sh
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# 检查参数
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||
echo "Usage: $0 <SERVER_IP> [OUTPUT_DIR]"
|
||||
echo " SERVER_IP: IP address for the certificate"
|
||||
echo " OUTPUT_DIR: Directory to save certificates (default: current directory)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER_IP="$1"
|
||||
OUTPUT_DIR="${2:-$(pwd)}"
|
||||
|
||||
# 确保输出目录存在
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# 切换到输出目录
|
||||
cd "$OUTPUT_DIR"
|
||||
|
||||
# 文件名(使用完整路径)
|
||||
ROOT_KEY="$OUTPUT_DIR/crossdesk.cn_root.key"
|
||||
ROOT_CERT="$OUTPUT_DIR/crossdesk.cn_root.crt"
|
||||
SERVER_KEY="$OUTPUT_DIR/crossdesk.cn.key"
|
||||
SERVER_CSR="$OUTPUT_DIR/crossdesk.cn.csr"
|
||||
SERVER_CERT="$OUTPUT_DIR/crossdesk.cn_bundle.crt"
|
||||
FULLCHAIN_CERT="$OUTPUT_DIR/crossdesk.cn_fullchain.crt"
|
||||
SAN_CONF="$OUTPUT_DIR/san.cnf"
|
||||
|
||||
# 证书主题
|
||||
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
||||
|
||||
# 1. 生成根证书
|
||||
echo "Generating root private key..."
|
||||
openssl genrsa -out "$ROOT_KEY" 4096
|
||||
|
||||
echo "Generating self-signed root certificate..."
|
||||
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
||||
|
||||
# 2. 生成服务器私钥
|
||||
echo "Generating server private key..."
|
||||
openssl genrsa -out "$SERVER_KEY" 2048
|
||||
|
||||
# 3. 生成服务器 CSR
|
||||
echo "Generating server CSR..."
|
||||
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
||||
|
||||
# 4. 生成临时 OpenSSL 配置文件,加入 SAN
|
||||
cat > "$SAN_CONF" <<EOL
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = req_ext
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = CN
|
||||
ST = Zhejiang
|
||||
L = Hangzhou
|
||||
O = CrossDesk
|
||||
OU = CrossDesk
|
||||
CN = $SERVER_IP
|
||||
|
||||
[ req_ext ]
|
||||
subjectAltName = IP:$SERVER_IP
|
||||
EOL
|
||||
|
||||
# 5. 用根证书签发服务器证书(包含 SAN)
|
||||
echo "Signing server certificate with root certificate..."
|
||||
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
||||
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
||||
|
||||
# 6. 生成完整链证书
|
||||
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
||||
|
||||
# 7. 清理中间文件
|
||||
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "$FULLCHAIN_CERT"
|
||||
|
||||
echo "Generation complete. Certificates saved to: $OUTPUT_DIR"
|
||||
echo " Client root certificate: $ROOT_CERT"
|
||||
echo " Server private key: $SERVER_KEY"
|
||||
echo " Server certificate: $SERVER_CERT"
|
||||
@@ -28,6 +28,30 @@ if [ -z "$MIN_PORT" ] || [ -z "$MAX_PORT" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check and generate certificates if needed
|
||||
CERT_DIR="/var/lib/crossdesk/certs"
|
||||
CERT_KEY="$CERT_DIR/crossdesk.cn.key"
|
||||
CERT_BUNDLE="$CERT_DIR/crossdesk.cn_bundle.crt"
|
||||
CERT_ROOT="$CERT_DIR/crossdesk.cn_root.crt"
|
||||
|
||||
if [ ! -f "$CERT_KEY" ] || [ ! -f "$CERT_BUNDLE" ] || [ ! -f "$CERT_ROOT" ]; then
|
||||
echo "Certificate files not found, generating certificates..."
|
||||
mkdir -p "$CERT_DIR"
|
||||
|
||||
# Run generate_certs.sh with EXTERNAL_IP and output directory
|
||||
bash /docker/generate_certs.sh "$EXTERNAL_IP" "$CERT_DIR"
|
||||
|
||||
# Verify certificates were generated
|
||||
if [ ! -f "$CERT_KEY" ] || [ ! -f "$CERT_BUNDLE" ] || [ ! -f "$CERT_ROOT" ]; then
|
||||
echo "Error: Failed to generate certificate files"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Certificates generated successfully"
|
||||
else
|
||||
echo "Certificate files found, skipping generation"
|
||||
fi
|
||||
|
||||
# generate coturn configuration file
|
||||
mkdir -p /etc/coturn
|
||||
cat > "$CONF_FILE" <<EOF
|
||||
@@ -44,7 +68,7 @@ user=crossdesk:crossdeskpw
|
||||
realm=crossdesk
|
||||
cert=${CERT_FILE}
|
||||
pkey=${PKEY_FILE}
|
||||
log-file=/crossdesk-server/logs/turn.log
|
||||
log-file=/var/log/crossdesk/turn.log
|
||||
no-cli
|
||||
EOF
|
||||
|
||||
@@ -56,8 +80,8 @@ exec turnserver -c "$CONF_FILE" &
|
||||
|
||||
# start crossdesk-server as main foreground process
|
||||
echo "Starting crossdesk-server..."
|
||||
./crossdesk-server/crossdesk_server \
|
||||
${CROSSDESK_SERVER_PORT} \
|
||||
/crossdesk-server/certs/ \
|
||||
/crossdesk-server/db/crossdesk_server.db \
|
||||
/crossdesk-server/logs
|
||||
# 程序现在使用固定目录:
|
||||
# - 数据库和配置文件:/var/lib/crossdesk
|
||||
# - 日志文件:/var/log/crossdesk
|
||||
# 只需传递端口参数
|
||||
./crossdesk-server/crossdesk_server ${CROSSDESK_SERVER_PORT}
|
||||
18
src/main.cpp
18
src/main.cpp
@@ -14,26 +14,14 @@
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string port = "9090";
|
||||
std::string log_dir = "./logs";
|
||||
std::string certs_dir = "./cert";
|
||||
std::string db_path = "devices.db";
|
||||
std::string log_dir = "/var/log/crossdesk";
|
||||
std::string certs_dir = "/var/lib/crossdesk/certs";
|
||||
std::string db_path = "/var/lib/crossdesk/db/crossdesk-server.db";
|
||||
|
||||
if (argc > 1) {
|
||||
port = argv[1];
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
certs_dir = argv[2];
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
db_path = argv[3];
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
log_dir = argv[4];
|
||||
}
|
||||
|
||||
InitLogger(log_dir);
|
||||
|
||||
SignalServer s(std::stoi(port), certs_dir, db_path);
|
||||
|
||||
Reference in New Issue
Block a user